feat(ci): squash updates repo history each release (DND_UPDATES_SQUASH_HISTORY)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
* DND_FEED_TMP_ROOT — каталог для временного клона feed (по умолчанию GITHUB_WORKSPACE / TMPDIR / os.tmpdir); не используйте узкий /tmp на раннере
|
||||
* DND_GIT_FETCH_RETRIES — число попыток git fetch (1–6, по умолчанию 6); между попытками — git gc --prune=now (освобождение после обрыва TLS/unpack)
|
||||
* DND_FEED_SKIP_DISK_CHECK — если "1", не проверять свободное место на томе DND_FEED_TMP_ROOT перед clone
|
||||
* DND_UPDATES_SQUASH_HISTORY — если "1", после каждого релиза ветка updates в UPDATES_REPO — один корневой коммит (orphan + force-with-lease push), история не копится (меньше места на раннере и на сервере после GC)
|
||||
*/
|
||||
import { execFileSync, spawnSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
@@ -175,6 +176,55 @@ function sleepSyncSeconds(seconds) {
|
||||
}
|
||||
}
|
||||
|
||||
function feedSquashSingleCommitEnabled() {
|
||||
return process.env.DND_UPDATES_SQUASH_HISTORY?.trim() === '1';
|
||||
}
|
||||
|
||||
/** После merge и add: одна линия без истории (только репо UPDATES_REPO / ветка updates). */
|
||||
function squashUpdatesBranchToSingleCommit(work, message) {
|
||||
const orphan = 'dnd-feed-squash-tmp';
|
||||
runGit(['checkout', '--orphan', orphan], work);
|
||||
runGit(['add', '-A'], work);
|
||||
runGit(['commit', '-m', message], work);
|
||||
runGit(['branch', '-D', 'updates'], work);
|
||||
runGit(['branch', '-m', 'updates'], work);
|
||||
}
|
||||
|
||||
function hadOriginUpdatesRemoteRef(work) {
|
||||
try {
|
||||
execFileSync('git', ['show-ref', '--verify', '--quiet', 'refs/remotes/origin/updates'], {
|
||||
cwd: work,
|
||||
stdio: 'ignore',
|
||||
});
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** После squash не делаем merge перед push — вернёт старую историю с remote. */
|
||||
function pushUpdatesBranchAfterSquash(work) {
|
||||
const retries = Math.max(1, Math.min(5, Number.parseInt(process.env.DND_GIT_PUSH_RETRIES || '3', 10) || 3));
|
||||
const args = hadOriginUpdatesRemoteRef(work)
|
||||
? ['push', '--force-with-lease', '-u', 'origin', 'updates']
|
||||
: ['push', '-u', 'origin', 'updates'];
|
||||
let lastError;
|
||||
for (let attempt = 1; attempt <= retries; attempt += 1) {
|
||||
try {
|
||||
console.log(`[sync-update-feed] push updates (squash, attempt ${attempt}/${retries})`);
|
||||
execFileSync('git', args, { cwd: work, stdio: 'inherit' });
|
||||
return;
|
||||
} catch (err) {
|
||||
lastError = err;
|
||||
console.warn(`[sync-update-feed] push failed (attempt ${attempt}/${retries})`);
|
||||
if (attempt < retries) {
|
||||
sleepSyncSeconds(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
function mergeOriginUpdates(work) {
|
||||
const fetchRetries = Math.max(
|
||||
1,
|
||||
@@ -252,10 +302,10 @@ function main() {
|
||||
const tmp = fs.mkdtempSync(path.join(tmpRoot, 'dnd-feed-'));
|
||||
const work = path.join(tmp, 'repo');
|
||||
|
||||
const cloneDepth = Math.max(
|
||||
2,
|
||||
Math.min(200, Number.parseInt(process.env.DND_UPDATES_CLONE_DEPTH || '40', 10) || 40),
|
||||
);
|
||||
const squash = feedSquashSingleCommitEnabled();
|
||||
const cloneDepth = squash
|
||||
? Math.max(1, Math.min(200, Number.parseInt(process.env.DND_UPDATES_CLONE_DEPTH || '8', 10) || 8))
|
||||
: Math.max(2, Math.min(200, Number.parseInt(process.env.DND_UPDATES_CLONE_DEPTH || '40', 10) || 40));
|
||||
|
||||
const gh = gitHttpInlineFlags();
|
||||
try {
|
||||
@@ -290,8 +340,17 @@ function main() {
|
||||
runGit(['add', '-A'], work);
|
||||
const st = execFileSync('git', ['status', '--porcelain'], { cwd: work }).toString().trim();
|
||||
if (st) {
|
||||
runGit(['commit', '-m', `update feed ${tag}`], work);
|
||||
pushUpdatesBranch(work);
|
||||
const msg = `update feed ${tag}`;
|
||||
if (squash) {
|
||||
console.warn(
|
||||
'[sync-update-feed] DND_UPDATES_SQUASH_HISTORY=1: одна линия в UPDATES_REPO (orphan + force-with-lease при наличии origin/updates)',
|
||||
);
|
||||
squashUpdatesBranchToSingleCommit(work, msg);
|
||||
pushUpdatesBranchAfterSquash(work);
|
||||
} else {
|
||||
runGit(['commit', '-m', msg], work);
|
||||
pushUpdatesBranch(work);
|
||||
}
|
||||
} else {
|
||||
console.warn('[sync-update-feed] nothing to commit (identical artifacts?)');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user