Skip to content

tend-mention/handle: POST-job cleanup of local <setup> action fails on stale PR branches (followup to #391) #561

@prql-bot

Description

@prql-bot

Problem

tend-mention's handle job fails during POST-job cleanup when fired by an issue_comment on a stale PR whose head branch predates the local ./.github/actions/<setup> composite action. The Claude session itself completes successfully and uploads its artifact — the failure happens after, when GitHub Actions tries to run the POST steps of nested actions inside <setup> and re-reads the composite's action.yaml from the workspace, which by then has been switched to the stale PR branch by gh pr checkout.

#391 fixed the forward step ordering by moving uses: ./.github/actions/<setup> ahead of gh pr checkout. The current generated tend-mention.yaml (0.0.24) is:

- uses: actions/checkout@v6
  with: { fetch-depth: 0, fetch-tags: true, token: ... }
- uses: ./.github/actions/tend-setup      # ✅ resolves against main
- name: Check out PR branch
  run: gh pr checkout "$PR_NUMBER"        # switches workspace to PR tree
- uses: max-sixty/tend@0.0.24

This works at run time. But at job end, the runner walks the POST chain in reverse. The POST handler for ./.github/actions/tend-setup re-opens the composite from the workspace path (<workspace>/.github/actions/tend-setup/action.yaml) — and if the PR branch lacks that path, it errors:

##[error]Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under '/home/runner/work/<repo>/<repo>/.github/actions/tend-setup'. Did you forget to run actions/checkout before running your local action?

The error fires because nested actions inside the composite — at minimum Swatinem/rust-cache@v2 — have real POST steps the runner needs to dispatch.

Evidence

PRQL/prql, run 25987714522 (2026-05-17):

  • Triggered by issue_comment on #5374 (Dependabot notify 7.0.0 → 8.2.0, opened 2025-09-12 — well before tend was added to PRQL on 2026-04-30 in #5727).
  • gh pr checkout 5374 switched workspace to dependabot/cargo/notify-8.2.0. That branch has no .github/actions/tend-setup — confirmed via gh api repos/PRQL/prql/contents/.github/actions/tend-setup?ref=dependabot/cargo/notify-8.2.0 → 404.
  • The Claude session exited silently (self-loop guard, correct behaviour) and uploaded claude-session-logs-6b8f824a.zip (36 KB).
  • Then POST cleanup fired the error above. The job's conclusion is failure despite the session being correct.

Sibling run 25987714377 at the same minute, for #5543 (dependabot/cargo/ariadne-0.6.0 — a branch that does contain .github/actions/tend-setup), succeeded cleanly. Same workflow, same code paths — the only difference is whether the PR's head tree carries the action directory.

Why this matters

  • Every consumer with a <setup> composite under .github/actions/ will hit this on any sufficiently old PR (long-lived feature branches, dependabot PRs that pre-date tend adoption, fork PRs not rebased).
  • Failure is silent in the sense that the agent did its job correctly, but the run shows red on the PR's status rollup and looks indistinguishable from a real failure to a maintainer reading their CI dashboard.
  • For PRQL specifically, the bot now needs maintainer attention on a comment thread where it actually did the right thing.

Possible fixes

Listing options without picking a winner — each has tradeoffs the maintainer is better placed to judge:

  1. Restore default-branch checkout after the session. Add a post: step (or always() step before tend's own post chain) that does a git checkout origin/<default> of just the .github/actions/<setup>/ path, so the cleanup walker can find the action file. Smallest blast radius.
  2. Copy the action dir to a stable location. Before gh pr checkout, copy .github/actions/<setup>/ to e.g. $RUNNER_TEMP/tend-setup/ and rewrite the workflow's uses: to that path. Defeats the issue but rewrites the action's resolution path.
  3. Ship <setup> as a remote action, not a local composite. Resolves identically across all consumers; biggest change to the install-tend flow.

Same fix applies symmetrically to tend-review if/when it grows a gh pr checkout after the setup step (referenced as out-of-scope in #396).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions