mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
fix: the github-range runner throws so an orphaned BEFORE_SHA can fall back to dev
resolveValidationRange already knows how to replace a force-push-orphaned BEFORE_SHA with origin/dev, but the CLI handed it a runner that killed the process with exit 2 on the first cat-file instead of throwing into gitObjectExists' catch. Every push after a mandatory issue-branch rebase therefore painted process-gate red (runs 32939996348, 32940625718, 32942113142). The regression test drives the real CLI in a throwaway repo with a BEFORE_SHA that no longer exists. Issue: #315 User-Visible: no
This commit is contained in:
@@ -575,13 +575,20 @@ function main(argv) {
|
|||||||
|
|
||||||
let range = value('range');
|
let range = value('range');
|
||||||
if (!range && flag('github-range')) {
|
if (!range && flag('github-range')) {
|
||||||
|
// gitObjectExists ловит исключение, чтобы подменить осиротевший после
|
||||||
|
// force-push BEFORE_SHA на origin/dev (#315). Раннер обязан бросать,
|
||||||
|
// а не завершать процесс, как это делает git() ниже.
|
||||||
range = resolveValidationRange({
|
range = resolveValidationRange({
|
||||||
eventName: process.env.EVENT_NAME,
|
eventName: process.env.EVENT_NAME,
|
||||||
beforeSha: process.env.BEFORE_SHA,
|
beforeSha: process.env.BEFORE_SHA,
|
||||||
baseSha: process.env.BASE_SHA,
|
baseSha: process.env.BASE_SHA,
|
||||||
headSha: process.env.HEAD_SHA,
|
headSha: process.env.HEAD_SHA,
|
||||||
developmentBranch: process.env.DEVELOPMENT_BRANCH,
|
developmentBranch: process.env.DEVELOPMENT_BRANCH,
|
||||||
}, (args) => git(args, repo).trim());
|
}, (args) => {
|
||||||
|
const r = spawnSync('git', ['-C', repo, ...args], { encoding: 'utf8' });
|
||||||
|
if (r.status !== 0) throw new Error(`git ${args.join(' ')} → ${(r.stderr || '').trim()}`);
|
||||||
|
return r.stdout.trim();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!range) {
|
if (!range) {
|
||||||
const hasDev = spawnSync('git', ['-C', repo, 'rev-parse', '--verify', 'origin/dev'],
|
const hasDev = spawnSync('git', ['-C', repo, 'rev-parse', '--verify', 'origin/dev'],
|
||||||
|
|||||||
@@ -535,6 +535,64 @@ test('the CLI judges a rebased issue branch by its own commits (#190)', (t) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('the CLI falls back to origin/dev when BEFORE_SHA is orphaned by a force-push (#315)', (t) => {
|
||||||
|
const probe = spawnSync('git', ['--version'], { encoding: 'utf8' });
|
||||||
|
if (probe.status !== 0) {
|
||||||
|
t.skip('git недоступен');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dir = mkdtempSync(join(tmpdir(), 'hp-gate-315-'));
|
||||||
|
const gate = fileURLToPath(new URL('../scripts/process-gate.mjs', import.meta.url));
|
||||||
|
const git = (...args) => {
|
||||||
|
const r = spawnSync('git', ['-C', dir, ...args], { encoding: 'utf8' });
|
||||||
|
assert.equal(r.status, 0, `git ${args.join(' ')}: ${r.stderr}`);
|
||||||
|
return r.stdout;
|
||||||
|
};
|
||||||
|
const write = (rel, text) => {
|
||||||
|
const full = join(dir, rel);
|
||||||
|
mkdirSync(join(full, '..'), { recursive: true });
|
||||||
|
writeFileSync(full, text);
|
||||||
|
};
|
||||||
|
const commitAll = (message) => {
|
||||||
|
git('add', '-A');
|
||||||
|
git('-c', 'user.name=t', '-c', 'user.email=t@t', '-c', 'core.hooksPath=/dev/null',
|
||||||
|
'commit', '-q', '-m', message);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
git('init', '-q', '-b', 'dev');
|
||||||
|
write('README.md', 'base\n');
|
||||||
|
commitAll('Base');
|
||||||
|
git('update-ref', 'refs/remotes/origin/dev', git('rev-parse', 'HEAD').trim());
|
||||||
|
|
||||||
|
git('checkout', '-q', '-b', 'issue/7-own-work');
|
||||||
|
write('scripts/w.mjs', 'export const w = 1;\n');
|
||||||
|
commitAll('Own work\n\nIssue: #7\nUser-Visible: no');
|
||||||
|
|
||||||
|
// Push-событие после force-push: BEFORE_SHA указывает на переписанную
|
||||||
|
// вершину, которой в клоне больше нет. Раньше первый же cat-file убивал
|
||||||
|
// процесс кодом 2; теперь диапазон берётся от merge-base с origin/dev.
|
||||||
|
const r = spawnSync(process.execPath, [gate, '--repo', dir, '--github-range', '--json'], {
|
||||||
|
encoding: 'utf8',
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
EVENT_NAME: 'push',
|
||||||
|
BEFORE_SHA: 'f'.repeat(40),
|
||||||
|
BASE_SHA: '',
|
||||||
|
HEAD_SHA: git('rev-parse', 'HEAD').trim(),
|
||||||
|
DEVELOPMENT_BRANCH: 'dev',
|
||||||
|
TARGET_REF: 'refs/heads/issue/7-own-work',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
assert.equal(r.status, 0, r.stdout + r.stderr);
|
||||||
|
const report = JSON.parse(r.stdout);
|
||||||
|
assert.equal(report.commits, 1, JSON.stringify(report));
|
||||||
|
assert.equal(report.ok, true, JSON.stringify(report.findings));
|
||||||
|
} finally {
|
||||||
|
rmSync(dir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('an infrastructure range is recognised by the absence of class A files (#207)', () => {
|
test('an infrastructure range is recognised by the absence of class A files (#207)', () => {
|
||||||
const infra = makeCommit({
|
const infra = makeCommit({
|
||||||
sha: 'a'.repeat(40), subject: 'Tune CI', body: 'Issue: #206\nUser-Visible: no',
|
sha: 'a'.repeat(40), subject: 'Tune CI', body: 'Issue: #206\nUser-Visible: no',
|
||||||
|
|||||||
Reference in New Issue
Block a user