Added canonical fields and unique safeguards so duplicates are caught case‑insensitively: schema now stores normalized_full_name / normalized_name with unique
indexes, and the migration backfills values while pruning extra rows per user_id (src/lib/db/schema.ts:329-478, drizzle/0007_whole_hellion.sql).
Organization/repository sync routes normalize input, expose an optional force flag to reuse the existing record, and rely on the new columns for conflict checks
(src/pages/api/sync/organization.ts:16-200, src/pages/api/sync/repository.ts:17-182, src/pages/api/sync/index.ts:73-182, src/lib/scheduler-service.ts:100-207,
src/lib/repo-utils.ts:23-55).
UI now blocks duplicates by default but offers a confirmation dialog to refresh the existing entry via the force flow; Sonner warnings surface the duplicate
before the modal, and add/reset logic keeps forms tidy (src/components/organizations/Organization.tsx:200-334, 813-880, src/components/repositories/
Repository.tsx:640-724, 1285-1347, src/components/organizations/AddOrganizationDialog.tsx:19-141, src/components/repositories/AddRepositoryDialog.tsx:19-104).
Added safe delete flows that only prune Gitea Mirror data: new DELETE endpoints handle cleanup (org deletes cascade to imported repos, repo deletes
remove mirror job history) and the UI exposes red “Delete from Mirror” actions with confirmation copy clarifying nothing happens on Gitea (src/pages/api/
organizations/[id].ts:65-119, src/pages/api/repositories/[id].ts:65-113, src/components/organizations/OrganizationsList.tsx:18-136, src/components/repositories/
RepositoryTable.tsx:1-714).
Request/response types reflect the new behaviour (src/types/organizations.ts:23-34, src/types/Repository.ts:79-94).
🔄 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/138
**Author:** [@arunavo4](https://github.com/arunavo4)
**Created:** 10/27/2025
**Status:** ✅ Merged
**Merged:** 10/30/2025
**Merged by:** [@arunavo4](https://github.com/arunavo4)
**Base:** `main` ← **Head:** `issue-132-org-repo-duplicates`
---
### 📝 Commits (3)
- [`8d96e17`](https://github.com/RayLabsHQ/gitea-mirror/commit/8d96e176b4d8a34f5d6b715e154c097bcbe1cd2d) fix: prevent duplicate orgs and repos
- [`bda8d10`](https://github.com/RayLabsHQ/gitea-mirror/commit/bda8d10f1044245676c856616840f834205448be) ci: build arm64 images in PR pipeline
- [`3b8fc99`](https://github.com/RayLabsHQ/gitea-mirror/commit/3b8fc99f066ebb1813f7519ad892ad84f1ebea4f) workaround to get rid of unknown/unknown in OS arch
### 📊 Changes
**21 files changed** (+2808 additions, -129 deletions)
<details>
<summary>View changed files</summary>
📝 `.github/workflows/docker-build.yml` (+9 -5)
➕ `drizzle/0007_whole_hellion.sql` (+18 -0)
➕ `drizzle/meta/0007_snapshot.json` (+1999 -0)
📝 `drizzle/meta/_journal.json` (+7 -0)
📝 `src/components/organizations/AddOrganizationDialog.tsx` (+13 -3)
📝 `src/components/organizations/Organization.tsx` (+190 -9)
📝 `src/components/organizations/OrganizationsList.tsx` (+45 -15)
📝 `src/components/repositories/AddRepositoryDialog.tsx` (+11 -1)
📝 `src/components/repositories/Repository.tsx` (+198 -10)
📝 `src/components/repositories/RepositoryTable.tsx` (+20 -2)
📝 `src/lib/db/schema.ts` (+6 -0)
📝 `src/lib/repo-utils.test.ts` (+1 -1)
📝 `src/lib/repo-utils.ts` (+1 -1)
📝 `src/lib/scheduler-service.ts` (+8 -8)
📝 `src/pages/api/organizations/[id].ts` (+58 -1)
📝 `src/pages/api/repositories/[id].ts` (+53 -2)
📝 `src/pages/api/sync/index.ts` (+9 -7)
📝 `src/pages/api/sync/organization.ts` (+93 -46)
📝 `src/pages/api/sync/repository.ts` (+65 -16)
📝 `src/types/Repository.ts` (+2 -1)
_...and 1 more files_
</details>
### 📄 Description
Highlights | Closes #132
- Added canonical fields and unique safeguards so duplicates are caught case‑insensitively: schema now stores normalized_full_name / normalized_name with unique
indexes, and the migration backfills values while pruning extra rows per user_id (src/lib/db/schema.ts:329-478, drizzle/0007_whole_hellion.sql).
- Organization/repository sync routes normalize input, expose an optional force flag to reuse the existing record, and rely on the new columns for conflict checks
(src/pages/api/sync/organization.ts:16-200, src/pages/api/sync/repository.ts:17-182, src/pages/api/sync/index.ts:73-182, src/lib/scheduler-service.ts:100-207,
src/lib/repo-utils.ts:23-55).
- UI now blocks duplicates by default but offers a confirmation dialog to refresh the existing entry via the force flow; Sonner warnings surface the duplicate
before the modal, and add/reset logic keeps forms tidy (src/components/organizations/Organization.tsx:200-334, 813-880, src/components/repositories/
Repository.tsx:640-724, 1285-1347, src/components/organizations/AddOrganizationDialog.tsx:19-141, src/components/repositories/AddRepositoryDialog.tsx:19-104).
- Added safe delete flows that only prune Gitea Mirror data: new DELETE endpoints handle cleanup (org deletes cascade to imported repos, repo deletes
remove mirror job history) and the UI exposes red “Delete from Mirror” actions with confirmation copy clarifying nothing happens on Gitea (src/pages/api/
organizations/[id].ts:65-119, src/pages/api/repositories/[id].ts:65-113, src/components/organizations/OrganizationsList.tsx:18-136, src/components/repositories/
RepositoryTable.tsx:1-714).
- Request/response types reflect the new behaviour (src/types/organizations.ts:23-34, src/types/Repository.ts:79-94).
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/RayLabsHQ/gitea-mirror/pull/138
Author: @arunavo4
Created: 10/27/2025
Status: ✅ Merged
Merged: 10/30/2025
Merged by: @arunavo4
Base:
main← Head:issue-132-org-repo-duplicates📝 Commits (3)
8d96e17fix: prevent duplicate orgs and reposbda8d10ci: build arm64 images in PR pipeline3b8fc99workaround to get rid of unknown/unknown in OS arch📊 Changes
21 files changed (+2808 additions, -129 deletions)
View changed files
📝
.github/workflows/docker-build.yml(+9 -5)➕
drizzle/0007_whole_hellion.sql(+18 -0)➕
drizzle/meta/0007_snapshot.json(+1999 -0)📝
drizzle/meta/_journal.json(+7 -0)📝
src/components/organizations/AddOrganizationDialog.tsx(+13 -3)📝
src/components/organizations/Organization.tsx(+190 -9)📝
src/components/organizations/OrganizationsList.tsx(+45 -15)📝
src/components/repositories/AddRepositoryDialog.tsx(+11 -1)📝
src/components/repositories/Repository.tsx(+198 -10)📝
src/components/repositories/RepositoryTable.tsx(+20 -2)📝
src/lib/db/schema.ts(+6 -0)📝
src/lib/repo-utils.test.ts(+1 -1)📝
src/lib/repo-utils.ts(+1 -1)📝
src/lib/scheduler-service.ts(+8 -8)📝
src/pages/api/organizations/[id].ts(+58 -1)📝
src/pages/api/repositories/[id].ts(+53 -2)📝
src/pages/api/sync/index.ts(+9 -7)📝
src/pages/api/sync/organization.ts(+93 -46)📝
src/pages/api/sync/repository.ts(+65 -16)📝
src/types/Repository.ts(+2 -1)...and 1 more files
📄 Description
Highlights | Closes #132
indexes, and the migration backfills values while pruning extra rows per user_id (src/lib/db/schema.ts:329-478, drizzle/0007_whole_hellion.sql).
(src/pages/api/sync/organization.ts:16-200, src/pages/api/sync/repository.ts:17-182, src/pages/api/sync/index.ts:73-182, src/lib/scheduler-service.ts:100-207,
src/lib/repo-utils.ts:23-55).
before the modal, and add/reset logic keeps forms tidy (src/components/organizations/Organization.tsx:200-334, 813-880, src/components/repositories/
Repository.tsx:640-724, 1285-1347, src/components/organizations/AddOrganizationDialog.tsx:19-141, src/components/repositories/AddRepositoryDialog.tsx:19-104).
remove mirror job history) and the UI exposes red “Delete from Mirror” actions with confirmation copy clarifying nothing happens on Gitea (src/pages/api/
organizations/[id].ts:65-119, src/pages/api/repositories/[id].ts:65-113, src/components/organizations/OrganizationsList.tsx:18-136, src/components/repositories/
RepositoryTable.tsx:1-714).
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.