fix(release): stream large migration checksums from git
All checks were successful
Build and Release FEDEO / verify (push) Successful in 25s
Build and Release FEDEO / build-and-release (push) Successful in 5m50s

This commit is contained in:
2026-09-23 15:37:19 +02:00
parent f6996c1d7b
commit 74c0cf40b3
4 changed files with 125 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
import { execFileSync } from 'node:child_process';
import { execFileSync, spawn } from 'node:child_process';
import { createHash } from 'node:crypto';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
@@ -91,11 +91,33 @@ export function componentVersions(sha, cwd = process.cwd()) {
};
}
export function migrationManifest(sha, cwd = process.cwd()) {
return ['backend/db/migrations', 'push-server/packages/db/drizzle'].flatMap(folder => {
const files = git(['ls-tree', '-r', '--name-only', sha, '--', folder], cwd);
return files ? files.split('\n').filter(path => path.endsWith('.sql')).map(path => ({
path, sha256: createHash('sha256').update(execFileSync('git', ['show', `${sha}:${path}`], { cwd })).digest('hex'),
})) : [];
function gitBlobSha256(reference, cwd) {
return new Promise((resolve, reject) => {
const child = spawn('git', ['cat-file', 'blob', reference], { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
const hash = createHash('sha256');
let stderr = '';
const fail = message => reject(new Error(`Prüfsumme für ${reference} fehlgeschlagen: ${message}`));
// Reference-data migrations can exceed 90 MB. Hash raw chunks without
// buffering the entire blob or altering whitespace/encoding.
child.stdout.on('data', chunk => hash.update(chunk));
child.stderr.setEncoding('utf8');
child.stderr.on('data', chunk => { stderr = (stderr + chunk).slice(0, 8192); });
child.once('error', error => fail(error.message));
for (const stream of [child.stdout, child.stderr]) {
stream.once('error', error => { child.kill(); fail(error.message); });
}
child.once('close', (code, signal) => {
if (code !== 0) fail(`git cat-file (Exit ${code ?? signal}): ${stderr.trim()}`);
else resolve(hash.digest('hex'));
});
});
}
export async function migrationManifest(sha, cwd = process.cwd()) {
const files = git(['ls-tree', '-r', '-z', '--name-only', sha, '--',
'backend/db/migrations', 'push-server/packages/db/drizzle'], cwd)
.split('\0').filter(path => path.endsWith('.sql'));
const manifest = [];
for (const path of files) manifest.push({ path, sha256: await gitBlobSha256(`${sha}:${path}`, cwd) });
return manifest;
}