mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 06:59:46 +00:00
process: preflight does not fail a task branch for foreign causes (#700)
11 of 85 returns in #600–#691 were the thin-workflow mirror check, and any push could turn red because a foreign site behind a docs link was down. - validate.yml preflight: on refs/heads/issue/* the workflow_sync mismatch is a warning in the summary, not a failed verdict; push to dev, the beta candidate and the release keep it red. - On push to dev a mismatch opens one owner issue titled [workflow-sync] (or comments on the open one), like the nightly mutation gate (#472); preflight gets issues: write for that. - check-docs --external=warn: external link failures become warnings; the docs step passes it on task branches only. Canon: PROCESS.md §10.4 («Workflow из ветки по умолчанию»). Issue: #700 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
This commit is contained in:
@@ -215,7 +215,7 @@ test('#586: preflight спрашивает режим одним значени
|
||||
assert.match(workflow, /classify-changes\.mjs --screenshots-mode/);
|
||||
assert.ok(!/=\s*"heavy=true"/.test(workflow),
|
||||
'сравнение со строкой «heavy=true» вернулось — строгий режим снова не включится');
|
||||
assert.match(workflow, /check-docs\.mjs --external --screenshots=\$mode/);
|
||||
assert.match(workflow, /check-docs\.mjs "\$external" --screenshots=\$mode/);
|
||||
});
|
||||
|
||||
test('#510 AC1 / #601 AC1: мутанты по диффу запрашиваются только кнопкой mutants=true и PR — не пушем, не кандидатом беты, не full', () => {
|
||||
|
||||
@@ -30,8 +30,14 @@ test('check-docs: только две проверки свежести идут
|
||||
assert.ok(viaMode[0].includes('fingerprint is stale'));
|
||||
assert.ok(viaMode[1].includes('capture script changed'));
|
||||
// Хеш картинки, полнота набора сцен и ссылки не имеют права ослабляться.
|
||||
for (const always of ['image hash does not match manifest', 'scenario set is incomplete', 'external link returned']) {
|
||||
for (const always of ['image hash does not match manifest', 'scenario set is incomplete']) {
|
||||
const line = source.split('\n').find((l) => l.includes(always));
|
||||
assert.ok(line && line.includes('errors.push'), `${always} остаётся ошибкой в обоих режимах`);
|
||||
}
|
||||
// #700: внешние ссылки не зависят от режима скриншотов; предупреждением их
|
||||
// делает только явный `--external=warn` на ветке задачи.
|
||||
const external = source.split('\n').find((l) => l.includes('external link returned'));
|
||||
assert.ok(external && external.includes('externalErrors.push'), 'внешняя ссылка идёт в свой сток');
|
||||
assert.match(source, /const externalErrors = EXTERNAL_WARN \? warnings : errors;/);
|
||||
assert.doesNotMatch(source, /externalErrors = freshness/);
|
||||
});
|
||||
|
||||
@@ -440,7 +440,7 @@ test('смоки, golden и performance_smoke условны по heavy (#479)',
|
||||
assert.match(text, /classify-changes\.mjs --heavy/);
|
||||
assert.match(text, /workflow_dispatch:\n\s+inputs:\n\s+full:/);
|
||||
// preflight: режим скриншотов считает тот же скрипт.
|
||||
assert.match(text, /check-docs\.mjs --external --screenshots=\$mode/);
|
||||
assert.match(text, /check-docs\.mjs "\$external" --screenshots=\$mode/);
|
||||
});
|
||||
|
||||
test('ночной прогон — dispatch Validate на dev с full=true (#479)', () => {
|
||||
@@ -613,3 +613,27 @@ test('#541: Validate всегда публикует proof точной попы
|
||||
assert.equal(reuse.includes('lookup-only: true'), false,
|
||||
'marker contents must be restored and verified, not reduced to a cache-hit bit');
|
||||
});
|
||||
|
||||
test('#700: на ветке задачи зеркало workflow и внешние ссылки — предупреждение, на dev — красный и issue', () => {
|
||||
const workflow = read('validate.yml');
|
||||
const preflight = workflow.slice(workflow.indexOf('\n preflight:\n'), workflow.indexOf('\n changes:\n'));
|
||||
const docs = preflight.slice(preflight.indexOf('id: docs'), preflight.indexOf('id: reviews_index'));
|
||||
assert.match(docs, /case "\$REF" in refs\/heads\/issue\/\*\) external=--external=warn ;; esac/);
|
||||
assert.match(docs, /REF: \$\{\{ github\.ref \}\}/);
|
||||
const verdict = preflight.slice(preflight.indexOf('- name: Вердикт предполётных проверок'));
|
||||
assert.match(verdict, /case "\$REF" in refs\/heads\/issue\/\*\) task_branch=true ;; esac/);
|
||||
assert.match(verdict, /if \[ "\$task_branch" = "true" \]; then\n\s+advise "тонкие вызывающие workflow в main и dev" "\$WORKFLOW_SYNC"\n\s+else\n\s+check "тонкие вызывающие workflow в main и dev"/);
|
||||
assert.doesNotMatch(verdict.slice(verdict.indexOf('advise() {'), verdict.indexOf('task_branch=false')), /fail=1/,
|
||||
'предупреждение не красит вердикт');
|
||||
const issue = preflight.slice(preflight.indexOf('- name: "Расхождение зеркала на dev — issue владельцу"'));
|
||||
assert.match(issue, /if: github\.event_name == 'push' && github\.ref == 'refs\/heads\/dev' && steps\.workflow_sync\.outcome == 'failure'/);
|
||||
assert.match(issue, /gh issue list --repo "\$REPO" --state open --search/, 'одно issue, а не одно на каждый push');
|
||||
assert.match(preflight, /permissions:\n\s+contents: read\n\s+actions: read\n\s+issues: write/);
|
||||
});
|
||||
|
||||
test('#700: check-docs --external=warn сводит внешние отказы в предупреждения', () => {
|
||||
const source = read('../../scripts/check-docs.mjs');
|
||||
assert.match(source, /const EXTERNAL_WARN = process\.argv\.includes\('--external=warn'\);/);
|
||||
assert.match(source, /const externalErrors = EXTERNAL_WARN \? warnings : errors;/);
|
||||
assert.equal((source.match(/externalErrors\.push\(/g) || []).length, 2, 'оба вида внешнего отказа');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user