mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-07-22 11:38:40 -05:00
[GH-ISSUE #343] [Bug] Gitea "Mirror Organization" ignores destination overrides and can mirror org repos to user's personal account #7071
Reference in New Issue
Block a user
Originally created by @YuzuZensai on GitHub (Jul 15, 2026).
Original GitHub issue: https://github.com/RayLabsHQ/gitea-mirror/issues/343
Hi, thanks for making this tool! I faced some issues while trying to mirror organization repos. The bulk Mirror Organization action does not follow the documented destination priority
(Repository override -> Organization override -> Strategy default, starred repos always follow starred-repo mode)
This results in
Destination Organization overrides (org-level and per-repo) are silently ignored. The repos land in whatever target the mirror strategy would normally pick, as if no override had been set. With the default
preservestrategy that means a Gitea org named after the GitHub org, and withsingle-orgit means the globally configured destination organization.With the
mixedstrategy, all of an org's repos land in the user's personal account instead of preserving org structure.Starred repos owned by an org the user is also a member of (and thus reachable via that org's own "Mirror Organization" button) don't follow the starred-repos destination when caught up in that org's bulk mirror, since the query matches by org name only and does not exclude starred repos. Under
preserve/single-orgthey are routed into the org's target, and undermixedthey land in the personal account (symptom 2). Only theflat-userbulk path happened to resolve starred mode correctly.Mirroring the same repos individually from the Repositories page works fine, and the Organizations UI already shows the correct destination when an override is applied.
Steps to reproduce
Scenario 1 - overrides ignored (default
preservestrategy)A->B.A.Expected: repos mirror into Gitea org
B.Actual: a Gitea org
Ais created and repos mirror there.Scenario 2 -
mixedstrategy goes to user's personal accountA.Expected: repos mirror into Gitea org
A.Actual: repos mirror into user's personal account.
Scenario 3 - starred org repo ignores starred-repo mode
starredReposModeat its default,dedicated-org, withstarredReposOrgunset.A, and star a repo owned byA, e.g.A/tools, that you did not create yourself.A.Expected:
A/toolsmirrors into the dedicated Gitea orgstarred. Starred status takes priority over org membership and strategy.Actual:
A/toolsmirrors into user's personal account, indistinguishable from any other repo caught by Scenario 2.Root cause
The canonical resolver
getGiteaRepoOwnerAsync(), insrc/lib/gitea.ts, follows the documented priority correctly, and every mirror path uses it, except two that have their own logic.mirrorGitHubOrgToGitea()picked the target from the strategy alone and never readorganization.destinationOrgor per-repodestinationOrg(Scenario 1)Its per-repo dispatch only checked for
flat-uservs. everything else, somixed, which fell into the fallback above, sent every org repo todefaultOwner(Scenario 2).On the non-
flat-userpath, per-repo overrides and starred-repo mode were never used (symptoms 1 and 3). Only theflat-userbranch worked correctly, becausemirrorGithubRepoToGitea()calls the canonical resolver itselfWhy
mixedends up in user's personal accountgiteaOrgIdis declaredlet giteaOrgId: number;and the fallback branch never sets it, so formixedit isundefinedat runtime (hidden by thegiteaOrgId!assertion)The migrate payload is built with
uid: giteaOrgId, givinguid: undefined, andJSON.stringifydropsundefinedvalues. The request body sent toPOST /api/v1/repos/migratehas nouidat allGitea's migrate handler defaults a missing owner to the authenticated user
So every repo of the org ends up under the token's user account. The actual wrong destination comes from Gitea defaulting the missing
uid, which is why the logs and the DB still looked consistent even though the location was wrong.Crash recovery also had the same problem. It pre-routed org repos by GitHub org name using the legacy(?)
preserveOrgStructureflag, skipping overrides andmirrorStrategy:@YuzuZensai commented on GitHub (Jul 15, 2026):
Also, the Repositories page doesn't show org-level destination overrides for the repo in the organizations column.
So if you set an org override but without repo override, the Repositories page still shows the old strategy-based destination, even though sync will use the override. Only the Organizations page shows it correctly (org-wide).
I left this out of the PR since I wasn't sure if it's intentional design choice or not. Happy to add it if needed.