From e98f8698269b7888539bbfe883f873143d7ab2e6 Mon Sep 17 00:00:00 2001 From: Matysh Date: Sun, 30 Aug 2026 19:05:24 +0300 Subject: [PATCH] ci: name the right issue in the range summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Живой прогон #2157 показал огрех формулировки: база диапазона (#388) представилась заголовком «База классификации (#387)». Текст верный, ссылка чужая — читатель уходит не в тот issue разбираться, почему диапазон такой. Заголовок теперь следует режиму, а не общей ветке кода. Закреплено тестом на оба режима и обе формулировки. Issue: #388 User-Visible: no --- scripts/classify-base.mjs | 17 ++++++++++++----- test/classify-base.test.mjs | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/scripts/classify-base.mjs b/scripts/classify-base.mjs index 43449f0c..0e74ce95 100644 --- a/scripts/classify-base.mjs +++ b/scripts/classify-base.mjs @@ -145,20 +145,27 @@ export function pickRangeBase({ candidates, green, fallback }) { const short = (sha) => (typeof sha === 'string' ? sha.slice(0, 8) : '?'); /** Строки для summary: почему диапазон именно такой. */ -export function baseSummary(choice, { head, mergeBase }) { +export function baseSummary(choice, { head, mergeBase, mode = 'classify' }) { + // Заголовок называет ЗАДАЧУ, а не режим кода: два потребителя задают разные + // вопросы, и общий заголовок отправил бы читателя не в тот issue. На живом + // прогоне #2157 это уже случилось — база диапазона представилась + // классификацией. + const heading = mode === 'range' + ? '### База диапазона (#388)' + : '### База классификации (#387)'; if (choice.reason === 'green-ancestor') { const skipped = choice.skipped ? ` Пропущено коммитов без завершённого прогона: ${choice.skipped}.` : ''; return [ - '### База классификации (#387)', + heading, `Диапазон \`${short(choice.base)}..${short(head)}\`: это самый новый предок,` + ` для которого Validate завершился успешно.${skipped}`, ]; } if (choice.reason === 'fallback') { return [ - '### База диапазона (#388)', + heading, `Ни один из ${choice.skipped} предков не был судим завершённым Validate.` + ` Диапазон взят от \`${short(choice.base)}\` — головы предыдущего пуша,` + ' и это НЕ доказательство проверенности: прогон того пуша мог быть отменён.' @@ -166,7 +173,7 @@ export function baseSummary(choice, { head, mergeBase }) { ]; } return [ - '### База классификации (#387)', + heading, 'Ни у одного предка до merge-base с dev нет завершённого зелёного Validate,' + ` поэтому диапазон расширен до \`${short(mergeBase)}..${short(head)}\` —` + ' весь вклад ветки. Узкий диапазон здесь означал бы «проверено» про то,' @@ -210,7 +217,7 @@ function main(argv) { const choice = mode === 'range' ? pickRangeBase({ candidates, green: judgedShas(payload), fallback: arg(argv, 'fallback') }) : pickBase({ candidates, green: greenShas(payload), mergeBase }); - const summary = baseSummary(choice, { head, mergeBase }); + const summary = baseSummary(choice, { head, mergeBase, mode }); process.stdout.write(`${summary.join('\n')}\n`); // Имя выхода задаётся явно: одна и та же job считает базу для двух разных // потребителей, и общее имя `base` для обоих было бы ловушкой — потребитель diff --git a/test/classify-base.test.mjs b/test/classify-base.test.mjs index df97eda6..e4208e84 100644 --- a/test/classify-base.test.mjs +++ b/test/classify-base.test.mjs @@ -222,3 +222,18 @@ test('красный прогон не переоткрывает уже осу assert.equal(choice.base, 'предыдущий'); assert.equal(choice.skipped, 0); }); + +test('заголовок summary называет задачу потребителя, а не режим кода (#388)', () => { + // На живом прогоне #2157 база диапазона представилась «классификацией» и + // отправила читателя не в тот issue. Заголовок обязан следовать режиму. + const green = { base: 'aaaaaaaa', reason: 'green-ancestor', proven: true, skipped: 1 }; + const fallback = { base: 'bbbbbbbb', reason: 'fallback', proven: false, skipped: 2 }; + const head = { head: 'cccccccc', mergeBase: 'dddddddd' }; + assert.match(baseSummary(green, { ...head, mode: 'range' })[0], /#388/); + assert.match(baseSummary(fallback, { ...head, mode: 'range' })[0], /#388/); + assert.match(baseSummary(green, head)[0], /#387/, 'по умолчанию — классификация'); + assert.match( + baseSummary({ base: 'e', reason: 'merge-base', proven: false, skipped: 0 }, head)[0], + /#387/, + ); +});