Skip to content

Bug: Checkout actions folder emitted without repository: or ref:Setup Scripts fails in cross-repo relay #20658

@johnwilliams-12

Description

@johnwilliams-12

Summary

PR #20500 ("Replace inlined Go builtin engine definitions with embedded shared agentic workflow files") changed Setup Scripts from a pinned remote action reference (uses: github/gh-aw/actions/setup@<sha>) to a local path action (uses: ./actions/setup). To support this, the compiler now emits a Checkout actions folder step that sparse-checks out the actions/ directory into $GITHUB_WORKSPACE. However, the step is emitted with no repository: and no ref: fields.

In a cross-repo relay triggered by a native event (e.g. issue_comment), actions/checkout defaults to github.repository — the caller (app) repo. The app repo has no actions/ directory, so Setup Scripts immediately fails with Can't find 'action.yml'. All downstream jobs are skipped.

Confirmed on v0.57.2-60-gd64fc1dee. Also confirmed that recompiling with a correct SHA already present in actions-lock.json does not fix the output — the compiler simply never emits these fields.

Root Cause

The emitter responsible for the Checkout actions folder + Setup Scripts pair
(likely pkg/workflow/compiler_activation_job.go and equivalent job emitters)
does not set repository: or ref: on the generated actions/checkout step.

Two missing fields:

  1. repository: — must always be github/gh-aw. Before Replace inlined Go builtin engine definitions with embedded shared agentic workflow files #20500, the runner
    fetched the actions/ directory implicitly from github/gh-aw via Actions
    service-level auth when processing uses: github/gh-aw/actions/setup@<sha>.
    After Replace inlined Go builtin engine definitions with embedded shared agentic workflow files #20500, the local-path switch (./actions/setup) requires the files to
    be present in $GITHUB_WORKSPACE, but the checkout has no repository: so
    it defaults to the calling repo, which has no actions/ directory.
    github/gh-aw is a public repository; no token: is required.

  2. ref: — must be the binary's own build commit SHA, not a version tag SHA.
    When the binary includes JS modules (e.g. resolve_host_repo.cjs, added in
    Cross-repo activation checkout still broken for event-driven relay workflows after #20301 #20567) that postdate the v0.57.x tag, checking out at the tag SHA produces
    an actions/ directory that is missing those modules, causing
    Cannot find module at runtime. The binary build commit SHA is already
    available as a build-time constant (e.g. via the -X linker flag or
    buildinfo.GitCommit).

Affected Code

All jobs that emit the Checkout actions folder + Setup Scripts pair:
pre_activation, activation, agent, safe_outputs, and any future jobs.

Current broken emitter output:

- name: Checkout actions folder
  uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
  with:
    sparse-checkout: |
      actions
    persist-credentials: false
    # NO repository: → defaults to github.repository (the caller/app repo)
    # NO ref:        → must be the binary's own build commit SHA
- name: Setup Scripts
  uses: ./actions/setup
  with:
    destination: /opt/gh-aw/actions

Proposed Fix

Emit repository: github/gh-aw and ref: <binary-build-sha> as compile-time
literals. No token: is needed (public repo). No preceding token-generation step
is needed.

- name: Checkout actions folder
  uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
  with:
    repository: github/gh-aw        # ← always the gh-aw tool repo
    ref: <binary-build-sha>         # ← the commit SHA the binary was built from
    sparse-checkout: |
      actions
    persist-credentials: false
- name: Setup Scripts
  uses: ./actions/setup
  with:
    destination: /opt/gh-aw/actions

This fix requires no new steps, no secrets, no runtime resolution, and no
per-repo configuration. It works identically in pure workflow_call relays and
event-driven relay patterns.

Note on GITHUB_WORKFLOW_REF: This approach does not generalise here. In
the primary real-world relay topology, GITHUB_WORKFLOW_REF points to the
relay file inside the caller (app) repo, not to the platform repo or to
github/gh-aw. Runtime resolution cannot determine github/gh-aw; only a
compile-time literal is correct.

Implementation Plan

  1. pkg/workflow/compiler_activation_job.go (and equivalent emitters for
    other jobs that emit this step pair):

    • Read the binary's build commit SHA from the existing build-time constant
      (e.g. version.Commit or buildinfo.GitCommit). Expose it via a
      CompilerData field or equivalent if not already available there.
    • In the Checkout actions folder step emitter, add:
      • repository: github/gh-aw as a string literal.
      • ref: <binary-commit-sha> using the value above.
    • Do not add a preceding token-generation step.
    • Apply to all jobs that emit this step pair: pre_activation,
      activation, agent, safe_outputs, and any future jobs.
  2. actions-lock.json handling: Verify that the sha field for
    github/gh-aw/actions/setup@<version> stores the binary's build commit SHA
    and not the version tag SHA. If the compiler currently stores the tag SHA,
    update the resolution to use the binary commit SHA instead so that
    actions-lock.json and the emitted ref: remain in sync.

  3. Tests (pkg/workflow/compiler_activation_job_test.go or equivalent):

    • Add test "cross-repo relay — Checkout actions folder emits repository and binary commit SHA":
      • Compile a workflow with a stubbed binary commit SHA.
      • Assert the Checkout actions folder step has repository: github/gh-aw.
      • Assert the Checkout actions folder step has ref: <stubbed-sha>.
      • Assert no token: field is present on that step.
      • Assert no preceding token-generation step is emitted.
    • Cover both workflow_call and event-driven (issue_comment) relay
      compilation.
  4. Update lock file golden fixtures to include repository: github/gh-aw
    and ref: <sha> in every Checkout actions folder step.

  5. Smoke test — add or update the cross-repo relay smoke test to use an
    event-driven trigger (e.g. issue_comment) and assert that Setup Scripts
    succeeds in pre_activation and that the activation job proceeds past
    Resolve host repo for activation checkout.

Reproduction

  1. Install a build that includes Replace inlined Go builtin engine definitions with embedded shared agentic workflow files #20500 (e.g. v0.57.2-60-gd64fc1dee).
  2. Compile any platform workflow: gh aw compile <workflow> --strict.
  3. Inspect the generated lock file — Checkout actions folder has no
    repository: and no ref:.
  4. In a separate (app) repository, create an event-driven relay:
    on:
      issue_comment:
        types: [created]
    jobs:
      relay:
        uses: <org>/<platform-repo>/.github/workflows/<workflow>.lock.yml@main
        secrets: inherit
  5. Trigger the relay (e.g. post an issue comment).
  6. Observe: Checkout actions folder checks out the app repo;
    Setup Scripts fails with Can't find 'action.yml'; all downstream
    jobs are skipped.

Expected: Checkout actions folder checks out github/gh-aw at the
binary's build commit SHA; Setup Scripts succeeds; downstream jobs proceed.

Verified fix: Manually patching the lock file to add
repository: github/gh-aw and ref: <binary-build-sha> to all
Checkout actions folder steps causes pre_activation and activation
to complete successfully in a live cross-repo event-driven relay.

Relationship to #20500 and #20567

This is a direct regression from #20500, which switched Setup Scripts from a
remote action ref (implicitly fetched from github/gh-aw by the runner) to a
local path action (requiring an explicit checkout). The Checkout actions folder
step was added to handle that checkout but was emitted without the required
repository: and ref:.

#20567 fixed a related checkout issue (the .github folder checkout in
activation using a workflow_call runtime discriminator). That fix uses
GITHUB_WORKFLOW_REF-based runtime resolution, which does not generalise to the
actions/ checkout — the correct fix here is purely compile-time.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions