fix: handle stale Gitea webhook bridge events

This commit is contained in:
Codex
2026-07-09 14:50:36 +02:00
parent 2bcbc634e0
commit d11d132932
4 changed files with 74 additions and 16 deletions
@@ -16,7 +16,7 @@ const giteaBaseUrl = requiredEnv("UNIDESK_GITEA_SERVICE_BASE_URL").replace(/\/+$
const githubAuthHeader = `Authorization: Basic ${Buffer.from(`x-access-token:${githubToken}`).toString("base64")}`;
const giteaAuthHeader = `Authorization: Basic ${Buffer.from(`${giteaUsername}:${giteaPassword}`).toString("base64")}`;
const running = new Set();
const syncStates = new Map();
createServer(async (req, res) => {
const startedAt = Date.now();
@@ -49,21 +49,18 @@ createServer(async (req, res) => {
writeJson(res, 202, { ok: true, event, repository, ref, disposition: "ignored-repo-or-ref", valuesPrinted: false });
return;
}
if (running.has(repo.key)) {
writeJson(res, 202, { ok: true, event, repository, ref, disposition: "already-running", repo: repo.key, valuesPrinted: false });
const state = syncState(repo.key);
if (state.running) {
state.pending = true;
log({ event: "github-to-gitea-sync-queued", repo: repo.key, repository, ref, disposition: "pending-rerun", valuesPrinted: false });
writeJson(res, 202, { ok: true, event, repository, ref, disposition: "queued-after-running", repo: repo.key, valuesPrinted: false });
return;
}
running.add(repo.key);
state.running = true;
state.pending = false;
writeJson(res, 202, { ok: true, event, repository, ref, repo: repo.key, disposition: "accepted", valuesPrinted: false });
setImmediate(() => {
try {
const sync = syncRepository(repo);
log({ event: "github-to-gitea-sync", repo: repo.key, ok: sync.ok, sourceCommit: sync.sourceCommit, snapshotRef: sync.snapshotRef, error: sync.error ? redact(sync.error) : null, elapsedMs: Date.now() - startedAt, valuesPrinted: false });
} catch (error) {
log({ event: "github-to-gitea-sync-error", repo: repo.key, ok: false, error: redact(String(error?.message || error)), elapsedMs: Date.now() - startedAt, valuesPrinted: false });
} finally {
running.delete(repo.key);
}
runSyncLoop(repo, state, startedAt);
});
} catch (error) {
log({ event: "github-to-gitea-sync-error", ok: false, error: String(error?.message || error), valuesPrinted: false });
@@ -73,6 +70,31 @@ createServer(async (req, res) => {
log({ event: "github-to-gitea-sync-listening", port, path, repos: repos.map((repo) => repo.key), valuesPrinted: false });
});
function syncState(key) {
let state = syncStates.get(key);
if (!state) {
state = { running: false, pending: false };
syncStates.set(key, state);
}
return state;
}
function runSyncLoop(repo, state, startedAt) {
let attempt = 0;
try {
do {
state.pending = false;
attempt += 1;
const sync = syncRepository(repo);
log({ event: "github-to-gitea-sync", repo: repo.key, ok: sync.ok, sourceCommit: sync.sourceCommit, snapshotRef: sync.snapshotRef, error: sync.error ? redact(sync.error) : null, attempt, pendingRerun: state.pending, elapsedMs: Date.now() - startedAt, valuesPrinted: false });
} while (state.pending);
} catch (error) {
log({ event: "github-to-gitea-sync-error", repo: repo.key, ok: false, error: redact(String(error?.message || error)), attempt, elapsedMs: Date.now() - startedAt, valuesPrinted: false });
} finally {
state.running = false;
}
}
function syncRepository(repo) {
const work = mkdtempSync(join(tmpdir(), `gitea-gh-sync-${repo.key}-`));
try {