The Name collision strategy dropdown (Configuration → GitHub Configuration → Duplicate name handling; field starredDuplicateStrategy) does not persist. Changing it from repo-owner to owner-repo, navigating away, and returning shows it reverted — and repos are still created with the repo-owner pattern.
Root cause
The field was absent from both directions of the UI↔DB config mapper (config-mapper.ts):
Save — mapUiToDbConfig never included starredDuplicateStrategy, so it was dropped before the DB write (the save API writes exactly what the mapper returns).
Load — mapDbToUiConfig never read it, so the UI fell back to the "suffix" (repo-owner) default on every reload.
Mirror logic — gitea.ts then read undefined and also defaulted to suffix, so the user's choice never took effect anywhere.
It has been broken since the field was introduced (git log -S shows it was never in the mapper). The schema/type/UI/mirror-logic all had it — only the persistence layer was missing. This matches the reporter's observation that other settings on the page save fine; only this one doesn't.
Fix
Map starredDuplicateStrategy in bothmapUiToDbConfig and mapDbToUiConfig (defaulting to suffix, no migration — it lives in the github_config JSON blob).
Add a STARRED_DUPLICATE_STRATEGY env var for parity (the reporter couldn't even work around it via compose because no env var existed) + docs.
Round-trip tests covering save, load, save-default, and the missing-field read default.
Verification
CI-equivalent on a clean checkout + this patch: bun test343 pass / 0 fail, bun test:migrations ✓, astro build ✓.
Real persistence round-trip through the actual SQLite JSON column:
mapUiToDbConfig -> github_config.starredDuplicateStrategy: prefix
read back from SQLite : prefix
mapDbToUiConfig -> UI starredDuplicateStrategy : prefix
legacy DB row (no field) -> defaults to : suffix
PERSISTENCE FIXED: "owner-repo" (prefix) survives save -> SQLite -> reload ✅
Note: the dropdown still intentionally exposes only suffix/prefix (the third schema value owner-org remains hidden) — out of scope here.
🔄 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/328
**Author:** [@arunavo4](https://github.com/arunavo4)
**Created:** 6/19/2026
**Status:** ✅ Merged
**Merged:** 6/19/2026
**Merged by:** [@arunavo4](https://github.com/arunavo4)
**Base:** `main` ← **Head:** `fix/starred-duplicate-strategy-persist`
---
### 📝 Commits (1)
- [`2f32351`](https://github.com/RayLabsHQ/gitea-mirror/commit/2f323517a640117567b788802391c8e1d408a77a) fix(config): persist Name Collision Strategy (starredDuplicateStrategy) (#326)
### 📊 Changes
**4 files changed** (+39 additions, -0 deletions)
<details>
<summary>View changed files</summary>
📝 `docs/ENVIRONMENT_VARIABLES.md` (+1 -0)
📝 `src/lib/env-config-loader.ts` (+3 -0)
📝 `src/lib/utils/config-mapper.test.ts` (+33 -0)
📝 `src/lib/utils/config-mapper.ts` (+2 -0)
</details>
### 📄 Description
Fixes #326.
## Problem
The **Name collision strategy** dropdown (Configuration → GitHub Configuration → *Duplicate name handling*; field `starredDuplicateStrategy`) does not persist. Changing it from `repo-owner` to `owner-repo`, navigating away, and returning shows it reverted — and repos are still created with the `repo-owner` pattern.
## Root cause
The field was **absent from both directions of the UI↔DB config mapper** (`config-mapper.ts`):
- **Save** — `mapUiToDbConfig` never included `starredDuplicateStrategy`, so it was dropped before the DB write (the save API writes exactly what the mapper returns).
- **Load** — `mapDbToUiConfig` never read it, so the UI fell back to the `"suffix"` (`repo-owner`) default on every reload.
- **Mirror logic** — `gitea.ts` then read `undefined` and also defaulted to `suffix`, so the user's choice never took effect anywhere.
It has been broken since the field was introduced (`git log -S` shows it was never in the mapper). The schema/type/UI/mirror-logic all had it — only the persistence layer was missing. This matches the reporter's observation that *other* settings on the page save fine; only this one doesn't.
## Fix
- Map `starredDuplicateStrategy` in **both** `mapUiToDbConfig` and `mapDbToUiConfig` (defaulting to `suffix`, no migration — it lives in the `github_config` JSON blob).
- Add a `STARRED_DUPLICATE_STRATEGY` env var for parity (the reporter couldn't even work around it via compose because no env var existed) + docs.
- Round-trip tests covering save, load, save-default, and the missing-field read default.
## Verification
CI-equivalent on a clean checkout + this patch: `bun test` **343 pass / 0 fail**, `bun test:migrations` ✓, `astro build` ✓.
Real persistence round-trip through the actual SQLite JSON column:
```
mapUiToDbConfig -> github_config.starredDuplicateStrategy: prefix
read back from SQLite : prefix
mapDbToUiConfig -> UI starredDuplicateStrategy : prefix
legacy DB row (no field) -> defaults to : suffix
PERSISTENCE FIXED: "owner-repo" (prefix) survives save -> SQLite -> reload ✅
```
Note: the dropdown still intentionally exposes only `suffix`/`prefix` (the third schema value `owner-org` remains hidden) — out of scope here.
---
<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/328
Author: @arunavo4
Created: 6/19/2026
Status: ✅ Merged
Merged: 6/19/2026
Merged by: @arunavo4
Base:
main← Head:fix/starred-duplicate-strategy-persist📝 Commits (1)
2f32351fix(config): persist Name Collision Strategy (starredDuplicateStrategy) (#326)📊 Changes
4 files changed (+39 additions, -0 deletions)
View changed files
📝
docs/ENVIRONMENT_VARIABLES.md(+1 -0)📝
src/lib/env-config-loader.ts(+3 -0)📝
src/lib/utils/config-mapper.test.ts(+33 -0)📝
src/lib/utils/config-mapper.ts(+2 -0)📄 Description
Fixes #326.
Problem
The Name collision strategy dropdown (Configuration → GitHub Configuration → Duplicate name handling; field
starredDuplicateStrategy) does not persist. Changing it fromrepo-ownertoowner-repo, navigating away, and returning shows it reverted — and repos are still created with therepo-ownerpattern.Root cause
The field was absent from both directions of the UI↔DB config mapper (
config-mapper.ts):mapUiToDbConfignever includedstarredDuplicateStrategy, so it was dropped before the DB write (the save API writes exactly what the mapper returns).mapDbToUiConfignever read it, so the UI fell back to the"suffix"(repo-owner) default on every reload.gitea.tsthen readundefinedand also defaulted tosuffix, so the user's choice never took effect anywhere.It has been broken since the field was introduced (
git log -Sshows it was never in the mapper). The schema/type/UI/mirror-logic all had it — only the persistence layer was missing. This matches the reporter's observation that other settings on the page save fine; only this one doesn't.Fix
starredDuplicateStrategyin bothmapUiToDbConfigandmapDbToUiConfig(defaulting tosuffix, no migration — it lives in thegithub_configJSON blob).STARRED_DUPLICATE_STRATEGYenv var for parity (the reporter couldn't even work around it via compose because no env var existed) + docs.Verification
CI-equivalent on a clean checkout + this patch:
bun test343 pass / 0 fail,bun test:migrations✓,astro build✓.Real persistence round-trip through the actual SQLite JSON column:
Note: the dropdown still intentionally exposes only
suffix/prefix(the third schema valueowner-orgremains hidden) — out of scope here.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.