getGithubRepositories (used by the main sync, the scheduler, and the repository cleanup service) calls /user/repos with an affiliation parameter that omits organization_member. As a result, repositories owned by organizations the authenticated user belongs to are never returned. This causes several visible symptoms:
Organizations added via the UI appear empty in subsequent syncs — listForOrg populated the repos on first add, but no later call sees them.
The scheduler never picks up org repos for periodic syncs.
The cleanup service, on every restart, sees org repos in the DB but not in the GitHub list, and (with CLEANUP_DELETE_IF_NOT_IN_GITHUB=true) flags them all as orphaned.
Root Cause
PR #283 (feat: add option to exclude collaborator repos from import) changed the affiliation to:
That commit's own message acknowledges the GitHub default:
"GitHub's listForAuthenticatedUser defaults to returning every repo the user has access to (owner + collaborator + organization_member)…"
But the implementation only set two of the three values. organization_member was meant to remain part of the default and was inadvertently dropped.
Three callers are affected:
Caller
File
Effect
Main sync
src/pages/api/sync/index.ts
org repos never imported
Scheduler
src/lib/scheduler-service.ts
org repos missing from periodic syncs
Cleanup service
src/lib/repository-cleanup-service.ts
even with includeCollaboratorReposOverride: true, org repos are invisible → flagged as orphaned
Fix
Always include organization_member in the affiliation, regardless of the includeCollaboratorRepos toggle. The toggle's original semantics from #279/#283 are preserved:
The collaborator-exclusion feature still works as intended; this change only restores the previously missing slot.
Testing
src/lib/github-affiliation.test.ts:
4 existing assertions updated to require organization_member.
New regression test always includes organization_member iterates 5 config combinations (default, includeCollab true/false, override true, override+toggle) to lock the invariant.
bun test src/lib/github-affiliation.test.ts
Steps to Reproduce (pre-fix)
PAT with repo + read:org scope.
Add an organization in the UI — repos appear (this uses listForOrg, which works).
Restart the container or wait for the scheduler.
Org repos disappear from the dashboard; cleanup logs them as orphaned.
After the fix, repos remain consistent across restarts and scheduler runs.
Related
The symptom is mentioned in passing in #254 ("I have a private repo from my org which does not show up at all in gitea-mirror"), but that issue was scoped to Forgejo auth and the side-mention was not addressed. This PR is the first formal report and fix for the org-repo invisibility itself.
🔄 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/286
**Author:** [@riguettodev](https://github.com/riguettodev)
**Created:** 5/15/2026
**Status:** ✅ Merged
**Merged:** 5/16/2026
**Merged by:** [@arunavo4](https://github.com/arunavo4)
**Base:** `main` ← **Head:** `fix/include-org-repos`
---
### 📝 Commits (1)
- [`5c44b27`](https://github.com/RayLabsHQ/gitea-mirror/commit/5c44b2746d91a6d4d519e62bb5980e6c46a7c4d5) fix: include organization_member in /user/repos affiliation
### 📊 Changes
**2 files changed** (+40 additions, -9 deletions)
<details>
<summary>View changed files</summary>
📝 `src/lib/github-affiliation.test.ts` (+33 -8)
📝 `src/lib/github.ts` (+7 -1)
</details>
### 📄 Description
## Summary
`getGithubRepositories` (used by the main sync, the scheduler, and the repository cleanup service) calls `/user/repos` with an `affiliation` parameter that omits `organization_member`. As a result, repositories owned by organizations the authenticated user belongs to are never returned. This causes several visible symptoms:
- Organizations added via the UI appear empty in subsequent syncs — `listForOrg` populated the repos on first add, but no later call sees them.
- The scheduler never picks up org repos for periodic syncs.
- The cleanup service, on every restart, sees org repos in the DB but not in the GitHub list, and (with `CLEANUP_DELETE_IF_NOT_IN_GITHUB=true`) flags them all as orphaned.
## Root Cause
PR #283 (`feat: add option to exclude collaborator repos from import`) changed the affiliation to:
```ts
const affiliation = includeCollab ? "owner,collaborator" : "owner";
```
That commit's own message acknowledges the GitHub default:
> *"GitHub's `listForAuthenticatedUser` defaults to returning every repo the user has access to (owner + collaborator + organization_member)…"*
But the implementation only set two of the three values. `organization_member` was meant to remain part of the default and was inadvertently dropped.
Three callers are affected:
| Caller | File | Effect |
|---|---|---|
| Main sync | `src/pages/api/sync/index.ts` | org repos never imported |
| Scheduler | `src/lib/scheduler-service.ts` | org repos missing from periodic syncs |
| Cleanup service | `src/lib/repository-cleanup-service.ts` | even with `includeCollaboratorReposOverride: true`, org repos are invisible → flagged as orphaned |
## Fix
Always include `organization_member` in the affiliation, regardless of the `includeCollaboratorRepos` toggle. The toggle's original semantics from #279/#283 are preserved:
- `includeCollaboratorRepos: true` (default) → `owner,collaborator,organization_member`
- `includeCollaboratorRepos: false` → `owner,organization_member`
The collaborator-exclusion feature still works as intended; this change only restores the previously missing slot.
## Testing
`src/lib/github-affiliation.test.ts`:
- 4 existing assertions updated to require `organization_member`.
- New regression test `always includes organization_member` iterates 5 config combinations (default, includeCollab true/false, override true, override+toggle) to lock the invariant.
```
bun test src/lib/github-affiliation.test.ts
```
## Steps to Reproduce (pre-fix)
1. PAT with `repo` + `read:org` scope.
2. Add an organization in the UI — repos appear (this uses `listForOrg`, which works).
3. Restart the container or wait for the scheduler.
4. Org repos disappear from the dashboard; cleanup logs them as orphaned.
After the fix, repos remain consistent across restarts and scheduler runs.
## Related
The symptom is mentioned in passing in [#254](https://github.com/RayLabsHQ/gitea-mirror/issues/254#issuecomment-4141605448) (*"I have a private repo from my org which does not show up at all in gitea-mirror"*), but that issue was scoped to Forgejo auth and the side-mention was not addressed. This PR is the first formal report and fix for the org-repo invisibility itself.
Origin of the bug: #283.
---
<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/286
Author: @riguettodev
Created: 5/15/2026
Status: ✅ Merged
Merged: 5/16/2026
Merged by: @arunavo4
Base:
main← Head:fix/include-org-repos📝 Commits (1)
5c44b27fix: include organization_member in /user/repos affiliation📊 Changes
2 files changed (+40 additions, -9 deletions)
View changed files
📝
src/lib/github-affiliation.test.ts(+33 -8)📝
src/lib/github.ts(+7 -1)📄 Description
Summary
getGithubRepositories(used by the main sync, the scheduler, and the repository cleanup service) calls/user/reposwith anaffiliationparameter that omitsorganization_member. As a result, repositories owned by organizations the authenticated user belongs to are never returned. This causes several visible symptoms:listForOrgpopulated the repos on first add, but no later call sees them.CLEANUP_DELETE_IF_NOT_IN_GITHUB=true) flags them all as orphaned.Root Cause
PR #283 (
feat: add option to exclude collaborator repos from import) changed the affiliation to:That commit's own message acknowledges the GitHub default:
But the implementation only set two of the three values.
organization_memberwas meant to remain part of the default and was inadvertently dropped.Three callers are affected:
src/pages/api/sync/index.tssrc/lib/scheduler-service.tssrc/lib/repository-cleanup-service.tsincludeCollaboratorReposOverride: true, org repos are invisible → flagged as orphanedFix
Always include
organization_memberin the affiliation, regardless of theincludeCollaboratorRepostoggle. The toggle's original semantics from #279/#283 are preserved:includeCollaboratorRepos: true(default) →owner,collaborator,organization_memberincludeCollaboratorRepos: false→owner,organization_memberThe collaborator-exclusion feature still works as intended; this change only restores the previously missing slot.
Testing
src/lib/github-affiliation.test.ts:organization_member.always includes organization_memberiterates 5 config combinations (default, includeCollab true/false, override true, override+toggle) to lock the invariant.Steps to Reproduce (pre-fix)
repo+read:orgscope.listForOrg, which works).After the fix, repos remain consistent across restarts and scheduler runs.
Related
The symptom is mentioned in passing in #254 ("I have a private repo from my org which does not show up at all in gitea-mirror"), but that issue was scoped to Forgejo auth and the side-mention was not addressed. This PR is the first formal report and fix for the org-repo invisibility itself.
Origin of the bug: #283.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.