From c2414957e3635c93a3f14994773b5035068aa90b Mon Sep 17 00:00:00 2001 From: Blair Hamilton Date: Wed, 17 Jun 2026 09:26:49 -0400 Subject: [PATCH] fix(actionlint): hardcode refs/heads/main for downstream cross-repo checkout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #21. That PR replaced `github.workflow_sha` with `github.workflow_ref` on the assumption that `workflow_ref` exposes the reusable workflow's own ref to a downstream caller — it doesn't. In a reusable workflow context `workflow_ref` returns the caller's workflow file path, e.g. `pinpredict/trading-reports/.github/workflows/ci.yml@refs/pull/5/merge`, which then fails to resolve against pinpredict/.github with `couldn't find remote ref refs/pull/5/merge`. There is no context variable that exposes the reusable workflow's own ref to the callee. Fall back to convention: per this repo's CLAUDE.md, downstream callers always pin `@main`, so checking out main from a downstream context gives the runner the same action source it already loaded for the workflow itself. Self-CI still works: `github.repository == 'pinpredict/.github'` identifies that case and we use `github.ref` so PR-mode runs see the PR's version of the action. --- .github/workflows/actionlint.yml | 37 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 2766dda..d6c4392 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -70,26 +70,35 @@ jobs: # `uses: ./...` in a reusable workflow resolves against the # caller's checkout, not this repo — so we vendor a copy of - # pinpredict/.github at the exact ref this workflow file came - # from. Earlier revisions used `github.workflow_sha`, which - # actually returns the *caller's* SHA in cross-repo reusable - # calls — fine for self-CI (the caller and this repo are the - # same), broken for every downstream consumer ("not our ref" - # against pinpredict/.github on the caller's head SHA). + # pinpredict/.github and reference the action from there. # - # `github.workflow_ref` shape: - # `//.github/workflows/.yml@` - # Splitting on `@` yields a ref `actions/checkout` resolves - # against pinpredict/.github — `refs/heads/main` for downstream - # callers using `@main`, `refs/pull/N/merge` for self-CI PR - # runs, a SHA when pinned. + # Picking the right ref is the tricky part. Neither + # `github.workflow_sha` nor `github.workflow_ref` exposes the + # reusable workflow's own ref to a downstream caller: + # - `workflow_sha` returns the caller's commit SHA. + # - `workflow_ref` returns the caller's workflow file path, + # e.g. `pinpredict/trading-reports/.github/workflows/ci.yml@refs/pull/5/merge`. + # Both prior attempts (`73a31ca`, `31626de`) failed downstream + # for this reason. + # + # Fall back to convention: per pinpredict/.github's CLAUDE.md, + # downstream callers always pin `@main`, so checking out main + # gets a downstream consumer the same action source the runner + # already loaded for the workflow itself. For self-CI we use + # `github.ref` so that PR-mode runs see the PR's version of the + # action (refs/pull/N/merge), not main's. - name: Resolve workflow ref id: workflow-ref env: - GITHUB_WORKFLOW_REF: ${{ github.workflow_ref }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_REF: ${{ github.ref }} run: | set -euo pipefail - ref="${GITHUB_WORKFLOW_REF#*@}" + if [ "$GITHUB_REPOSITORY" = "pinpredict/.github" ]; then + ref="$GITHUB_REF" + else + ref="refs/heads/main" + fi printf 'ref=%s\n' "$ref" >> "$GITHUB_OUTPUT" - name: Checkout pinpredict/.github at workflow ref