mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 22:45:02 +01:00
fix(ship-preflight): read the default branch from the remote's HEAD, not a local origin/HEAD
A Capy checkout points refs/remotes/origin/HEAD at the PR branch, so the preflight refused every lane as 'on the base branch'. ls-remote --symref is authoritative; the local ref stays the offline fallback. Failing-first test in test/ship-preflight.test.ts. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
150e44b082
commit
628278ebe4
2 files changed
+13
-1
No files matched your search
@@ -22,7 +22,8 @@ const DIST = /(^|\/)(cmd\/[^/]+\/main\.go|bin\/[^/]+|Cargo\.toml|setup\.py|packa
|
||||
|
||||
function integrate(cwd: string, base: string, r: Report): boolean {
|
||||
const branch = git(cwd, ['branch', '--show-current']).stdout.trim();
|
||||
const head = git(cwd, ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']).stdout.trim().replace(/^origin\//, '');
|
||||
const remote = /^ref: refs\/heads\/(\S+)\s+HEAD$/m.exec(git(cwd, ['ls-remote', '--symref', 'origin', 'HEAD'], 60_000).stdout)?.[1];
|
||||
const head = remote ?? git(cwd, ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']).stdout.trim().replace(/^origin\//, '');
|
||||
r.add(`BRANCH: ${branch || '(detached)'} base=${base}`);
|
||||
if (!branch || branch === base || branch === head) { r.stop(`on the base branch (${branch || 'detached HEAD'}): ship from a feature branch`); return false; }
|
||||
const status = git(cwd, ['status', '--porcelain']).stdout.split('\n').filter(Boolean);
|
||||
|
||||
@@ -45,6 +45,17 @@ describe('gstack-ship-preflight', () => {
|
||||
expect(fetch.stdout).not.toContain('MERGE:');
|
||||
});
|
||||
|
||||
// Value: protects=the default-branch abort reads the remote's HEAD, not a local origin/HEAD a clone pointed at the feature branch; fails_when=a checkout whose local origin/HEAD names the feature branch is refused as "on the base branch";
|
||||
// why_new=GSTA-167 dogfood on #3633: a Capy checkout's origin/HEAD is the PR branch; seam=git ls-remote --symref; no_claim=offline fallback
|
||||
test('a local origin/HEAD naming the feature branch is not the default branch', () => {
|
||||
const f = fx();
|
||||
f.git('update-ref', 'refs/remotes/origin/feat', 'HEAD');
|
||||
f.git('symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/feat');
|
||||
const r = f.run(PREFLIGHT, ['--base', 'main']);
|
||||
expect(r.stdout).not.toContain('STOP: on the base branch');
|
||||
expect(r.status).toBe(0);
|
||||
});
|
||||
|
||||
// Value: protects=Step 3 merges the base and a conflict stops with the files named, leaving the merge for the agent to resolve; fails_when=the bin resolves a conflict itself, aborts the merge, or continues to tests;
|
||||
// why_new=moved from the Step 3 prose; seam=git merge; no_claim=which side is right
|
||||
test('a merged base is reported; a conflict stops with the conflicted files and the merge left in place', () => {
|
||||
|
||||
Reference in new issue
Block a user