mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 19:58:50 +00:00
The label step after integration ran one gh call `--add-label "$TO" --remove-label "$FROM"`. For the rereview outcome TO == FROM == S7-code-review, and gh added and removed the same label: #699 was left without a status and no new round started (run 36491087708). - scripts/status-label.mjs: the same label is removed and set again through relabel from process-reconcile (#555), so the labeled event starts the next round and a failed restore fails the step; a different label is still one call. - _process.yml: the step calls the script. - PROCESS.md: the exact-candidate rule names the relabel. - test/status-label.test.mjs; mutants rereview-relabel-in-one-call and process-label-step-combined-again. Issue: #706 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
51 lines
2.6 KiB
JavaScript
51 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Перестановка статусной метки после интеграции ревью (#706).
|
|
*
|
|
* node scripts/status-label.mjs --repo=owner/name --issue=NN --from=<метка> --to=<метка>
|
|
*
|
|
* Обычный исход — одна правка: `--add-label TO --remove-label FROM`. Исход
|
|
* `rereview` (#492) возвращает задачу в ту же метку, из которой она пришла:
|
|
* `TO == FROM == S7-code-review`. Одним вызовом `gh` такую метку добавляет и
|
|
* тут же снимает — задача оставалась без статуса, и нового захода не было
|
|
* (#699, 2026-09-28). Поэтому одинаковая метка снимается и ставится заново
|
|
* двумя вызовами, как в автосверке (`relabel`, #555): событие `labeled`
|
|
* запускает новый заход ревью, а сбой повторной постановки роняет шаг, и
|
|
* конвейер зовёт владельца.
|
|
*/
|
|
import { spawnSync } from 'node:child_process';
|
|
import { isMainModule } from './spawn-portable.mjs';
|
|
import { relabel } from './process-reconcile.mjs';
|
|
|
|
function gh(args, { allowFailure = false } = {}) {
|
|
const result = spawnSync('gh', args, { encoding: 'utf8' });
|
|
if (!allowFailure && (result.error || result.status !== 0)) {
|
|
throw new Error(`gh ${args.join(' ')} → ${(result.stderr || result.error?.message || '').trim()}`);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** @returns {'moved' | 'relabeled'} */
|
|
export function moveStatusLabel({ repo, issue, from = '', to, execute = gh }) {
|
|
if (!repo || !issue || !to) throw new Error('usage: status-label.mjs --repo=owner/name --issue=NN --from=<метка> --to=<метка>');
|
|
if (from === to) {
|
|
relabel(repo, { number: issue }, to, execute);
|
|
return 'relabeled';
|
|
}
|
|
const args = ['issue', 'edit', String(issue), '--repo', repo, '--add-label', to];
|
|
if (from) args.push('--remove-label', from);
|
|
execute(args);
|
|
return 'moved';
|
|
}
|
|
|
|
if (isMainModule(import.meta.url)) {
|
|
const arg = (name) => process.argv.find((a) => a.startsWith(`--${name}=`))?.slice(name.length + 3) ?? '';
|
|
try {
|
|
const how = moveStatusLabel({ repo: arg('repo'), issue: arg('issue'), from: arg('from'), to: arg('to') });
|
|
console.log(`${arg('from') || '(без метки)'} -> ${arg('to')}${how === 'relabeled' ? ' (снята и поставлена заново — новый заход, #706)' : ''}`);
|
|
} catch (error) {
|
|
console.error(`::error::${error.message}`);
|
|
process.exit(1);
|
|
}
|
|
}
|