mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 12:18:51 +00:00
fix(process): a workflow-permission refusal tells the author to rebase (#730)
Review r1 (Medium): refusalSummary said "повтор и ребейз не помогут" for every non-stale outcome, and since AC2 the rebase guard's summary carries it too. For a workflow-permission refusal a rebase and push by the author is exactly the way out (PROCESS.md §10.4). That outcome now says so; other GitHub refusals keep the old sentence. Issue: #730 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:
@@ -538,6 +538,11 @@ export function refusalSummary(refusal, { ref = '', stage = '' } = {}) {
|
||||
: refusal.kind === PUSH_REFUSAL.remote
|
||||
? 'GitHub отклонил push сам (правило ветки, хук, сбой сервера)'
|
||||
: 'git push не удался, и это не отказ по lease (сеть, аутентификация)';
|
||||
// #730 r1: при отказе по праву на workflow ребейз — штатный выход, только
|
||||
// делает его автор (PROCESS.md §10.4). «Ребейз не поможет» говорило обратное.
|
||||
const nextStep = refusal.kind === PUSH_REFUSAL.workflow
|
||||
? `Это не сдвиг \`${ref}\`: повтор этого шага не поможет, шаг остановлен без повторов. Кандидат меняет workflow-файл, токен конвейера не может его опубликовать: ребейз и push делает автор, либо владелец выдаёт право.`
|
||||
: `Это не сдвиг \`${ref}\`: повтор и ребейз не помогут, шаг остановлен без повторов.`;
|
||||
// Ответ GitHub не должен открыть или закрыть блок кода сводки.
|
||||
const unfence = (text) => String(text || '').replace(/```/g, "'''");
|
||||
const files = (refusal.files || []).map((file) => `\`${file}\``).join(', ');
|
||||
@@ -545,7 +550,7 @@ export function refusalSummary(refusal, { ref = '', stage = '' } = {}) {
|
||||
return [
|
||||
`### git push в \`${ref}\` отклонён: ${refusal.kind} (#723)`,
|
||||
'',
|
||||
`${what} не опубликован в \`${ref}\`. ${why}. Это не сдвиг \`${ref}\`: повтор и ребейз не помогут, шаг остановлен без повторов.`,
|
||||
`${what} не опубликован в \`${ref}\`. ${why}. ${nextStep}`,
|
||||
...(refusal.reason ? ['', `Причина, которую назвал GitHub: «${unfence(refusal.reason)}».${files ? ` Файлы: ${files}.` : ''}`] : []),
|
||||
'',
|
||||
stderr ? `Ответ git:\n\n\`\`\`\n${stderr}\n\`\`\`` : 'git не прислал текста отказа.',
|
||||
|
||||
@@ -579,6 +579,15 @@ test('#730: подписи сводки для публикации ship, про
|
||||
assert.match(refusalSummary(refusal, { ref: 'issue/9-fix', stage: 'rebase' }), /\n\nРебейз ветки на dev не опубликован в `issue\/9-fix`\./);
|
||||
});
|
||||
|
||||
test('#730 r1: при отказе по праву на workflow сводка зовёт автора сделать ребейз, а не отговаривает', () => {
|
||||
const workflow = refusalSummary(classifyPushRefusal(remoteRejected('issue/9-fix', WORKFLOW_REASON)), { ref: 'issue/9-fix', stage: 'rebase' });
|
||||
assert.match(workflow, /ребейз и push делает автор, либо владелец выдаёт право/);
|
||||
assert.doesNotMatch(workflow, /ребейз не помогут/);
|
||||
const remote = refusalSummary(classifyPushRefusal(remoteRejected('dev', 'protected branch hook declined')), { ref: 'dev', stage: 'ship-review' });
|
||||
assert.match(remote, /повтор и ребейз не помогут/);
|
||||
assert.doesNotMatch(remote, /ребейз и push делает автор/);
|
||||
});
|
||||
|
||||
test('#723 AC2: сводка об отказе — без токена, URL с учётными данными и Authorization; причина и файлы названы', () => {
|
||||
const refusal = classifyPushRefusal(`> Authorization: Bearer ${OTHER_TOKEN}\n${remoteRejected('dev', WORKFLOW_REASON)}`, { secrets: [FAKE_TOKEN] });
|
||||
const text = refusalSummary(refusal, { ref: 'dev', stage: 'release-review' });
|
||||
|
||||
Reference in New Issue
Block a user