diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 3d8a1c1e..755588f1 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -18,3 +18,10 @@ On receipt, this workflow fetches the PR's changed files from the DynEarthSol AP See [`CLAUDE.md`](../../CLAUDE.md) for the doc-sync procedure a triage issue is meant to kick off, and for the `workflow_dispatch` testing gotcha (a workflow must be merged to the default branch before it can be dispatched manually, on either side of the pipeline). Can be run manually for testing: `gh workflow run dynearthsol-pr-notify.yml --repo GeoFLAC/des3d -f number=`. + +## `dependabot-auto-merge.yml` +Auto-approves and enables auto-merge for Dependabot PRs that are patch or minor version bumps (major bumps are left for manual review, since they're more likely to need judgment). Uses `dependabot/fetch-metadata` to read the update type, then `gh pr merge --auto`. + +This only *enables* auto-merge — the actual merge is still gated by branch protection on `main`, which requires the `Test deployment` check (the same build `test-deploy.yml` runs) to pass first. A dependency bump that breaks the build (e.g. the js-yaml/gray-matter conflict documented in the `Patch nanoid, undici, and js-yaml security advisories` commit) just sits open instead of merging. + +Depends on repo settings that aren't in this file: Dependabot security updates enabled, "Allow auto-merge" enabled, and a branch protection ruleset on `main` requiring the `Test deployment` check (only that — not "require a pull request before merging", so direct pushes to `main` still work). diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 00000000..3900d9f0 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,37 @@ +name: Dependabot auto-merge + +# Auto-approves and enables auto-merge for Dependabot PRs that are patch or +# minor version bumps. GitHub won't actually merge until the required +# "Test deployment" status check (see branch protection on main) passes, so +# a bump that breaks the build just sits open for manual review instead of +# merging. Major version bumps are left alone regardless of CI outcome. + +on: + pull_request: + branches: [main] + +permissions: + contents: write + pull-requests: write + +jobs: + auto-merge: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Fetch Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Approve and enable auto-merge for patch/minor updates + if: > + steps.metadata.outputs.update-type == 'version-update:semver-patch' || + steps.metadata.outputs.update-type == 'version-update:semver-minor' + run: | + gh pr review --approve "$PR_URL" + gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CLAUDE.md b/CLAUDE.md index 02cb6ffb..8574f89a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,3 +51,9 @@ Merges to DynEarthSol no longer require manually running the `gh pr list` scan a 2. **`.github/workflows/dynearthsol-pr-notify.yml`** (in this repo) receives it, fetches the PR's changed files from the DynEarthSol API, and skips it if every changed file is under `.github/` (CI-only, no doc surface) — note this checks files, not the title, so a `ci:`-titled PR that also touches non-workflow files (e.g. `docker/Dockerfile.cuda`) still gets flagged. Otherwise it opens a GitHub issue here titled `Review DynEarthSol # for doc updates: `. 3. When one of those issues shows up, that's the trigger to run the sync procedure above for that specific PR — start at step 4 with the PR number the issue already gives you. 4. Both workflows can also be run manually via `workflow_dispatch` (`gh workflow run <file> --repo <owner/repo> -f number=<N>` / `-f pr_number=<N>`) for testing. **Gotcha:** `workflow_dispatch` can't be fired on a workflow that exists only on a non-default branch — GitHub only indexes dispatchable workflows from the default branch, so a newly-added or newly-edited workflow must be merged before it can be triggered this way, even with `--ref <branch>` pointing at where the code actually lives. + +## Dependency security updates + +Dependabot alerts on this repo are handled by a mix of GitHub-native automation and manual fixes — see `.github/workflows/README.md` for the full picture. In short: Dependabot security updates + repo auto-merge + a branch protection rule requiring the `Test deployment` check are enabled, and `dependabot-auto-merge.yml` auto-merges patch/minor Dependabot PRs once that check passes. This covers most alerts with no intervention needed. + +What it *won't* catch: alerts on deep transitive dependencies where different consumers in the tree genuinely need different major versions of the same package (a semver-invisible runtime conflict, not something Dependabot can resolve with a single-version bump). The `js-yaml`/`gray-matter` case is the concrete example — `gray-matter` calls the since-removed `yaml.safeLoad`, so it needs to stay on js-yaml 3.x while everything else uses 4.x. Fixing these requires scoped `resolutions` entries in `package.json` using anchored paths (e.g. `"@docusaurus/core/**/gray-matter/js-yaml": "3.15.1"`), not a single bare `"js-yaml"` override — a bare override collapses both tracks onto one version and silently breaks whichever side needed the other major version. If you add a bare resolution key for a package that also has an anchored one, the bare key seems to win over the more specific one in practice (contrary to what Yarn's docs imply about specificity) — don't mix the two for the same package. Alerts with no upstream fix at all (check via `npm view <pkg> versions` / the GHSA advisory's `first_patched_version`) are left open with a note; don't force a downgrade to dodge them without checking whether the vulnerable code path is even reachable here (e.g. `image-size`'s DoS parsers only run at build time against this repo's own trusted images, never untrusted input).