Skip to content

feat(ci): add reusable nix-hash-autofix workflow#153

Closed
JacobPEvans wants to merge 1 commit intomainfrom
feat/nix-hash-autofix
Closed

feat(ci): add reusable nix-hash-autofix workflow#153
JacobPEvans wants to merge 1 commit intomainfrom
feat/nix-hash-autofix

Conversation

@JacobPEvans
Copy link
Copy Markdown
Owner

Summary

New reusable workflow _nix-hash-autofix.yml that automatically fixes Nix package
hashes on Renovate PRs.

Problem

Renovate's regex custom manager can bump version strings in .nix files (via
# renovate: annotations) but cannot update fetchFromGitHub hashes or vendorHash.
This causes every Renovate version bump for Go/Rust packages to break CI.

Example: gh-aw v0.65.4 hash mismatch broke nix-darwin CI (PR #955) when GitHub
regenerated the tarball.

Solution

A reusable workflow that:

  1. Triggers on Renovate PRs (caller filters by bot author)
  2. Runs nix-update --version=skip for specified packages (keeps Renovate's version, fixes hashes)
  3. Pushes a fixup commit if hashes changed

Test plan

  • Verify workflow syntax valid
  • Wire into nix-ai and nix-home CI gates
  • Test with a manual Renovate-like version bump

🤖 Generated with Claude Code

Renovate's regex manager bumps version strings in .nix files but
cannot update fetchFromGitHub hashes or vendorHash. This workflow
runs nix-update with --version=skip on Renovate PRs to fix hashes
and pushes a fixup commit.

Callers pass a list of package attribute names to update. Only runs
on Renovate bot PRs (jacobpevans-github-actions[bot]).

(claude)
Copilot AI review requested due to automatic review settings April 3, 2026 00:23
@gemini-code-assist
Copy link
Copy Markdown

Note

Gemini is unable to generate a summary for this pull request due to the file types involved not being currently supported.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new reusable GitHub Actions workflow to automatically recalculate and commit updated Nix fetch/vendor hashes after Renovate bumps versions in .nix files, reducing CI breakages from stale hashes.

Changes:

  • Introduces reusable workflow _nix-hash-autofix.yml callable via workflow_call
  • Installs Nix and runs nix-update --version=skip for specified flake package attributes
  • Commits and pushes a fixup commit when hash-related diffs are produced

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +54
on:
workflow_call:
inputs:
packages:
description: "Space-separated list of flake package attributes to update (e.g., 'gh-aw git-flow-next')"
required: true
type: string

permissions: {}

concurrency:
group: nix-hash-autofix-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
autofix:
name: Fix Nix Hashes
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.GH_ACTION_JACOBPEVANS_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}

- name: Checkout PR branch
uses: actions/checkout@v6
with:
ref: ${{ github.head_ref }}
token: ${{ steps.app-token.outputs.token }}

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow checks out and runs commands against the PR branch using inherited secrets, but it does not enforce that it’s running in a safe context (e.g., a same-repo pull_request from the expected bot). If a caller accidentally invokes this via pull_request_target or for a fork PR, this would run untrusted code with write-capable credentials. Add an explicit guard (job-level if: or an early step that fails) to require github.event_name == 'pull_request', github.event.pull_request.head.repo.full_name == github.repository, and (optionally) the expected PR author/actor before generating the app token/checkout.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +17
# Usage in ci-gate.yml:
# nix-hash-autofix:
# needs: changes
# if: needs.changes.outputs.nix == 'true' && github.event.pull_request.user.login == 'jacobpevans-github-actions[bot]'
# uses: JacobPEvans/.github/.github/workflows/_nix-hash-autofix.yml@main
# with:
# packages: "gh-aw"
# secrets: inherit
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header "Usage" example indicates secrets: inherit, but the workflow implicitly requires GH_ACTION_JACOBPEVANS_APP_ID and GH_APP_PRIVATE_KEY to exist in the caller repo/org. Please document these required secrets (and what permissions the app needs) in the header, or expose them as explicit workflow_call.secrets entries so callers get a clearer validation/error message.

Copilot uses AI. Check for mistakes.
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.GH_ACTION_JACOBPEVANS_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actions/create-github-app-token is invoked without scoping token permissions. In this repo, _release-please.yml uses permission-contents, permission-pull-requests, etc. to least-privilege the generated token; consider doing the same here (contents: write, pull-requests: read) to reduce blast radius if the token is misused/exposed.

Suggested change
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: read

Copilot uses AI. Check for mistakes.
Comment on lines +63 to +76
for pkg in $PACKAGES; do
echo "::group::Updating $pkg"
# nix-update recalculates src hash and vendorHash
# --version=skip keeps Renovate's version bump, only fixes hashes
if nix run nixpkgs#nix-update -- --flake "$pkg" --version=skip 2>&1; then
echo "Updated $pkg"
else
echo "::warning::Failed to update $pkg (may already be correct)"
fi
echo "::endgroup::"
done
if [ -n "$(git diff --name-only)" ]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update loop converts any nix-update failure into a warning and still exits 0. If nix-update fails due to a real error (evaluation failure, network, etc.), the workflow will report success but won’t fix the hashes, leaving CI broken. Track failures and fail the job when one or more requested packages could not be updated (or at least fail when all updates fail and no diff is produced).

Copilot uses AI. Check for mistakes.
@JacobPEvans
Copy link
Copy Markdown
Owner Author

Closing — switching to simpler approach: daily nix-update + remove Renovate annotations for fetchFromGitHub packages. No new workflow needed.

@JacobPEvans JacobPEvans closed this Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants