[PR #206] [MERGED] feat: smart force-push protection with backup strategies #1082

Closed
opened 2026-04-19 13:39:03 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/RayLabsHQ/gitea-mirror/pull/206
Author: @arunavo4
Created: 3/2/2026
Status: Merged
Merged: 3/2/2026
Merged by: @arunavo4

Base: mainHead: feat/smart-force-push-protection


📝 Commits (7)

  • ba7789c feat: smart force-push protection with backup strategies (#187)
  • 12e58b4 fix: resolve four bugs in smart force-push protection
  • 4da8645 test(e2e): migrate backup tests from backupBeforeSync to backupStrategy
  • 6bb109c docs: add backup strategy UI screenshot
  • f1175d6 refactor(ui): move Destructive Update Protection to GitHub config tab
  • 3663e91 docs: add force-push protection documentation and Beta badge
  • 901050f fix(ui): match Beta badge style to Git LFS badge

📊 Changes

24 files changed (+1706 additions, -145 deletions)

View changed files

.github/screenshots/backup-strategy-ui.png (+0 -0)
📝 README.md (+2 -0)
docs/FORCE_PUSH_PROTECTION.md (+179 -0)
📝 src/components/config/ConfigTabs.tsx (+12 -1)
📝 src/components/config/GitHubConfigForm.tsx (+146 -7)
📝 src/components/config/GiteaConfigForm.tsx (+1 -73)
📝 src/components/repositories/Repository.tsx (+76 -0)
📝 src/components/repositories/RepositoryTable.tsx (+74 -2)
📝 src/lib/db/schema.ts (+11 -1)
📝 src/lib/gitea-enhanced.ts (+128 -40)
📝 src/lib/repo-backup.test.ts (+134 -1)
📝 src/lib/repo-backup.ts (+92 -2)
📝 src/lib/scheduler-service.ts (+19 -1)
📝 src/lib/utils.ts (+2 -0)
📝 src/lib/utils/config-defaults.ts (+2 -1)
📝 src/lib/utils/config-mapper.ts (+2 -0)
src/lib/utils/force-push-detection.test.ts (+319 -0)
src/lib/utils/force-push-detection.ts (+286 -0)
src/pages/api/job/approve-sync.ts (+202 -0)
📝 src/types/Repository.ts (+1 -0)

...and 4 more files

📄 Description

Summary

Closes #187

  • Replaces backupBeforeSync: boolean with backupStrategy enum: disabled, always, on-force-push (default), block-on-force-push
  • Detects force-pushes by comparing branch SHAs between Gitea and GitHub APIs before sync — lightweight, no git cloning
  • Adds pending-approval repo status with approve/dismiss buttons for block-on-force-push mode
  • Fail-open design: detection errors never block sync; transient API errors skip that branch rather than producing false positives

UI: Destructive Update Protection

Screenshot 2026-03-02 at 3 14 49 PM

Backup strategy modes

Strategy Detection Backup Sync Storage Cost
disabled No No Always Zero
always No Every sync After backup High (current behavior)
on-force-push Yes Only when detected After backup Near-zero normally
block-on-force-push Yes No Blocked, needs approval Zero

Files changed

  • Schema/types: backupStrategy enum, pending-approval status
  • Force-push detection: New module at src/lib/utils/force-push-detection.ts
  • Backup resolver: Strategy resolution with backward-compat (backupBeforeSync: truealways)
  • Sync flow: Detection integrated before mirror-sync call
  • Approval API: POST /api/job/approve-sync with approve/dismiss actions
  • UI: 4-option strategy selector in config, amber badge + action buttons in repo table
  • Config mapper: backupStrategy persisted through save/load round-trip

Test plan

  • bun test — 161 pass, 0 fail
  • bun run build — no type errors
  • Manual: set each strategy mode, trigger sync, verify behavior
  • Manual: block-on-force-push — verify repo shows pending-approval, approve/dismiss work
  • Manual: backward compat — old config with only backupBeforeSync: true resolves to always

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/RayLabsHQ/gitea-mirror/pull/206 **Author:** [@arunavo4](https://github.com/arunavo4) **Created:** 3/2/2026 **Status:** ✅ Merged **Merged:** 3/2/2026 **Merged by:** [@arunavo4](https://github.com/arunavo4) **Base:** `main` ← **Head:** `feat/smart-force-push-protection` --- ### 📝 Commits (7) - [`ba7789c`](https://github.com/RayLabsHQ/gitea-mirror/commit/ba7789cf40b4a68a436bafc139622b2b85f3a0df) feat: smart force-push protection with backup strategies (#187) - [`12e58b4`](https://github.com/RayLabsHQ/gitea-mirror/commit/12e58b4045cdba9e83dc06002679bf314eca875a) fix: resolve four bugs in smart force-push protection - [`4da8645`](https://github.com/RayLabsHQ/gitea-mirror/commit/4da8645b07bbc3403ac826f94487ec0875c1a8dc) test(e2e): migrate backup tests from backupBeforeSync to backupStrategy - [`6bb109c`](https://github.com/RayLabsHQ/gitea-mirror/commit/6bb109ce746bed8a60314ae1996b3767d8b6dd24) docs: add backup strategy UI screenshot - [`f1175d6`](https://github.com/RayLabsHQ/gitea-mirror/commit/f1175d6dc0a69056cfa0674b74a93c20347307a4) refactor(ui): move Destructive Update Protection to GitHub config tab - [`3663e91`](https://github.com/RayLabsHQ/gitea-mirror/commit/3663e9174d57551c31f1863b5428e76103b01365) docs: add force-push protection documentation and Beta badge - [`901050f`](https://github.com/RayLabsHQ/gitea-mirror/commit/901050f563c819b727bbcc4b54874ca19cc82c20) fix(ui): match Beta badge style to Git LFS badge ### 📊 Changes **24 files changed** (+1706 additions, -145 deletions) <details> <summary>View changed files</summary> ➕ `.github/screenshots/backup-strategy-ui.png` (+0 -0) 📝 `README.md` (+2 -0) ➕ `docs/FORCE_PUSH_PROTECTION.md` (+179 -0) 📝 `src/components/config/ConfigTabs.tsx` (+12 -1) 📝 `src/components/config/GitHubConfigForm.tsx` (+146 -7) 📝 `src/components/config/GiteaConfigForm.tsx` (+1 -73) 📝 `src/components/repositories/Repository.tsx` (+76 -0) 📝 `src/components/repositories/RepositoryTable.tsx` (+74 -2) 📝 `src/lib/db/schema.ts` (+11 -1) 📝 `src/lib/gitea-enhanced.ts` (+128 -40) 📝 `src/lib/repo-backup.test.ts` (+134 -1) 📝 `src/lib/repo-backup.ts` (+92 -2) 📝 `src/lib/scheduler-service.ts` (+19 -1) 📝 `src/lib/utils.ts` (+2 -0) 📝 `src/lib/utils/config-defaults.ts` (+2 -1) 📝 `src/lib/utils/config-mapper.ts` (+2 -0) ➕ `src/lib/utils/force-push-detection.test.ts` (+319 -0) ➕ `src/lib/utils/force-push-detection.ts` (+286 -0) ➕ `src/pages/api/job/approve-sync.ts` (+202 -0) 📝 `src/types/Repository.ts` (+1 -0) _...and 4 more files_ </details> ### 📄 Description ## Summary Closes #187 - Replaces `backupBeforeSync: boolean` with `backupStrategy` enum: `disabled`, `always`, `on-force-push` (default), `block-on-force-push` - Detects force-pushes by comparing branch SHAs between Gitea and GitHub APIs before sync — lightweight, no git cloning - Adds `pending-approval` repo status with approve/dismiss buttons for `block-on-force-push` mode - Fail-open design: detection errors never block sync; transient API errors skip that branch rather than producing false positives ### UI: Destructive Update Protection <img width="595" height="370" alt="Screenshot 2026-03-02 at 3 14 49 PM" src="https://github.com/user-attachments/assets/4de8c342-2c0c-4a2e-94fd-09ae699c1f61" /> ### Backup strategy modes | Strategy | Detection | Backup | Sync | Storage Cost | |----------|-----------|--------|------|-------------| | `disabled` | No | No | Always | Zero | | `always` | No | Every sync | After backup | High (current behavior) | | `on-force-push` | Yes | Only when detected | After backup | Near-zero normally | | `block-on-force-push` | Yes | No | Blocked, needs approval | Zero | ### Files changed - **Schema/types**: `backupStrategy` enum, `pending-approval` status - **Force-push detection**: New module at `src/lib/utils/force-push-detection.ts` - **Backup resolver**: Strategy resolution with backward-compat (`backupBeforeSync: true` → `always`) - **Sync flow**: Detection integrated before mirror-sync call - **Approval API**: `POST /api/job/approve-sync` with approve/dismiss actions - **UI**: 4-option strategy selector in config, amber badge + action buttons in repo table - **Config mapper**: `backupStrategy` persisted through save/load round-trip ## Test plan - [x] `bun test` — 161 pass, 0 fail - [x] `bun run build` — no type errors - [ ] Manual: set each strategy mode, trigger sync, verify behavior - [ ] Manual: `block-on-force-push` — verify repo shows `pending-approval`, approve/dismiss work - [ ] Manual: backward compat — old config with only `backupBeforeSync: true` resolves to `always` --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-19 13:39:03 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea-mirror#1082