diff --git a/.github/workflows/nix-vendor-hash.yml b/.github/workflows/nix-vendor-hash.yml deleted file mode 100644 index 361edaf..0000000 --- a/.github/workflows/nix-vendor-hash.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Nix vendorHash - -# Keep dependency-bump PRs green automatically: when go.mod / go.sum change, the -# buildGoModule vendorHash in nix/package.nix goes stale and the Nix build -# fails. This recomputes it and commits the fix back to the PR branch, so -# Dependabot (and human) dependency PRs fix their own vendorHash. -# -# Pushing back requires a token with write access. We reuse -# REPOSITORY_FULL_ACCESS_GITHUB_TOKEN (already used by release.yml); using a PAT -# rather than the default GITHUB_TOKEN also makes the follow-up commit -# re-trigger the Nix build workflow. -# -# For this to work on Dependabot PRs, that token must ALSO be registered as a -# Dependabot secret (Settings -> Secrets and variables -> Dependabot), because -# GitHub withholds Actions secrets from Dependabot-triggered pull_request runs. -on: - pull_request: - paths: - - "go.mod" - - "go.sum" - - "nix/package.nix" - - ".github/workflows/nix-vendor-hash.yml" - workflow_dispatch: - -permissions: - contents: read - -jobs: - update-vendor-hash: - # Only same-repo branches (Dependabot branches live in this repo); we can't - # push to a fork's branch. - if: github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest - steps: - - name: Checkout PR branch - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - ref: ${{ github.event.pull_request.head.ref }} - token: ${{ secrets.REPOSITORY_FULL_ACCESS_GITHUB_TOKEN }} - - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 - - - name: Recompute vendorHash - run: ./nix/update-vendor-hash.sh - - - name: Commit and push if changed - run: | - if git diff --quiet -- nix/package.nix; then - echo "vendorHash already correct; nothing to do." - exit 0 - fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add nix/package.nix - git commit -m "chore(nix): update vendorHash for dependency change" - git push origin "HEAD:${{ github.event.pull_request.head.ref }}" diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index cd0439f..0e48b6e 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -2,6 +2,19 @@ name: Nix # Keeps the Nix packaging green: builds the flake package and runs the flake # checks (the Home Manager module's assertion and seed-merge unit tests). +# +# vendorHash upkeep: a dependency bump changes go.mod / go.sum, which makes the +# buildGoModule vendorHash in nix/package.nix go stale and the build fail. We do +# NOT auto-fix that on the PR branch: doing so would require a write-scoped PAT +# in a job that runs untrusted branch code (a poisoned dependency could then +# exfiltrate the token). Instead: +# - the `nix` build is skipped on Dependabot PRs (github.actor guard), so the +# bump can merge without a red check; and +# - the `update-vendor-hash` job recomputes and commits the fix on push to +# main, where the code is trusted and the PAT is safe to use. +# Cost: main's nix build is briefly red between the merge and the fix commit. +# Releases are cut manually (workflow_dispatch -> tag), so that window can't +# silently ship a broken package. on: push: branches: @@ -25,8 +38,16 @@ on: - ".github/workflows/nix.yml" workflow_dispatch: +permissions: + contents: read + jobs: nix: + # Skip on Dependabot PRs: the vendorHash is stale until the bump merges and + # `update-vendor-hash` heals it on main. A job-level skip reports a `skipped` + # conclusion, which branch protection treats as passing. Human dependency + # changes still get the full build. + if: github.actor != 'dependabot[bot]' runs-on: ubuntu-latest steps: - name: Checkout repository @@ -40,3 +61,38 @@ jobs: - name: Run flake checks run: nix flake check --print-build-logs + + update-vendor-hash: + # On merge to main, self-heal a stale vendorHash left by a dependency bump + # (Dependabot PRs skip the build above, so the fix lands here). This runs on + # trusted main code, so holding a write-scoped PAT is safe. + # + # We reuse REPOSITORY_FULL_ACCESS_GITHUB_TOKEN (also used by the release + # workflows); using a PAT rather than the default GITHUB_TOKEN also lets the + # follow-up commit re-trigger this workflow, which then finds the hash + # correct and no-ops. + if: github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - name: Checkout main + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + token: ${{ secrets.REPOSITORY_FULL_ACCESS_GITHUB_TOKEN }} + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 + + - name: Recompute vendorHash + run: ./nix/update-vendor-hash.sh + + - name: Commit and push if changed + run: | + if git diff --quiet -- nix/package.nix; then + echo "vendorHash already correct; nothing to do." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add nix/package.nix + git commit -m "chore(nix): update vendorHash for dependency change" + git push origin "HEAD:main" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc28148..f97644b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,7 +47,8 @@ When `go.mod`/`go.sum` change, refresh it: make update-vendor-hash ``` -On pull requests this is automated: the [`Nix vendorHash`](.github/workflows/nix-vendor-hash.yml) workflow recomputes the hash and commits the fix back to the branch, so Dependabot and other dependency PRs heal themselves. +On `main` this is automated: the `update-vendor-hash` job in the [`Nix`](.github/workflows/nix.yml) workflow recomputes the hash and commits the fix after a dependency bump merges. +The Nix build is skipped on Dependabot PRs (the hash is stale until the bump lands), so those PRs merge without a red check and `main` self-heals right after; human dependency PRs should refresh the hash locally with `make update-vendor-hash` before pushing. Note that CI builds the PR's *merge commit*, so a dependency bump landing on `main` can make an unrelated open PR's Nix build go red until its branch is updated. ### Binary distribution (NUR) diff --git a/nix/update-vendor-hash.sh b/nix/update-vendor-hash.sh index 7187fc6..e8c37a3 100755 --- a/nix/update-vendor-hash.sh +++ b/nix/update-vendor-hash.sh @@ -5,8 +5,9 @@ # correct the file is left unchanged. # # Run from the repository root (or via `make update-vendor-hash`). Requires Nix -# with flakes enabled. Used by .github/workflows/nix-vendor-hash.yml to keep -# dependency-bump PRs (Dependabot or human) green automatically. +# with flakes enabled. Used by the `update-vendor-hash` job in +# .github/workflows/nix.yml to self-heal a stale vendorHash on push to main +# after a dependency bump merges. set -euo pipefail pkg="nix/package.nix"