mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
fix: exempt pipeline review documents from the branch-name gate rule (#305)
Правило 2 локального process-gate блокировало пуш issue-ветки после того, как конвейер «Привести ветку к dev» вносил в неё свежую историю dev с чужим коммитом «docs: review document for #NNN» — локальный origin/dev автора отставал и не вычитал его из диапазона, а нарушение в истории не чинится следующим коммитом (единственный выход был --no-verify по §12/17). Исключение доказуемое и fail-closed: точный subject документа ревью И дифф только в docs/reviews/ (files обязателен — ownCommits теперь читаются с filesOf). Любой код рядом с документом или пустой список файлов возвращают правило 2 в строй; юниты фиксируют оба контура. Issue: #305 User-Visible: no
This commit is contained in:
@@ -202,12 +202,26 @@ export function evaluateCommit(c) {
|
||||
// уезжает назад, и в диапазон попадают коммиты `dev` с чужими номерами issue —
|
||||
// каждый из них выглядел бы нарушением. Проверено на реальной истории: сидя на
|
||||
// issue/89 с диапазоном по dev, гейт дал 26 ложных отказов из 26 коммитов.
|
||||
// Документ ревью, доказанно созданный конвейером (#305): точный subject
|
||||
// «docs: review document for #NN» и дифф ТОЛЬКО в docs/reviews/. Такой коммит
|
||||
// попадает в чужую issue-ветку легитимно — шаг «Привести ветку к dev»
|
||||
// вносит свежую историю dev, где конвейер только что опубликовал документ
|
||||
// соседней задачи, а локальный origin/dev автора мог отстать и не вычесть его
|
||||
// из диапазона. Кода в таком коммите нет по построению (files-критерий), и
|
||||
// судить им правило 2 — ложный отказ, чинимый только --no-verify.
|
||||
export function isPipelineReviewDocCommit(c) {
|
||||
return /^docs: review document for #\d+$/.test(c.subject ?? '')
|
||||
&& (c.files?.length ?? 0) > 0
|
||||
&& c.files.every((f) => f.startsWith('docs/reviews/'));
|
||||
}
|
||||
|
||||
export function checkBranchRule(branch, commits) {
|
||||
const m = (branch ?? '').match(/^issue\/(\d+)-/);
|
||||
if (!m) return [];
|
||||
const want = `#${m[1]}`;
|
||||
const out = [];
|
||||
for (const c of commits) {
|
||||
if (isPipelineReviewDocCommit(c)) continue;
|
||||
for (const t of c.issues) {
|
||||
if (t !== want) {
|
||||
out.push({
|
||||
@@ -541,8 +555,11 @@ function main(argv) {
|
||||
const hasDev = spawnSync('git', ['-C', repo, 'rev-parse', '--verify', 'origin/dev'],
|
||||
{ encoding: 'utf8' }).status === 0;
|
||||
if (!hasDev) return checkedCommits;
|
||||
// filesOf обязателен: исключение #305 доказывается диффом коммита
|
||||
// (только docs/reviews/), а без файлов оно не срабатывает fail-closed.
|
||||
const own = parseRecords(
|
||||
git(['log', '--reverse', `--pretty=format:${LOG_FORMAT}`, 'origin/dev..HEAD'], repo),
|
||||
filesOf,
|
||||
);
|
||||
return commitsNeedingTargetValidation(own, { targetRef, isCommitOnMain });
|
||||
})()
|
||||
|
||||
Reference in New Issue
Block a user