mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 23:19:14 +00:00
fix(process): слияние не обрывает дифф кандидата и называет причину сбоя запуска
Шаг слияния конвейера считает patch-id материала и кандидата через `git diff --full-index`, когда `dev` сдвинулся за время ревью. Дифф задачи, пересобирающей бандл, несёт три копии `houseplan-card.js` — у #594 это 7 103 616 байт. `sh()` не задавал `maxBuffer`, умолчание `spawnSync` — 1 МиБ, и процесс убивался по ENOBUFS на 1 027 868 байтах. Вторая половина дефекта прятала первую: `r.error` нигде не читался, а `status: r.status ?? 1` выдавало `null` за «git вернул 1». `must()` брал `r.stderr || r.stdout`, stderr был пуст — и в issue уезжало «Слияние не выполнено: diff: <огрызок диффа>». Огрызок выглядит осмысленным и уводит разбор в сторону. Путь исполняется только при сдвинувшемся `dev`, поэтому дефект дремал. Но конвейер сам пушит в `dev` документ ревью на каждом раунде, так что `devMoved` — норма, а не исключение. Что изменено: - `MAX_COMMAND_OUTPUT_BYTES` (256 МиБ) и явный `maxBuffer` в `sh()`; - `sh()` называет сбой запуска в `stderr` результата вместо молчания; - `sh()` экспортирован, у обоих пунктов есть исполнимый свидетель; - мутант `merge-candidate-truncates-the-candidate-diff` возвращает 1 МиБ. Issue: #596 User-Visible: no
This commit is contained in:
@@ -5,7 +5,9 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { MAX_ATTEMPTS, commentFor, decideMerge, mergeCandidate, realOps } from '../scripts/merge-candidate.mjs';
|
||||
import {
|
||||
MAX_ATTEMPTS, MAX_COMMAND_OUTPUT_BYTES, commentFor, decideMerge, mergeCandidate, realOps, sh,
|
||||
} from '../scripts/merge-candidate.mjs';
|
||||
import { buildCiProof } from '../scripts/ci-proof.mjs';
|
||||
|
||||
const mergeProofContext = (row, sha, tree) => {
|
||||
@@ -387,3 +389,24 @@ test('#516 AC1: dev moved only by review documents and the branch carries its ow
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
// #596: шаг слияния считает patch-id через `git diff` кандидата, а тот несёт три
|
||||
// копии бандла — семь мегабайт у #594. С умолчанием spawnSync в 1 МиБ процесс
|
||||
// убивался по ENOBUFS, `status` приходил `null`, и вывод обрезался посередине.
|
||||
test('#596: вывод больше мегабайта доезжает целиком, а не обрывается по буферу', () => {
|
||||
const bytes = 3 * 1024 * 1024;
|
||||
const r = sh(process.execPath, ['-e', `process.stdout.write('x'.repeat(${bytes}))`]);
|
||||
assert.equal(r.status, 0, r.stderr);
|
||||
assert.equal(r.stdout.length, bytes);
|
||||
assert.ok(MAX_COMMAND_OUTPUT_BYTES > bytes, 'предел выбран с запасом над проверяемым объёмом');
|
||||
});
|
||||
|
||||
// #596: вторая половина дефекта — сбой ЗАПУСКА выдавался за ненулевой код
|
||||
// возврата, и в сообщение уезжал усечённый stdout. Огрызок диффа выглядит
|
||||
// осмысленным и уводит разбор в сторону; причина обязана быть названа.
|
||||
test('#596: сбой запуска называет причину, а не притворяется кодом возврата', () => {
|
||||
const r = sh('houseplan-no-such-command-596', []);
|
||||
assert.equal(r.status, 1);
|
||||
assert.match(r.stderr, /houseplan-no-such-command-596 не выполнился: ENOENT/);
|
||||
assert.equal(r.stdout, '');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user