mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-08-12 22:21:52 +08:00
dd1c42264e
* fix: stop snapshot-row zombies + flapping force-push on deleted branches
Two bugs caused Simple-WP-Helpdesk to accumulate one orphan
"Snapshot created" job row per scheduled sync — 7 zombies in 24h
against a deleted GitHub branch (`fix/v4.0.2-webhook-comment-author`).
(1) gitea-enhanced.ts:522 created the post-snapshot job record with
status="syncing". The snapshot was already complete at that point
(createPreSyncBundleBackup had returned), and no later code path
advanced the row to a terminal status — it just lingered. Set
status="synced" to reflect reality.
(2) force-push-detection treated any Gitea branch missing from GitHub
as a "deleted" force-push. But gitea-mirror is one-way (GitHub →
Gitea), so deletions never propagate back to the Gitea mirror —
the branch lingers in Gitea forever, the missing-from-GitHub condition
holds on every subsequent sync, and detection re-fires endlessly.
Each re-fire triggered backupBeforeSync=true to take a fresh snapshot
of the exact same state we already backed up the previous cycle.
Fix: detector accepts an `acknowledgedDeletions: { branch, giteaSha }[]`
list (persisted in RepositoryMetadataState). A Gitea branch missing
from GitHub is suppressed when its current giteaSha matches an entry.
If the giteaSha later changes (branch restored, then re-deleted with
new history), the entry won't match and detection fires again — back
up the new state, then acknowledge the new SHA. After a successful
snapshot, the call site appends each just-backed-up "deleted" branch
to the acknowledged list and persists the metadata blob.
Hoists parseRepositoryMetadataState above the backup-strategy block so
both the detection-time read and post-snapshot append happen against
the same in-memory state object; the existing metadata-mirror block
just stops re-declaring it.
Adds 9 new test cases covering:
- deleted branch suppressed when acknowledged at matching giteaSha
- re-flagged when giteaSha differs (restored-then-redeleted)
- mixed deletions (only matching one suppressed)
- undefined list = back-compat (existing callers unaffected)
- acknowledgedDeletions does not suppress "diverged"
- metadata-state parse/serialize round-trips the new field
- legacy metadata defaults acknowledgedDeletions to []
- malformed entries dropped without throwing
All 76 tests in the affected suites pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: acknowledge deletion before backup, not after, to fix concurrent-sync race
When two sync invocations fire for the same repo within the same backup
window (observed in prod via UI trigger pipeline: a single click ends up
producing two parallel processWithResilience callbacks that both run
syncGiteaRepoEnhanced), the second invocation's createPreSyncBundleBackup
short-circuits (file already exists from the first), so the second
invocation never reached the acknowledge-push that lived inside the
backup try block. Then both invocations wrote metadata: invocation A
with acknowledgedDeletions=[forged], invocation B (with its stale
in-memory state) with acknowledgedDeletions=[], and B's write landed
last — overwriting A.
Net result: the deletion never got acknowledged, and the next sync
re-detected it, the next-next sync re-detected it, etc. Same flapping
behavior as before the fix.
Fix: move the acknowledge-push to run right after detection, based on
detectionResult.affectedBranches alone. Semantically correct — once
we've detected the branch is gone from GitHub, we know it's a permanent
deletion; whether THIS particular invocation took a backup or
short-circuited is orthogonal (a previous backup on disk is fine, and
in the rare case where no backup ever succeeded, the user can re-trigger
a manual backup). Both concurrent invocations now push the same entry;
both write the same metadata; race is benign.
Verified locally: 59 tests pass across force-push-detection,
gitea-enhanced, repo-backup.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>