News

GitHub Actions Exposes Reusable Workflow Identity: Trace the Checks Behind an AI Pull Request

Compare caller and reusable workflow revisions in a disposable CI fixture, then record the implementation SHA alongside the completed check result.

2026-09-06

Two modular blocks on a glass tray joined by a glowing path, one lit cyan and one amber, standing for a calling workflow and the reusable workflow that defines the job.
Illustration: trace which reusable implementation ran, not only which caller asked for it.

What changed on September 3

GitHub's September 3, 2026 Actions update adds four job context properties for identifying the workflow that defines a running job: job.workflow_ref, job.workflow_sha, job.workflow_repository and job.workflow_file_path. They expose the reference, commit, repository and relative file path of that implementation. For a reusable workflow, this can differ from the caller identity exposed through github.workflow_ref and github.workflow_sha. GitHub says these additions are unavailable on GitHub Enterprise Server.

For an AI-generated pull request, use this distinction to answer a narrow review question: which reusable check implementation actually ran? The fixture below is a proposed reproducible exercise, not an integration test executed for this article. Its output should join a caller revision, a callee revision and a completed check result. That record helps you inspect the checking code; it does not establish that the proposed application change is safe.

Keep three revisions separate

Use the GitHub context reference to distinguish the event commit (github.sha), caller workflow commit (github.workflow_sha) and current job's implementation commit (job.workflow_sha). The event commit depends on the triggering event. Do not label it “PR head” by assumption. Record the pull request head separately when evaluating a real pull request, then document which revision the test checkout actually used.

Imagine a caller in example/application that invokes a validator in example/ci-fixture. An unchanged caller can still ask for a moving callee reference. Your review record should make that relationship visible before anyone interprets a green badge as approval. Keep the broader permission review in the zero-trust architecture guide for AI agents beside this identity exercise.

Create a disposable pair of workflows

Create two test repositories under your control, with no production secrets or deployment jobs. Put the following file at .github/workflows/probe.yml in the callee repository and commit it on a dedicated branch named identity-demo. Copy its full commit SHA into your notes as revision A. The reusable workflow guide documents workflow_call, job-level calls, and references using a branch, tag or commit SHA. The branch in this exercise is deliberately mutable so you can observe a change.

name: Identity probe
on: workflow_call
permissions:
  contents: read
jobs:
  probe:
    runs-on: ubuntu-latest
    steps:
      - name: Record selected identity fields
        env:
          CALLER_REF: ${{ github.workflow_ref }}
          CALLER_SHA: ${{ github.workflow_sha }}
          EVENT_SHA: ${{ github.sha }}
          CALLEE_REF: ${{ job.workflow_ref }}
          CALLEE_SHA: ${{ job.workflow_sha }}
          CALLEE_REPO: ${{ job.workflow_repository }}
          CALLEE_PATH: ${{ job.workflow_file_path }}
          RUN_ID: ${{ github.run_id }}
          RUN_ATTEMPT: ${{ github.run_attempt }}
          CHECK_ID: ${{ job.check_run_id }}
        shell: python
        run: |
          import json, os
          keys = ("CALLER_REF", "CALLER_SHA", "EVENT_SHA",
                  "CALLEE_REF", "CALLEE_SHA", "CALLEE_REPO",
                  "CALLEE_PATH", "RUN_ID", "RUN_ATTEMPT", "CHECK_ID")
          record = {key: os.environ[key] for key in keys}
          print(json.dumps(record, sort_keys=True))
          assert record["CALLEE_SHA"], "Missing callee identity"
      - name: Synthetic check
        run: exit 0

In the caller repository, save this as .github/workflows/caller.yml on its default branch. Replace YOUR-OWNER with your account or organization and use the actual callee repository name. Ensure the repositories' Actions access settings permit the call. The synthetic check intentionally validates no application code; its sole role is to provide a controlled result for the identity experiment.

name: Caller identity fixture
on: workflow_dispatch
permissions:
  contents: read
jobs:
  reusable-check:
    uses: YOUR-OWNER/ci-fixture/.github/workflows/probe.yml@identity-demo

Dispatch the caller once and save the JSON line plus the run URL. Export selected fields rather than the entire context: GitHub's context documentation warns that the full github object includes sensitive information. A missing callee SHA should fail this probe and remain an unresolved compatibility result, not be silently replaced by the caller SHA.

Change the callee while keeping the caller fixed

For revision B, change only the final command in the callee from run: exit 0 to run: exit 1, keeping the workflow name, job identifier, enclosing structure and identity step unchanged. Commit that change to identity-demo. Start a fresh caller dispatch from the same caller revision. Avoid using a rerun for this comparison; record two independent run URLs and inspect the actual resolved identities.

CaseExpected identity comparisonExpected synthetic result
A: initial calleeInitial caller; callee ASuccess
B: changed callee branchInitial caller unchanged; callee B differsFailure
C: caller pinned to ANew caller revision; callee A restoredSuccess

For case C, replace @identity-demo in the caller with the full SHA recorded for A and commit that caller edit. Dispatch again. This case intentionally changes the caller revision, so do not score it as an unchanged-caller comparison. The reuse guide recommends commit SHAs for stability and security; here the explicit SHA also gives you a concrete expected identity to compare with the runtime record.

If case B still reports A, investigate the selected reference, new dispatch, repository and committed file before drawing a conclusion. If it reports B but succeeds, inspect the completed job and the final step rather than assuming the displayed workflow title identifies the intended implementation. Treat a queued, cancelled or inaccessible run as incomplete evidence for this exercise.

Attach the final result after completion

Save one evidence row per run with the caller reference and SHA, event SHA, callee repository, path, reference and SHA, run URL, run attempt, check ID, completed conclusion and observation time. The context reference defines the run ID, attempt and check ID fields used above. The JSON printed during the identity step does not contain the final result of the later synthetic check: retrieve that conclusion from the completed run and attach it to the matching record.

For a real AI pull request, add the PR number, head commit, tested checkout commit, check command and reviewer. Ask another maintainer to open the callee file at the recorded SHA and explain what the check measures. A workflow that merely prints “passed” can have perfectly traceable identity. Likewise, a useful validator may miss a requirement it was never designed to test. Make the acceptance decision against the actual requirement and retain the agent rollback and approval plan for changes that pass review.

The acceptance criterion for this fixture is deliberately limited: all three recorded cases resolve to the expected implementations and completed synthetic outcomes, with the changed-callee case visible while the caller remains fixed. Do not report application correctness, dependency integrity or approval-policy enforcement as measured outcomes. Those need separate checks with their own inputs and failure cases.

Sources checked 2026-09-06