feat(release): automate versioned releases on main
This commit is contained in:
25
scripts/release/lock.mjs
Normal file
25
scripts/release/lock.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { setTimeout as sleep } from 'node:timers/promises';
|
||||
import { git } from './lib.mjs';
|
||||
|
||||
export const lockRef = 'refs/heads/automation/release-lock';
|
||||
|
||||
export async function acquireLock({ runGit = git, wait = sleep, attempts = 480, ref = lockRef } = {}) {
|
||||
const lockSha = runGit(['-c', 'user.name=FEDEO Release', '-c', 'user.email=release@fedeo.de',
|
||||
'commit-tree', 'HEAD^{tree}', '-p', 'HEAD', '-m', `chore(release): lock ${randomUUID()}`]);
|
||||
for (let attempt = 0; attempt < attempts; attempt++) {
|
||||
const existing = runGit(['ls-remote', 'origin', ref]);
|
||||
if (!existing) {
|
||||
try {
|
||||
// An empty lease means the ref MUST NOT exist, even if another runner just created it.
|
||||
runGit(['push', `--force-with-lease=${ref}:`, 'origin', `${lockSha}:${ref}`]);
|
||||
return () => runGit(['push', `--force-with-lease=${ref}:${lockSha}`, 'origin', `:${ref}`]);
|
||||
} catch (error) {
|
||||
if (!runGit(['ls-remote', 'origin', ref])) throw error;
|
||||
}
|
||||
}
|
||||
if (attempt % 4 === 0) console.log('Ein anderer Release läuft; warte auf die Git-Sperre.');
|
||||
await wait(15_000);
|
||||
}
|
||||
throw new Error(`Release-Sperre ${ref} bleibt belegt. Siehe docs/releases.md zur Wiederaufnahme.`);
|
||||
}
|
||||
Reference in New Issue
Block a user