fix: pre-landing review fixes (full-ref branch compare, portable gh bound)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-31 18:46:41 +00:00
1 parent d1d1134a88
commit be34c94d3a
4 files changed
+31 -11

No files matched your search

+13 -8
View File
@@ -28,20 +28,25 @@ set -euo pipefail
# Detect the repo's default branch when no arg is given (#703-class
# platform-agnostic rule, lib/default-base.ts in bash): origin/HEAD unless it
# names the checked-out branch (a PR flow's clone can point it at the PR
# branch, GST-511) -> the PR's base (gh, bounded; skipped without a timeout
# binary) -> origin/main -> origin/master -> main. An origin/HEAD skipped that
# way leaves BASE empty when nothing past it resolves, and that fails closed.
# branch, GST-511) -> the PR's base (gh, killed after 5 s) -> origin/main ->
# origin/master -> main. An origin/HEAD skipped that way leaves BASE empty when
# nothing past it resolves, and that fails closed.
SKIPPED_HEAD=""
_default_base() {
local cur head pr to
cur=$(git symbolic-ref --quiet --short HEAD 2>/dev/null || true)
local cur head pr out g w
cur=$(git symbolic-ref --quiet HEAD 2>/dev/null || true)
cur="${cur#refs/heads/}"
head=$(git symbolic-ref --quiet refs/remotes/origin/HEAD 2>/dev/null || true)
head="${head#refs/remotes/origin/}"
if [ -n "$head" ] && [ "$head" != "$cur" ]; then BASE="$head"; return; fi
SKIPPED_HEAD="$head"
to=$(command -v gtimeout 2>/dev/null || command -v timeout 2>/dev/null || true)
if [ -n "$cur" ] && [ -n "$to" ]; then
pr=$(GH_PROMPT_DISABLED=1 "$to" 5 gh pr view --json baseRefName -q .baseRefName </dev/null 2>/dev/null | head -n 1 || true)
if [ -n "$cur" ] && command -v gh >/dev/null 2>&1 && out=$(mktemp "${TMPDIR:-/tmp}/gstack-diff-scope.XXXXXX" 2>/dev/null); then
GH_PROMPT_DISABLED=1 gh pr view --json baseRefName -q .baseRefName </dev/null >"$out" 2>/dev/null & g=$!
{ sleep 5; kill "$g"; } >/dev/null 2>&1 & w=$!
wait "$g" 2>/dev/null || true
kill "$w" 2>/dev/null || true
pr=$(head -n 1 "$out" 2>/dev/null || true)
rm -f "$out"
if [ -n "$pr" ]; then BASE="$pr"; return; fi
fi
git rev-parse --verify -q origin/main >/dev/null 2>&1 && { BASE="main"; return; }
+1 -1
View File
@@ -27,7 +27,7 @@ function read(cmd: string, args: string[], cwd: string, timeout: number): string
}
export function defaultBaseBranch(cwd: string, remotes: readonly string[] = ['origin']): DefaultBase {
const current = read('git', ['symbolic-ref', '--quiet', '--short', 'HEAD'], cwd, 30_000);
const current = read('git', ['symbolic-ref', '--quiet', 'HEAD'], cwd, 30_000).replace(/^refs\/heads\//, '');
let skipped: DefaultBase['skipped'];
for (const remote of remotes) {
const prefix = `refs/remotes/${remote}/`;
+14 -2
View File
@@ -451,8 +451,9 @@ describe('uncommitted work is visible (#2299)', () => {
// Value: protects=a clone whose origin/HEAD names the checked-out PR branch scopes the PR against origin/main, and with no
// other base fails closed naming origin/HEAD (GST-511); fails_when=the default base takes origin/HEAD's branch when it is the
// checked-out one (every SCOPE_*=false, exit 0); why_new=no test pointed origin/HEAD at the feature branch; seam=a gh stub on
// PATH; no_claim=remotes other than origin.
// checked-out one (every SCOPE_*=false, exit 0), including when a tag shares the branch's name, or the default branch's own
// uncommitted work stops being scoped; why_new=no test pointed origin/HEAD at the feature branch; seam=a gh stub on PATH;
// no_claim=remotes other than origin.
test('origin/HEAD naming the checked-out branch is skipped: the PR base, then origin/main, and none fails closed', () => {
const dir = createRepo(['lib/server.ts']);
const git = (...a: string[]) => spawnSync('git', a, { cwd: dir, stdio: 'pipe', timeout: 5000 });
@@ -469,6 +470,17 @@ describe('uncommitted work is visible (#2299)', () => {
expect(found.status).toBe(0);
expect(found.out).toContain('SCOPE_BACKEND=true');
expect(scope('json', 'no-such-base').out).toContain('SCOPE_ERROR=no_base');
git('tag', 'feature/test');
expect(scope('fail').out).toContain('SCOPE_BACKEND=true');
git('tag', '-d', 'feature/test');
git('checkout', '-q', 'main');
git('symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/main');
mkdirSync(join(dir, 'lib'), { recursive: true });
writeFileSync(join(dir, 'lib', 'local.ts'), 'export const local = 1;\n');
expect(scope('fail').out).toContain('SCOPE_BACKEND=true');
rmSync(join(dir, 'lib', 'local.ts'));
git('checkout', '-q', 'feature/test');
git('symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/feature/test');
git('update-ref', '-d', 'refs/remotes/origin/main');
const none = scope('fail');
expect(none.status).toBe(2);
+3
View File
@@ -335,6 +335,9 @@ describe('resolveBaseBranch: origin/HEAD naming the checked-out branch (GST-511)
return { out: r.stdout ?? '', err: r.stderr ?? '' };
};
expect(base('fail')).toEqual({ out: 'main', err: '' });
git('tag', 'feat');
expect(base('fail')).toEqual({ out: 'main', err: '' });
git('tag', '-d', 'feat');
expect(base('json', 'release').out).toBe('release');
git('update-ref', '-d', 'refs/remotes/origin/main');
const none = base('fail');