fix(git-tools): correlate Gitea PR merge state and CI runs (#140) - #184
Merged
st0nefish-ci[bot] merged 2 commits intoAug 29, 2026
Merged
Conversation
Two Gitea-only defects made `pr show` and `run watch` report the wrong
thing. Both fixes were written against an older git-cli and never landed;
this rebases them onto current master, which has since gained the
progress-aware idle-timeout handling that the original branch predated.
- `pr show` on Gitea sourced from `tea pr list`, whose JSON omits the
`merged` boolean and `merged_at` timestamp entirely, so a merged PR
reported merged:false and callers treated it as still open. Fetch the PR
detail via `tea api repos/{owner}/{repo}/pulls/<n>` instead, mirroring the
existing run:show/run:list pattern, and derive `state` from `merged` so it
matches the GitHub path
- Emit `merged_at` on the GitHub path too, so both platforms return the
same shape
- `run watch` timed out into status:no-workflow on Gitea even when CI ran:
Gitea leaves head_branch empty on pull_request-triggered runs, so
`run list --branch` correlates nothing. Resolve the branch head SHA up
front and fall back to head_sha correlation when the branch-filtered
lookup comes back empty. GitHub is unaffected — its server-side --branch
filter populates the first call, so the SHA path is never taken
- Add regression suites for both (6 tests, mock git/tea via PATH injection)
- Bump git-tools 2.2.1 -> 2.2.2 and session 4.5.0 -> 4.5.1 for the
vendored git-cli
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EddJxaTMXyj7o4ndrqfCxa
Every test that PATH-injects a fake `git` fell through unmatched
subcommands to `command git "$@"`. `command` bypasses functions and
aliases but NOT PATH lookup, and the mock's own directory is prepended to
PATH — so the mock re-executed itself, recursing without bound.
This was latent for as long as the mocks have existed: nothing ever called
git with a subcommand other than `remote get-url origin`. The `run watch`
head-SHA fix in the preceding commit calls `git rev-parse`, which made
every affected suite spawn processes until the terminal's cgroup pids
controller started rejecting forks. Observed at 56,311 processes in one
scope against a pids.max of 114,647, which takes down the whole terminal,
not just the test run.
Delegate to the real git by stripping the mock's own directory from PATH
first, so `exec git` resolves past it:
*) PATH=${PATH#"${0%/*}":}; exec git "$@" ;;
- Fix all 11 fallbacks across 9 suites
- `exec` rather than a nested call, so the mock does not linger as a parent
- Verified: matched cases still return mock values; unmatched delegate to
real git and terminate; `git rev-parse origin/<missing>` now returns
git's own error instead of recursing
tests/test.sh: 32 suites, 0 failed — previously it hung indefinitely.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EddJxaTMXyj7o4ndrqfCxa
There was a problem hiding this comment.
🟢 Approval recommended
The fixes directly address the reported Gitea defects and are backed by targeted regression tests plus a hardened mock setup to prevent recursive git execution.
Pull request overview
This PR fixes two Gitea-specific correctness bugs in git-cli (PR merge-state reporting and CI run correlation in run watch) and hardens the test harness to prevent recursive git mock execution (fork-bomb) when unmocked subcommands are invoked.
Changes:
- Fix
pr showon Gitea to fetch PR details viatea api .../pulls/<n>and emit consistent merge fields (merged,merged_at, derivedstate), matching the GitHub path’s semantics. - Fix
run watch --branchon Gitea by resolving the branch head SHA and falling back tohead_shacorrelation when branch-based correlation yields no runs. - Update git mocks across test suites to safely delegate unmatched subcommands to real
git(avoid PATH-based self-recursion), and add Gitea regression tests for both defects.
File summaries
| File | Description |
|---|---|
| utils/git-cli | Gitea pr show now uses REST detail for reliable merge fields; Gitea run watch gains head-SHA fallback correlation. |
| tests/session/test-pr-wait.sh | Fix git mock fallback to avoid recursive execution when delegating to real git. |
| tests/session/test-pr-auto-merge-status.sh | Fix git mock fallback to avoid recursive execution when delegating to real git. |
| tests/session/test-ci-poll.sh | Fix git mock fallback(s) to avoid recursive execution when delegating to real git. |
| tests/git-cli/test-run-watch-gitea.sh | Add regression coverage for Gitea run watch head-SHA fallback correlation. |
| tests/git-cli/test-run-show.sh | Fix git mock fallback to avoid recursive execution when delegating to real git. |
| tests/git-cli/test-pr-show-gitea.sh | Add regression coverage for Gitea pr show REST merge fields + guard against tea pr list usage. |
| tests/git-cli/test-pr-create.sh | Fix git mock fallback to avoid recursive execution when delegating to real git. |
| tests/git-cli/test-issue-write-json.sh | Fix git mock fallback(s) to avoid recursive execution when delegating to real git. |
| tests/git-cli/test-body-args.sh | Fix git mock fallback to avoid recursive execution when delegating to real git. |
| plugins-copilot/session/.claude-plugin/plugin.json | Bump session plugin version to ship the vendored git-cli fix. |
| plugins-copilot/git-tools/.claude-plugin/plugin.json | Bump git-tools plugin version to ship the vendored git-cli fix. |
| plugins-claude/session/scripts/git-cli | Vendored git-cli copy updated to include the Gitea fixes. |
| plugins-claude/session/.claude-plugin/plugin.json | Bump session plugin version to ship the vendored git-cli fix. |
| plugins-claude/git-tools/scripts/git-cli | Vendored git-cli copy updated to include the Gitea fixes. |
| plugins-claude/git-tools/.claude-plugin/plugin.json | Bump git-tools plugin version to ship the vendored git-cli fix. |
Review details
- Files reviewed: 16/16 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
st0nefish-ci
Bot
deleted the
fix/gitea-pr-show-and-run-watch-correlation
branch
August 29, 2026 21:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #140.
Summary
Two Gitea-only defects made
git-clireport the wrong thing, plus a fork-bomb landmine in the test mocks that the first fix exposed.1.
pr showreported merged PRs as openThe Gitea path sourced from
tea pr list, whose JSON omits themergedboolean andmerged_attimestamp entirely — tea only encodes merge state into thestatestring. A merged PR came backmerged:falseand callers treated it as still open.Fetches the PR detail via
tea api repos/{owner}/{repo}/pulls/<n>instead, mirroring the existingrun:show/run:listpattern, and derivesstatefrommergedso it matches the GitHub path.merged_atis now emitted on both platforms so the shape is identical.2.
run watchtimed out intono-workflowwhen CI had actually runGitea leaves
head_branchempty onpull_request-triggered runs, sorun list --branchcorrelates nothing. Resolves the branch head SHA up front and falls back tohead_shacorrelation when the branch-filtered lookup is empty.GitHub is unaffected — its server-side
--branchfilter populates the first call, so the SHA path is never taken. The two GitHub-only call sites (statusCheckRollup) are deliberately left alone.3. Test mocks fork-bombed on any unmatched git subcommand
Every suite that PATH-injects a fake
gitfell through tocommand git "$@".commandbypasses functions and aliases but not PATH lookup, and the mock's directory is prepended to PATH — so the mock re-executed itself, unbounded.Latent since the mocks were written, because nothing had ever called git with a subcommand other than
remote get-url origin. Therev-parsecall in fix 2 was the first, and it took out a whole terminal: 56,311 processes in one cgroup scope against apids.maxof 114,647, after which every fork in that terminal failed.Fixed at all 11 fallbacks across 9 suites by stripping the mock's own directory from PATH before delegating:
Without this, CI itself would fork-bomb on the
rev-parsecall, so it is a prerequisite for fix 2 rather than a follow-up.Test plan
bash tests/test.sh— 32 suites, 0 failed; previously hung indefinitelytests/session/test-ci-poll.sh— 38/38 (this is the suite that bombed)test-pr-show-gitea.sh(4),test-run-watch-gitea.sh(2)git rev-parse origin/<missing>returns git's own error instead of recursingvalidate-frontmatter.sh103/0;utils/sync.sh --checkno driftVersions
git-tools 2.2.1 → 2.2.2, session 4.5.0 → 4.5.1 (both vendor
git-cli).