diff --git a/.github/jactionlint.yaml b/.github/jactionlint.yaml index 11d6ccd219..11746e71e1 100644 --- a/.github/jactionlint.yaml +++ b/.github/jactionlint.yaml @@ -1,4 +1,7 @@ -require-commit-hash: true # actions, reusable workflows and docker:// must be pinned to a full SHA / @sha256 digest +rules: + missing-timeout: off + concurrency-limits: off + unpinned-uses: error # actions, reusable workflows and docker:// must be pinned to a full SHA / @sha256 digest self-hosted-runner: labels: - arm-runner @@ -8,3 +11,8 @@ self-hosted-runner: - blacksmith-8vcpu-ubuntu-2404 - blacksmith-8vcpu-windows-2025 - blacksmith-32vcpu-ubuntu-2404 +paths: + # Other projects' repositories, pulled in as git submodules. CI never checks them out. + ".repos/**": + ignore: + - ".*" diff --git a/.github/scripts/ai-review/resolve.ts b/.github/scripts/ai-review/resolve.ts index 0cfaafc071..74984e22ed 100644 --- a/.github/scripts/ai-review/resolve.ts +++ b/.github/scripts/ai-review/resolve.ts @@ -12,7 +12,7 @@ * * `resolveDecision` is the pure orchestration function (I/O injected) a test * can drive without the network; `main()` wires up the real GitHub I/O, - * writes `should_run`/`pr_number`/`head_ref`/`trigger` to `$GITHUB_OUTPUT`, + * writes `should_run`/`pr_number`/`head_sha`/`trigger` to `$GITHUB_OUTPUT`, * and surfaces the skip reason (if any) in `$GITHUB_STEP_SUMMARY`. * * Run in CI as: `bun .github/scripts/ai-review/resolve.ts`. @@ -374,7 +374,6 @@ function writeOutputs(result: ResolveResult, prNumber: number): void { const entries: Record = { should_run: String(result.shouldRun), pr_number: String(prNumber), - head_ref: `refs/pull/${prNumber}/head`, head_sha: result.headSha ?? "", trigger: result.trigger, }; diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml index 582874175f..56bbfb6926 100644 --- a/.github/workflows/ai-review.yml +++ b/.github/workflows/ai-review.yml @@ -16,6 +16,10 @@ on: description: "PR number to review" required: true type: string + # A `/ai-review` comment on a pull request starts a review. The resolve job checks who + # commented, and the one job that can write to the pull request runs code from the default + # branch only, never from the pull request. + # jactionlint ignore=dangerous-triggers issue_comment: types: - created @@ -65,7 +69,6 @@ jobs: outputs: should_run: ${{ steps.resolve.outputs.should_run }} pr_number: ${{ steps.resolve.outputs.pr_number }} - head_ref: ${{ steps.resolve.outputs.head_ref }} # Every job reviews this commit, so a push during the run is never reported as reviewed. head_sha: ${{ steps.resolve.outputs.head_sha }} trigger: ${{ steps.resolve.outputs.trigger }} @@ -161,7 +164,10 @@ jobs: # behavior mid-rollout. Installed from the trusted checkout with npm config isolation so a # PR-supplied `.npmrc` in the untrusted `pr` checkout can never redirect this install to a # hostile registry. - # 2.1.280 is the first release that accepts claude-opus-5-5. + # 2.1.280 is the first release that accepts claude-opus-5-5. The CLI is installed on its + # own, not through the repository's lockfile, so nothing in the pull request's checkout + # can change what gets installed. + # jactionlint ignore=adhoc-packages - name: Install Claude Code CLI working-directory: trusted run: | @@ -544,7 +550,7 @@ jobs: steps: # Security-critical: this is the only job with write permission, so it must only ever # execute trusted base-branch code — never the PR head. Checking out `develop` explicitly - # (never `needs.resolve.outputs.head_ref`) keeps a malicious PR from smuggling a script + # (never the PR's own ref) keeps a malicious PR from smuggling a script # change into the one job that can write back to the PR. (For `pull_request` events GitHub # runs the workflow file from the PR's own ref; acceptable since the auto path only admits # same-repo PRs, whose authors hold write access anyway, and fork PRs run with a read-only diff --git a/.github/workflows/apply-release-notes.yml b/.github/workflows/apply-release-notes.yml index 753028e5cc..831ec66cf7 100644 --- a/.github/workflows/apply-release-notes.yml +++ b/.github/workflows/apply-release-notes.yml @@ -27,13 +27,14 @@ jobs: outputs: authorized: ${{ steps.check.outputs.authorized }} steps: - # App token needs org membership read, repo write to edit the release, and PR write to - # comment and close. + # The token reads the approver's team membership and comments on the pull request. - id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: client-id: ${{ vars.GH_APP_CLIENT_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + permission-members: read + permission-pull-requests: write - name: Authorize approver against supabase/cli team id: check @@ -66,11 +67,16 @@ jobs: contents: write pull-requests: write steps: + # The token edits the GitHub release, deletes the branch, and comments on and closes the + # pull request. The script below runs from the pull request's own checkout, so the token + # must not be able to change workflow files. - id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: client-id: ${{ vars.GH_APP_CLIENT_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write # Checkout the PR head so reviewer edits made before approval are captured; # apply-release-notes.ts reads from the working tree. diff --git a/.github/workflows/bot-pr-auto-merge.yml b/.github/workflows/bot-pr-auto-merge.yml index 6745993567..3d1006bfda 100644 --- a/.github/workflows/bot-pr-auto-merge.yml +++ b/.github/workflows/bot-pr-auto-merge.yml @@ -1,6 +1,9 @@ name: Bot PR auto-merge on: + # Only this event lets the job use the auto-approve environment's secret. The job never + # checks out or runs code from the pull request. + # jactionlint ignore=dangerous-triggers pull_request_target: types: [opened, reopened, synchronize, ready_for_review] branches: [develop] @@ -14,6 +17,9 @@ jobs: # Other apps (coding agents, CI vendors) also open PRs here and still need a maintainer. # Release-notes PRs are published by a maintainer approval and must never merge. Branch sync # PRs land by fast-forward on a maintainer approval, never by a squash. + # The first condition checks who opened the pull request. The second checks who caused this + # event, so a person pushing to a bot's pull request does not get it approved. + # jactionlint ignore=bot-conditions if: >- contains(fromJSON('["dependabot[bot]", "supabase-cli-releaser[bot]"]'), github.event.pull_request.user.login) && contains(fromJSON('["dependabot[bot]", "supabase-cli-releaser[bot]"]'), github.event.sender.login) && diff --git a/.github/workflows/cli-go-ci.yml b/.github/workflows/cli-go-ci.yml index 2ae77eac79..97ee9dc277 100644 --- a/.github/workflows/cli-go-ci.yml +++ b/.github/workflows/cli-go-ci.yml @@ -31,6 +31,7 @@ jobs: # Required by: internal/utils/credentials/keyring_test.go - uses: t1m0thyj/unlock-keyring@cbcf205c879ebd86add70bab3a6abfcce59a5cae # v1.2.0 - run: | + set -o pipefail pkgs=$(go list ./pkg/... | grep -Ev 'pkg/api' | paste -sd ',' -) go tool gotestsum -- -race -v -count=1 ./... \ -coverpkg="./cmd/...,./internal/...,${pkgs}" -coverprofile=coverage.out diff --git a/.github/workflows/cli-go-mirror-image.yml b/.github/workflows/cli-go-mirror-image.yml index 889ecaf9ae..284118c964 100644 --- a/.github/workflows/cli-go-mirror-image.yml +++ b/.github/workflows/cli-go-mirror-image.yml @@ -19,14 +19,15 @@ on: required: true type: string -permissions: - contents: read - packages: write - id-token: write +permissions: {} jobs: mirror: runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write steps: - id: strip env: diff --git a/.github/workflows/cli-go-pg-prove.yml b/.github/workflows/cli-go-pg-prove.yml index 6a4414ee3f..3c836bbdce 100644 --- a/.github/workflows/cli-go-pg-prove.yml +++ b/.github/workflows/cli-go-pg-prove.yml @@ -38,8 +38,6 @@ jobs: arch: arm64 runs-on: ${{ matrix.runner }} timeout-minutes: 180 - outputs: - image_digest: ${{ steps.build.outputs.digest }} steps: - run: docker context create builders - uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 diff --git a/.github/workflows/cli-go-publish-migra.yml b/.github/workflows/cli-go-publish-migra.yml index c3b0a56333..7e37210911 100644 --- a/.github/workflows/cli-go-publish-migra.yml +++ b/.github/workflows/cli-go-publish-migra.yml @@ -38,8 +38,6 @@ jobs: arch: arm64 runs-on: ${{ matrix.runner }} timeout-minutes: 180 - outputs: - image_digest: ${{ steps.build.outputs.digest }} steps: - run: docker context create builders - uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 diff --git a/.github/workflows/cli-go-tag-pkg.yml b/.github/workflows/cli-go-tag-pkg.yml index 9185ad5771..3563c4077b 100644 --- a/.github/workflows/cli-go-tag-pkg.yml +++ b/.github/workflows/cli-go-tag-pkg.yml @@ -8,13 +8,14 @@ on: required: true type: string -permissions: - contents: write +permissions: {} jobs: tag: name: Create pkg tag runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/close-stale-issues-and-prs.yml b/.github/workflows/close-stale-issues-and-prs.yml index e6ecb519a3..fb43466983 100644 --- a/.github/workflows/close-stale-issues-and-prs.yml +++ b/.github/workflows/close-stale-issues-and-prs.yml @@ -22,10 +22,7 @@ on: type: string default: "security,pinned,do-not-close,keep-open,do not merge" -permissions: - contents: read - issues: write - pull-requests: write +permissions: {} concurrency: group: close-stale-issues-and-prs @@ -35,6 +32,10 @@ jobs: close-stale: runs-on: ubuntu-latest timeout-minutes: 30 + permissions: + contents: read + issues: write + pull-requests: write steps: - name: Close stale issues and PRs uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 diff --git a/.github/workflows/contribution-gate.yml b/.github/workflows/contribution-gate.yml index af7cab6ac5..341bea8b29 100644 --- a/.github/workflows/contribution-gate.yml +++ b/.github/workflows/contribution-gate.yml @@ -1,6 +1,9 @@ name: Contribution Gate on: + # The gate has to comment on pull requests from forks, which only this event's token can do. + # It checks out the base branch, never the pull request. + # jactionlint ignore=dangerous-triggers pull_request_target: types: - opened @@ -16,10 +19,7 @@ on: type: boolean default: false -permissions: - pull-requests: write - issues: read - contents: read +permissions: {} concurrency: # Per-PR for pull_request_target; unique per run for manual sweeps (which @@ -31,6 +31,10 @@ jobs: gate-single: name: Contribution Gate runs-on: ubuntu-latest + permissions: + pull-requests: write + issues: read + contents: read # Exempt maintainers/collaborators and bots. External contributors are gated. if: > github.event_name == 'pull_request_target' && @@ -42,6 +46,8 @@ jobs: # Checks out the base repo (default for pull_request_target), so the gate # runs trusted code from the base branch, never the untrusted PR head. - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: ".bun-version" @@ -58,11 +64,17 @@ jobs: gate-all: name: Contribution Gate (all open PRs) runs-on: ubuntu-latest + permissions: + pull-requests: write + issues: read + contents: read if: github.event_name == 'workflow_dispatch' steps: # Base-branch checkout only — the sweep makes API calls and never runs # any PR's code. - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: ".bun-version" diff --git a/.github/workflows/dispatch-cli-e2e-ci.yml b/.github/workflows/dispatch-cli-e2e-ci.yml index ed5aa0f22a..0fc4f0a9f9 100644 --- a/.github/workflows/dispatch-cli-e2e-ci.yml +++ b/.github/workflows/dispatch-cli-e2e-ci.yml @@ -37,6 +37,7 @@ jobs: CLI_SHA: ${{ github.event.pull_request.head.sha }} PR_NUMBER: ${{ github.event.pull_request.number }} run: | + set -o pipefail echo "Dispatching cli-e2e-ci live run for PR #${PR_NUMBER} @ ${CLI_SHA}" # Build the nested client_payload with jq — `gh api -f` sends a flat # body and would not nest `client_payload.*` correctly. diff --git a/.github/workflows/fill-sticky-disks.yml b/.github/workflows/fill-sticky-disks.yml index 2440f388d1..0e9da129b8 100644 --- a/.github/workflows/fill-sticky-disks.yml +++ b/.github/workflows/fill-sticky-disks.yml @@ -72,6 +72,7 @@ jobs: - name: Pull stack package images run: | + set -o pipefail pnpm --silent --filter @supabase/stack prepare:test-artifacts --images | xargs --max-procs 4 --max-args 1 docker pull --quiet @@ -79,6 +80,7 @@ jobs: - name: Prune Docker before saving its image disk if: always() run: | + set -o pipefail docker ps --all --quiet | xargs --no-run-if-empty docker rm --force docker system prune --force docker volume prune --all --force diff --git a/.github/workflows/live-e2e-notify.yml b/.github/workflows/live-e2e-notify.yml index 66edf219b7..441f130f15 100644 --- a/.github/workflows/live-e2e-notify.yml +++ b/.github/workflows/live-e2e-notify.yml @@ -1,6 +1,8 @@ name: Live E2E Notifications on: + # The job only reads whether the run passed. It runs nothing the run produced. + # jactionlint ignore=dangerous-triggers workflow_run: workflows: [Live E2E, Release] types: [completed] diff --git a/.github/workflows/propose-release-notes.yml b/.github/workflows/propose-release-notes.yml index 04f9359071..3ba3ad70fc 100644 --- a/.github/workflows/propose-release-notes.yml +++ b/.github/workflows/propose-release-notes.yml @@ -61,6 +61,9 @@ jobs: with: client-id: ${{ vars.GH_APP_CLIENT_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + permission-contents: write + permission-issues: read + permission-pull-requests: write - uses: useblacksmith/checkout@6fd481652155169ed4d2f25ebaf97464f685175f # v1 with: diff --git a/.github/workflows/release-config.yml b/.github/workflows/release-config.yml index 2b79a91614..87e6d5e57b 100644 --- a/.github/workflows/release-config.yml +++ b/.github/workflows/release-config.yml @@ -355,19 +355,24 @@ jobs: fi echo "dist-tag ${NPM_TAG} -> ${VERSION} confirmed." + # The CLI's install scripts and setup-cli resolve releases/latest/download/..., so a + # config release must never become the repo's "latest" release. Re-runs skip this step + # when the release already exists. - name: Create GitHub Release - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 - with: - token: ${{ github.token }} - tag_name: config-v${{ needs.plan.outputs.version }} - name: "@supabase/config v${{ needs.plan.outputs.version }}" - body_path: ${{ runner.temp }}/config-release/config-release-notes.md - draft: false - prerelease: false - # The CLI's install scripts and setup-cli resolve - # releases/latest/download/..., so a config release must never - # become the repo's "latest" release. - make_latest: "false" + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + tag="config-v${VERSION}" + if gh release view "${tag}" >/dev/null 2>&1; then + echo "Release ${tag} already exists; skipping." + else + gh release create "${tag}" \ + --verify-tag \ + --title "@supabase/config v${VERSION}" \ + --notes-file "${RUNNER_TEMP}/config-release/config-release-notes.md" \ + --latest=false + fi # Pages Slack the moment a real run arms the config-release approval gate. Runs in parallel # with the publish job's `waiting` state (needs only `plan`), so the ping and the pending diff --git a/.github/workflows/release-shared.yml b/.github/workflows/release-shared.yml index 1f0e0a13c9..119ee14e84 100644 --- a/.github/workflows/release-shared.yml +++ b/.github/workflows/release-shared.yml @@ -307,6 +307,8 @@ jobs: with: dependency-firewall-token: ${{ secrets.DF_FIREWALL_TOKEN }} + # The cache key includes this run's id, so only this run's build job can have written it. + # jactionlint ignore=cache-poisoning - name: Restore build artifacts cache uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -377,13 +379,23 @@ jobs: done # Created empty; the next step uploads the assets so each one can be retried on its own. + # Re-runs skip this step when the release already exists. - name: Create draft GitHub Release - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 - with: - tag_name: v${{ inputs.version }} - name: v${{ inputs.version }} - draft: true - prerelease: ${{ inputs.prerelease }} + env: + GH_TOKEN: ${{ github.token }} + PRERELEASE: ${{ inputs.prerelease }} + run: | + set -euo pipefail + tag="v${VERSION}" + if gh release view "${tag}" >/dev/null 2>&1; then + echo "Release ${tag} already exists; skipping." + else + args=(--draft --verify-tag --title "${tag}") + if [[ "$PRERELEASE" == true ]]; then + args+=(--prerelease) + fi + gh release create "${tag}" "${args[@]}" + fi # One asset at a time with per-asset retries; see apps/cli/scripts/upload-release-assets.ts. - name: Upload release assets diff --git a/.github/workflows/release-smoke-test.yml b/.github/workflows/release-smoke-test.yml index 27ca8a2ebc..0aa4ff6b17 100644 --- a/.github/workflows/release-smoke-test.yml +++ b/.github/workflows/release-smoke-test.yml @@ -26,17 +26,18 @@ concurrency: group: release-smoke-test-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true -permissions: - # release-shared.yml declares privileged publish jobs. They are gated by - # dry_run here, but GitHub validates nested-workflow permissions at startup. - actions: read - contents: write - id-token: write - pull-requests: write +permissions: {} jobs: smoke: name: Run release smoke tests + # release-shared.yml declares privileged publish jobs. They are gated by + # dry_run here, but GitHub validates nested-workflow permissions at startup. + permissions: + actions: read + contents: write + id-token: write + pull-requests: write # Fork heads are skipped: the shared workflow declares write permissions a # fork pull request token cannot hold, and hotfixes come from this repository. if: | diff --git a/.github/workflows/reopen-stale-issue.yml b/.github/workflows/reopen-stale-issue.yml index dd7572b617..1235ddbefe 100644 --- a/.github/workflows/reopen-stale-issue.yml +++ b/.github/workflows/reopen-stale-issue.yml @@ -1,12 +1,17 @@ name: Reopen stale issue on: + # Anyone who can comment must be able to use /reopen. The script only reads the comment + # text and never runs it. + # jactionlint ignore=dangerous-triggers issue_comment: types: - created permissions: contents: read + # The script reopens the issue, removes a label, and comments. Each needs issues: write. + # jactionlint ignore=excessive-permissions issues: write concurrency: diff --git a/.github/workflows/setup-cli-smoke-test.yml b/.github/workflows/setup-cli-smoke-test.yml index dc9aeb1ba9..1bcc37242b 100644 --- a/.github/workflows/setup-cli-smoke-test.yml +++ b/.github/workflows/setup-cli-smoke-test.yml @@ -84,6 +84,9 @@ jobs: # `node:20-alpine` ships a musl-linked Node, required for JavaScript-based actions to launch # here — the runner's mounted glibc Node won't execute inside an Alpine container. container: + # The image is pinned by tag, not by digest. It only hosts the installer smoke test, and + # nothing would update a digest here automatically. + # jactionlint ignore=unpinned-images image: node:20-alpine env: VERSION: ${{ inputs.version }} diff --git a/.github/workflows/sync-branches.yml b/.github/workflows/sync-branches.yml index 5eefcfbae3..5ab7797833 100644 --- a/.github/workflows/sync-branches.yml +++ b/.github/workflows/sync-branches.yml @@ -1,6 +1,9 @@ name: Sync branches on: + # Starts when the Release workflow finishes. Every script runs from the default-branch + # checkout, never from the merged tree. + # jactionlint ignore=dangerous-triggers workflow_run: workflows: - Release @@ -120,7 +123,8 @@ jobs: persist-credentials: false - name: Load Claude model - run: echo "CLAUDE_MODEL=$(jq -r .claude.opus trusted/.github/ai-models.json)" >> "$GITHUB_ENV" + id: model + run: echo "model=$(jq -r .claude.opus trusted/.github/ai-models.json)" >> "$GITHUB_OUTPUT" - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -134,6 +138,7 @@ jobs: bun-version-file: trusted/.bun-version # Same pinned release and isolated npm config as the AI review workflow. + # jactionlint ignore=adhoc-packages - name: Install Claude Code CLI run: | npm install -g \ @@ -146,6 +151,7 @@ jobs: working-directory: trusted env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + CLAUDE_MODEL: ${{ steps.model.outputs.model }} WORK_DIR: ${{ github.workspace }}/work run: | git -C "$WORK_DIR" config user.name "github-actions[bot]" @@ -246,7 +252,8 @@ jobs: persist-credentials: false - name: Load Claude model - run: echo "CLAUDE_MODEL=$(jq -r .claude.opus trusted/.github/ai-models.json)" >> "$GITHUB_ENV" + id: model + run: echo "model=$(jq -r .claude.opus trusted/.github/ai-models.json)" >> "$GITHUB_OUTPUT" - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -260,6 +267,7 @@ jobs: bun-version-file: trusted/.bun-version # Same pinned release and isolated npm config as the AI review workflow. + # jactionlint ignore=adhoc-packages - name: Install Claude Code CLI run: | npm install -g \ @@ -276,6 +284,7 @@ jobs: working-directory: trusted env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + CLAUDE_MODEL: ${{ steps.model.outputs.model }} WORK_DIR: ${{ github.workspace }}/work run: | git -C "$WORK_DIR" fetch --no-tags "$OUTPUT_DIR/sync.bundle" HEAD diff --git a/.github/workflows/sync-repair.yml b/.github/workflows/sync-repair.yml index a9002a4085..dea2a6ec30 100644 --- a/.github/workflows/sync-repair.yml +++ b/.github/workflows/sync-repair.yml @@ -3,6 +3,9 @@ name: Sync repair # Once CI and the AI review finish on a Claude-resolved sync/develop-into-next pull request, lets Claude fix what # the merge broke and answer the review. See apps/cli/docs/release-process.md#claude-resolved-develop-into-next. on: + # Starts when the sync branch's checks finish. Every script runs from the default-branch + # checkout, never from the sync branch. + # jactionlint ignore=dangerous-triggers workflow_run: workflows: - CI @@ -55,7 +58,8 @@ jobs: persist-credentials: false - name: Load Claude model - run: echo "CLAUDE_MODEL=$(jq -r .claude.opus trusted/.github/ai-models.json)" >> "$GITHUB_ENV" + id: model + run: echo "model=$(jq -r .claude.opus trusted/.github/ai-models.json)" >> "$GITHUB_OUTPUT" - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: @@ -77,6 +81,7 @@ jobs: persist-credentials: false # Same pinned release and isolated npm config as the AI review workflow. + # jactionlint ignore=adhoc-packages - name: Install Claude Code CLI if: steps.collect.outputs.action == 'repair' run: | @@ -91,6 +96,7 @@ jobs: working-directory: trusted env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + CLAUDE_MODEL: ${{ steps.model.outputs.model }} WORK_DIR: ${{ github.workspace }}/work HEAD_SHA: ${{ steps.collect.outputs.head }} run: | @@ -119,6 +125,7 @@ jobs: HEAD_SHA: ${{ steps.collect.outputs.head }} CHANGED: ${{ steps.repair.outputs.changed }} run: | + set -o pipefail if [ "$(gh pr view "$PR" --repo "$GITHUB_REPOSITORY" --json headRefOid -q .headRefOid)" != "$HEAD_SHA" ]; then echo "::notice::The sync branch moved since the checks settled; skipping." exit 0 diff --git a/.github/workflows/verify-install-channels.yml b/.github/workflows/verify-install-channels.yml index 26bfa0d90b..66402ba70e 100644 --- a/.github/workflows/verify-install-channels.yml +++ b/.github/workflows/verify-install-channels.yml @@ -222,6 +222,9 @@ jobs: env: VERSION: ${{ inputs.version }} steps: + # This job exists to run the published install script. That script checks the tarball it + # downloads against the release's checksums.txt before using it. + # jactionlint ignore=unverified-download - name: Install via the published install script shell: bash run: | diff --git a/mise.lock b/mise.lock index 83da59b571..4b64eed8ee 100644 --- a/mise.lock +++ b/mise.lock @@ -172,74 +172,74 @@ url_api = "https://api.github.com/repos/golangci/golangci-lint/releases/assets/4 provenance = "github-attestations" [[tools.jactionlint]] -version = "1.8.2" +version = "2.3.0" backend = "github:jdx/jactionlint" -specifiers = ["1"] +specifiers = ["2"] [tools.jactionlint."platforms.linux-arm64"] -checksum = "sha256:7d618749dbddd762a14bd491ea97bc4f6599626f830a11edc6c6522ead8bcd05" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338576" +checksum = "sha256:deea7744e5769e1e5cc8c9898a838f80a941ec68476d9f2814a61474d5652dac" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210370" provenance = "github-attestations" [tools.jactionlint."platforms.linux-arm64-musl"] -checksum = "sha256:7d618749dbddd762a14bd491ea97bc4f6599626f830a11edc6c6522ead8bcd05" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338576" +checksum = "sha256:deea7744e5769e1e5cc8c9898a838f80a941ec68476d9f2814a61474d5652dac" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210370" provenance = "github-attestations" [tools.jactionlint."platforms.linux-x64"] -checksum = "sha256:6533bd8047fc012a3f66238d84f65cacdac669da00b9f6cf042c1734c252bc93" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338580" +checksum = "sha256:907e6f6a59e181879f7e6936e19ee2eca1cbc51de134fb85460cfa8d65a71f28" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210498" provenance = "github-attestations" [tools.jactionlint."platforms.linux-x64-baseline"] -checksum = "sha256:6533bd8047fc012a3f66238d84f65cacdac669da00b9f6cf042c1734c252bc93" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338580" +checksum = "sha256:907e6f6a59e181879f7e6936e19ee2eca1cbc51de134fb85460cfa8d65a71f28" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210498" provenance = "github-attestations" [tools.jactionlint."platforms.linux-x64-musl"] -checksum = "sha256:6533bd8047fc012a3f66238d84f65cacdac669da00b9f6cf042c1734c252bc93" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338580" +checksum = "sha256:907e6f6a59e181879f7e6936e19ee2eca1cbc51de134fb85460cfa8d65a71f28" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210498" provenance = "github-attestations" [tools.jactionlint."platforms.linux-x64-musl-baseline"] -checksum = "sha256:6533bd8047fc012a3f66238d84f65cacdac669da00b9f6cf042c1734c252bc93" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338580" +checksum = "sha256:907e6f6a59e181879f7e6936e19ee2eca1cbc51de134fb85460cfa8d65a71f28" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210498" provenance = "github-attestations" [tools.jactionlint."platforms.macos-arm64"] -checksum = "sha256:de9eb05af3cde409dc0b37fe2fd6a21b875a575374e7b26c02d45a7086645c28" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338605" +checksum = "sha256:f96afa36578b21290203ae8df4fa7ac3bf5aba08ed288df28cb0530af7ca6e55" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210452" provenance = "github-attestations" [tools.jactionlint."platforms.macos-x64"] -checksum = "sha256:42790b2565759b7f4a81696fb9034b2060f97f551d2ced54cf722c9de9abe6b2" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_darwin_amd64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338604" +checksum = "sha256:a61006b669ec0ab1266c73e3561eecf839537eb6e8b3b6be766a55ba17fcbe42" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_darwin_amd64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210428" provenance = "github-attestations" [tools.jactionlint."platforms.macos-x64-baseline"] -checksum = "sha256:42790b2565759b7f4a81696fb9034b2060f97f551d2ced54cf722c9de9abe6b2" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_darwin_amd64.tar.gz" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338604" +checksum = "sha256:a61006b669ec0ab1266c73e3561eecf839537eb6e8b3b6be766a55ba17fcbe42" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_darwin_amd64.tar.gz" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210428" provenance = "github-attestations" [tools.jactionlint."platforms.windows-x64"] -checksum = "sha256:fd7be539cd3276d5178f85ef140c1bb52395b1ec1f59b1585050e1be3b0b194b" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_windows_amd64.zip" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338616" +checksum = "sha256:9864d1045bd37fddb2df33bf4d6b45de205c0ce133c52a225928b7ede7d7f3eb" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_windows_amd64.zip" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210534" provenance = "github-attestations" [tools.jactionlint."platforms.windows-x64-baseline"] -checksum = "sha256:fd7be539cd3276d5178f85ef140c1bb52395b1ec1f59b1585050e1be3b0b194b" -url = "https://github.com/jdx/jactionlint/releases/download/v1.8.2/jactionlint_1.8.2_windows_amd64.zip" -url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/611338616" +checksum = "sha256:9864d1045bd37fddb2df33bf4d6b45de205c0ce133c52a225928b7ede7d7f3eb" +url = "https://github.com/jdx/jactionlint/releases/download/v2.3.0/jactionlint_2.3.0_windows_amd64.zip" +url_api = "https://api.github.com/repos/jdx/jactionlint/releases/assets/662210534" provenance = "github-attestations" [[tools.node]] diff --git a/mise.toml b/mise.toml index 5596a9bb89..a197d4db4c 100644 --- a/mise.toml +++ b/mise.toml @@ -3,7 +3,7 @@ min_version = '2026.10.17' [tools] go = "1.26.5" golangci-lint = "2.12.2" -jactionlint = "1" +jactionlint = "2" shellcheck = "0.11.0" [settings]