From c3170a1c131ae35b1aa6c4d413b3e22e91f4e59e Mon Sep 17 00:00:00 2001 From: JacobPEvans <20714140+JacobPEvans-personal@users.noreply.github.com> Date: Mon, 1 Jun 2026 20:58:53 -0400 Subject: [PATCH] feat(workflows): add reusable update-flake-input workflow Reusable workflow_call target for bumping a single flake input and opening a squash-mergeable PR. Consumers (nix-ai, nix-darwin) call it via repository_dispatch when an upstream dryvist repo releases. - Inputs: input_name (required), runner_label (optional, RunsOn default) - Uses app token for push + PR creation; DeterminateSystems Nix action - No-op if flake.lock is unchanged; auto-merge enabled on created PR - input_name is channelled through env vars in run: steps to prevent shell injection from attacker-controlled client_payload fields Assisted-by: Claude:claude-opus-4-8 --- .github/workflows/_update-flake-input.yml | 98 +++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .github/workflows/_update-flake-input.yml diff --git a/.github/workflows/_update-flake-input.yml b/.github/workflows/_update-flake-input.yml new file mode 100644 index 0000000..15c31bd --- /dev/null +++ b/.github/workflows/_update-flake-input.yml @@ -0,0 +1,98 @@ +# Reusable: Update flake input +# Bumps a single flake.lock input in the calling repo and opens a squash- +# mergeable PR. If the input is already at the latest rev, exits cleanly +# with no PR. Called by consumer repos (nix-ai, nix-darwin) via +# repository_dispatch when an upstream dryvist repo cuts a release. +name: _update-flake-input + +on: + workflow_call: + inputs: + input_name: + description: >- + Name of the flake input to update (e.g. "nix-claude-code", "nix-ai"). + Must match an entry in the calling repo's flake.nix inputs block. + type: string + required: true + runner_label: + description: >- + GitHub Actions runner label. Defaults to the RunsOn 2-cpu linux + runner used by the rest of the dryvist automation stack. + type: string + required: false + default: "runs-on=${{ github.run_id }}/runner=2cpu-linux-x64" + secrets: + GH_APP_PRIVATE_KEY: + required: true + +concurrency: + group: update-flake-input-${{ inputs.input_name }}-${{ github.repository }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + update: + name: Bump ${{ inputs.input_name }} + runs-on: ${{ inputs.runner_label }} + environment: automation + timeout-minutes: 20 + permissions: + contents: write + pull-requests: write + steps: + - name: Generate GitHub App Token + id: app-token + uses: actions/create-github-app-token@v3 + with: + client-id: ${{ vars.GH_APP_CLIENT_ID }} + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + + - name: Checkout repository + uses: actions/checkout@v6 + with: + token: ${{ steps.app-token.outputs.token }} + + - name: Install Nix + uses: DeterminateSystems/determinate-nix-action@v3 + + - name: Update flake input + # Use env var — never interpolate inputs directly into run: (injection risk). + env: + INPUT_NAME: ${{ inputs.input_name }} + run: nix flake update "$INPUT_NAME" + + - name: Check for changes + id: diff + run: | + if git diff --quiet flake.lock; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Create Pull Request + if: steps.diff.outputs.changed == 'true' + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ steps.app-token.outputs.token }} + sign-commits: true + branch: chore/bump-${{ inputs.input_name }} + delete-branch: true + commit-message: "chore(deps): bump ${{ inputs.input_name }} flake input" + title: "chore(deps): bump ${{ inputs.input_name }} flake input" + body: | + Automated flake input update triggered by a release in `${{ inputs.input_name }}`. + labels: dependencies + author: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" + + - name: Enable auto-merge + if: steps.diff.outputs.changed == 'true' + # Use env var for the branch name — input_name must not be shell-interpolated. + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + INPUT_NAME: ${{ inputs.input_name }} + run: | + PR=$(gh pr list --head "chore/bump-${INPUT_NAME}" --json number --jq '.[0].number') + [ -n "$PR" ] && gh pr merge "$PR" --auto --squash || true