Skip to content

#203 Checkout default branch so self-healing script is always up to date#205

Merged
hubertgajewski merged 3 commits into
mainfrom
bugfix/203-checkout
Apr 13, 2026
Merged

#203 Checkout default branch so self-healing script is always up to date#205
hubertgajewski merged 3 commits into
mainfrom
bugfix/203-checkout

Conversation

@hubertgajewski
Copy link
Copy Markdown
Owner

Summary

Follow-up to #203. The workflow checked out head_sha (the failing branch's commit), which meant self-healing.py ran from that old commit — not the latest version on main. For branches that predate the self-healing code, the script wouldn't even exist.

Fix: remove the ref: parameter so actions/checkout uses the default branch. The script already calls git checkout -b fix/self-healing-<sha> <head_sha> internally when creating draft PRs, so the failing commit's code is still accessible for applying fixes. fetch-depth: 0 ensures full history is available.

Test plan

  • 70/70 unit tests pass
  • Comment path: reads from self-healing-data/ artifacts, never touches repo files — unaffected
  • Draft PR path: git checkout -b in the script switches to head_sha before reading test files — correct behavior preserved
  • self-healing-data/ is untracked — survives git checkout in the script
  • CI smoke test: re-trigger on test/self-healing-smoke after merge, verify draft PR is created

@hubertgajewski hubertgajewski self-assigned this Apr 13, 2026
@claude
Copy link
Copy Markdown

claude Bot commented Apr 13, 2026

Claude finished @hubertgajewski's task in 2m 24s —— View job


Review complete

  • Gather context
  • Read changed workflow file
  • Analyze the diff and correctness of the fix
  • Submit formal GitHub review (changes requested)

Summary

Approach is correct — running self-healing.py from main instead of the failing branch's commit is the right fix for the original problem. The overall structure holds up.

One functional bug found in the draft-PR path:

actions/checkout@v6 with fetch-depth: 0 unshallows history for the checked-out branch (main) only. It does not fetch refs from other branches. After this change, head_sha (the failing commit on a feature branch) will not exist in the local git object store.

scripts/self-healing.py:637 then runs:

git_run("git", "checkout", "-b", fix_branch, head_sha)

…which will fail with fatal: not a valid object name '<sha>' — exactly for the non-merged feature branches this PR targets.

Suggested fix (inline comment added): add an explicit fetch step in the workflow after checkout:

- name: Fetch failing commit
  run: git fetch origin ${{ github.event.workflow_run.head_branch }}

Comment thread .github/workflows/self-healing.yml
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: head_sha availability gap in the draft-PR path

The motivation for this change is sound — using the latest self-healing.py from main is the right call, especially for branches that predate the self-healing code. The overall approach is correct.

However there is one functional bug that will break the draft-PR path for the exact case this PR targets (branches that predated self-healing).

Bug: head_sha is no longer guaranteed to be a local git object

actions/checkout@v6 with fetch-depth: 0 performs a full unshallow of the checked-out branch (main), but does not automatically fetch refs from other branches. After the checkout step, any head_sha that belongs to a non-merged feature branch will not exist in the local object store.

self-healing.py:637 then does:

git_run("git", "checkout", "-b", fix_branch, head_sha)

This will fail with fatal: not a valid object name '<sha>' for the branches this PR was designed to fix (those that predate self-healing and therefore predate any merge into main).

Fix

Add a fetch of the failing branch between actions/checkout and the script invocation:

- name: Fetch failing commit
  run: git fetch origin ${{ github.event.workflow_run.head_branch }}

Or move the fetch into scripts/self-healing.py inside create_draft_pr, immediately before the git checkout -b call:

# Ensure head_sha is available locally (may not be if it's on a non-merged branch)
subprocess.run(["git", "fetch", "origin", head_sha], check=False)
git_run("git", "checkout", "-b", fix_branch, head_sha)

(Using check=False for the fetch is intentional — it's a best-effort prefetch; the checkout call that follows will raise a clear error if it still fails.)

Everything else looks good

  • Removing ref: so the script runs from main is the correct fix for the original problem.
  • fetch-depth: 0 is still needed — once the branch is created from head_sha, git needs history to push cleanly.
  • The comment path (read artifacts, post comment) is unaffected by the checkout change.
  • The environment variables (HEAD_SHA, HEAD_BRANCH) are passed explicitly, so the script always knows the right SHA to target.

@claude
Copy link
Copy Markdown

claude Bot commented Apr 13, 2026

Claude finished @hubertgajewski's task in 2m 1s —— View job


Review complete

  • Gather context
  • Read updated workflow file
  • Verify the fetch fix addresses the head_sha availability gap
  • Submit formal GitHub review (changes requested)

Summary

The added fetch step is the right fix — it guarantees head_sha is in the local object store before scripts/self-healing.py:637 runs git checkout -b fix/self-healing-<sha> <head_sha>.

One remaining issue on line 36: the refspec passed to git fetch is head_sha (a raw commit hash) rather than head_branch (the branch name). git fetch origin <sha> is non-standard — it works on GitHub because uploadpack.allowReachableSHA1InWant is enabled, but it's not the idiomatic approach and my original inline suggestion specifically used head_branch.

Suggested one-word change:

# current
run: git fetch origin ${{ github.event.workflow_run.head_sha }}

# correct
run: git fetch origin ${{ github.event.workflow_run.head_branch }}

Everything else looks good: removing the ref: pin so the script runs from main, keeping fetch-depth: 0, and passing HEAD_SHA/HEAD_BRANCH as env vars are all correct.

Comment thread .github/workflows/self-healing.yml Outdated
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: one remaining issue with the fetch refspec

The approach is correct and the fix moves in the right direction — adding an explicit fetch step to guarantee head_sha is in the local object store before the script calls git checkout -b fix/self-healing-<sha> <head_sha>.

One issue on line 36: the refspec passed to git fetch is head_sha (a raw commit hash) instead of head_branch (the branch name). git fetch origin <sha> is non-standard: it works on GitHub because uploadpack.allowReachableSHA1InWant is enabled there, but it's not a portable git operation and the step name already says "Fetch failing branch". My original inline suggestion used head_branch for this reason.

Suggested fix (same as the inline suggestion):

run: git fetch origin ${{ github.event.workflow_run.head_branch }}

Everything else looks good:

  • Removing ref: head_sha from the checkout so the script always runs from main ✓
  • Keeping fetch-depth: 0 for full history ✓
  • Passing HEAD_SHA and HEAD_BRANCH as env vars so the script still targets the right commit ✓
  • Comment path is unaffected by the checkout change ✓

@claude
Copy link
Copy Markdown

claude Bot commented Apr 13, 2026

Claude finished @hubertgajewski's task in 1m 17s —— View job


Review complete

  • Gather context
  • Read updated workflow file
  • Verify the head_branch fetch fix is correct
  • Submit formal GitHub review (approved)

All three review concerns from the previous rounds are now resolved:

  1. ref: pin removed — checkout uses the default branch so self-healing.py always runs from the latest version on main. ✓

  2. head_sha availability gap closedgit fetch origin ${{ github.event.workflow_run.head_branch }} ensures head_sha is in the local object store before scripts/self-healing.py:637 calls git checkout -b fix/self-healing-<sha> <head_sha>. ✓

  3. Refspec is now idiomatic — fetching by branch name (not raw SHA) is standard git and avoids relying on uploadpack.allowReachableSHA1InWant. ✓

The inline comment on line 37 clearly explains why the fetch is needed. fetch-depth: 0, HEAD_SHA, HEAD_BRANCH, and all other env vars are intact. LGTM.

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three review concerns are now resolved:

  1. ref: pin removedactions/checkout uses the default branch, so self-healing.py always runs from the latest version on main. ✓

  2. head_sha availability gap closed — the added fetch step makes head_sha available in the local object store before scripts/self-healing.py:637 runs git checkout -b fix/self-healing-<sha> <head_sha>. ✓

  3. Refspec is now idiomaticgit fetch origin ${{ github.event.workflow_run.head_branch }} fetches by branch name rather than raw SHA, which is standard git and does not rely on server-side uploadpack.allowReachableSHA1InWant. ✓

The comment on line 37 correctly explains why the fetch is needed. fetch-depth: 0, HEAD_SHA, HEAD_BRANCH, and all other env vars are intact. LGTM.

@hubertgajewski hubertgajewski merged commit 08ad4a2 into main Apr 13, 2026
19 checks passed
@hubertgajewski hubertgajewski deleted the bugfix/203-checkout branch April 13, 2026 17:55
@hubertgajewski hubertgajewski restored the bugfix/203-checkout branch April 13, 2026 18:10
@hubertgajewski hubertgajewski deleted the bugfix/203-checkout branch April 13, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant