Skip to content

refactor(ci): use event-payload SHAs instead of network fetch of base ref#404

Merged
coseto6125 merged 1 commit into
mainfrom
refactor/use-event-base-sha
May 23, 2026
Merged

refactor(ci): use event-payload SHAs instead of network fetch of base ref#404
coseto6125 merged 1 commit into
mainfrom
refactor/use-event-base-sha

Conversation

@coseto6125
Copy link
Copy Markdown
Owner

@coseto6125 coseto6125 commented May 23, 2026

Root cause

Today's recurring `fatal: could not read Username for 'https://github.com': No such device or address` flakes (#388 macos checkout, #393 main-push, #395 dep-review, #397 main-push, #401 ubuntu Test, repro in #402's diagnostic run) all happen the same way:

  1. `actions/checkout` sets up `http.extraheader` correctly
  2. A subsequent `git fetch origin ` in the same job runs
  3. Git falls back to the system `credential.helper` from `/etc/gitconfig` on the runner image
  4. That helper errors with ENXIO → `could not read Username`

The system helper is GitHub's problem (broken default in runner image), not ours. But every `git fetch` we issue after checkout invites the bug.

What this PR does

Eliminate the failure surface entirely by dropping all post-checkout `git fetch` of base refs. GitHub already gives us `pull_request.base.sha` in the event payload, and the default `actions/checkout` ref (`refs/pull/N/merge`) brings both PR head AND base history into the local object DB. We can derive the branch point purely from local objects.

`ci.yml` — `Detect code changes` job

Before After
`git fetch --no-tags origin "$BASE_REF"` (network) (removed)
`diff_range="origin/$BASE_REF...HEAD"` `diff_range="$BASE_SHA...HEAD"`

Three-dot range still gives merge-base..HEAD semantics. Same result, no network.

`ecp-pr-analyze.yml` — drop `Fetch base ref` step

Before After
`ref: ${{ pull_request.head.sha }}` checkout override default ref (`refs/pull/N/merge`)
`git fetch origin "$BASE_REF:..."` (network) (removed)
`BASE=$(git merge-base "origin/$BASE_REF" HEAD)` `PR_HEAD=$(git rev-parse HEAD^1); BASE_TIP=$(git rev-parse HEAD^2); BRANCH_POINT=$(git merge-base "$PR_HEAD" "$BASE_TIP")`
(HEAD = PR head) `git checkout "$PR_HEAD"` (after computing branch point from merge ref's parents)

The branch point we compute is the SAME value the old `git merge-base origin/` produced — derived from the merge ref's two parents instead of a fetched ref.

Edge cases

  • PR with merge conflicts: GitHub doesn't compute `refs/pull/N/merge`, checkout fails. Correct behavior — conflicted PRs can't merge, so ecp impact analysis would be meaningless. Author resolves conflict → ref recomputed → next run works.
  • push to main / merge_group / workflow_dispatch: unchanged code path (already used BEFORE_SHA / blanket `code=true`, no fetch involved).

Test plan

  • Self-PR: `Detect code changes` step doesn't fetch, classifies paths correctly
  • Self-PR: `ecp pr-analyze` workflow computes branch point and runs analysis
  • Verify diff result matches what was produced before (compare with PR refactor(ci): replace Mergify with GitHub-native auto-merge + auto-update #401's expected analysis or any recent PR)
  • No regression on other workflow runs (push events / merge_group)

Cleanup after merge

@github-actions github-actions Bot enabled auto-merge (squash) May 23, 2026 18:24
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 23, 2026

ecp impact cache (0 symbols) — internal, used by ecp dev pr-analyze

[]

@github-actions github-actions Bot added the ecp:risk-low ecp signal label May 23, 2026
… ref

Root cause for today's recurring 'could not read Username for https://github.com'
flakes (#388 macos, #393 ubuntu, #395 dep-review, #397 main-push,
#401 ubuntu Test, #402 instrumentation): the runner image ships with a
default credential.helper in /etc/gitconfig that errors with ENXIO when
git falls back to it. actions/checkout sets up http.extraheader scoped
to the repo URL, but on certain runner image revisions the auth setup
escapes our isolation and the system helper gets invoked anyway.

Rather than work around the broken helper (which would leave a
permanent shellcheck-style `-c credential.helper=` debt on every
git command), we eliminate the failure surface entirely: the only steps
that do post-checkout fetches all want the same thing — main's tip
SHA — and GitHub already provides that in the pull_request event
payload (`github.event.pull_request.base.sha`).

# ci.yml — `Detect code changes` job

Was:
  git fetch --no-tags origin "$BASE_REF"
  diff_range="origin/$BASE_REF...HEAD"

Now:
  # Event payload exposes base.sha for free; checkout used default
  # ref (refs/pull/N/merge) so both sides are in local object DB.
  diff_range="$BASE_SHA...HEAD"

Three-dot range still gives merge-base..HEAD semantics — equivalent to
the old behavior, no network needed.

# ecp-pr-analyze.yml — drop `Fetch base ref` + recompute branch point locally

Was:
  - uses: actions/checkout@v6.0.2
    with:
      ref: ${{ pull_request.head.sha }}     # only PR head ancestors fetched
  - name: Fetch base ref
    run: git fetch origin "$BASE_REF:..."  # network — triggers ENXIO flake
  ...
  BASE=$(git merge-base "origin/$BASE_REF" HEAD)

Now:
  - uses: actions/checkout@v6.0.2
    with:
      fetch-depth: 0
      # No `ref:` override. Default refs/pull/N/merge brings both PR
      # head AND base history into local object DB.
  - name: Compute branch point + switch HEAD to PR head
    run: |
      PR_HEAD=$(git rev-parse HEAD^1)       # merge ref's parent 1
      BASE_TIP=$(git rev-parse HEAD^2)      # merge ref's parent 2
      BRANCH_POINT=$(git merge-base "$PR_HEAD" "$BASE_TIP")
      git checkout "$PR_HEAD"

Branch point is the SAME value the old `git merge-base origin/<base>`
would produce — but derived purely from local objects (the merge ref's
two parents) instead of a network fetch.

# Edge cases

- PR with merge conflicts: GitHub doesn't compute refs/pull/N/merge,
  checkout fails. This is correct — conflicted PRs can't merge, so
  ecp impact analysis would be meaningless. Author resolves conflict,
  ref recomputed, next run works.
- Push to main / merge_group / workflow_dispatch: unchanged code path
  (already used BEFORE_SHA / blanket 'code=true', no fetch).

# Result

- One entire class of CI flake eliminated: no post-checkout git fetch
  means no credential-helper invocation means no ENXIO.
- No upstream-bug workaround comment debt.
- Slightly faster CI (one fewer network round-trip per PR job).
- Closes the path that diagnostic instrumentation in PR #402 was
  trying to capture; PR #402 can be closed once this lands.
@coseto6125 coseto6125 force-pushed the refactor/use-event-base-sha branch from 40d5400 to 6a49805 Compare May 23, 2026 18:53
auto-merge was automatically disabled May 23, 2026 19:09

Tried to create or update workflow without `workflows` permission

@coseto6125 coseto6125 merged commit 0b26832 into main May 23, 2026
19 checks passed
@coseto6125 coseto6125 deleted the refactor/use-event-base-sha branch May 23, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecp:risk-low ecp signal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant