-
released this
2026-05-19 02:21:18 -05:00 | 1 commits to main since this release📅 Originally published on GitHub: Tue, 19 May 2026 07:21:42 GMT
🏷️ Git tag created: Tue, 19 May 2026 07:21:18 GMTWhat's new
feat: Change password and Change email from the UI (#292)Resolves discussion #291. Better Auth's
change-password/change-emailendpoints have always been exposed server-side, but there was no way to reach them from the web UI.The avatar dropdown in the header now shows:
- Change password — opens a dialog with current/new/confirm fields and a "Sign out other devices" checkbox (defaults on, calls Better Auth's `revokeOtherSessions: true` — verified end-to-end that other sessions are invalidated immediately).
- Change email — opens a dialog with the new email field. The dropdown updates to show the new address as soon as the change succeeds.
SSO-only users (no local password) have the Change password item hidden. The check uses `GET /api/auth/list-accounts` to look for a `credential` provider; if the probe errors it fails open rather than locking anyone out.
This required enabling `user.changeEmail` in Better Auth with `updateEmailWithoutVerification: true` — safe in this app because email verification isn't on and there's no email sender wired up.
ci: pin third-party GitHub Actions to commit SHAs (#293)In response to the supply-chain attack pattern that recently hit `actions-cool/issues-helper` and `actions-cool/maintain-one-comment`, and `tj-actions/changed-files` before that.
Tags are mutable. A compromised maintainer can force-move `@v3` to point at malicious code, and every workflow using the tag picks it up on the next run. Pinning to a 40-char commit SHA makes the reference immutable.
This release pins the highest-risk subset:
- `nix-build.yml` — two `@main` branch refs (worse than tags, since they move on every push) → pinned to release SHAs for `v22` / `v13`.
- `docker-build.yml` — every third-party action (`docker/setup-buildx`, `docker/login`, `docker/metadata`, `docker/build-push`, `docker/scout`) now references a SHA with a trailing `# vX.Y.Z` comment for readability.
This is the workflow that holds the GHCR push token, Docker Hub login, and Scout API token — so it's the one with the largest blast radius if compromised.
First-party `actions/*` and `github/codeql-action` are left on tags for now; they're a separate, lower-risk follow-up. Dependabot for the `github-actions` ecosystem is recommended next so SHA pins still get auto-bumped.
`chore`: bump and digest-pin Bun base image to 1.3.14 (#295)
Same hardening principle, applied to the Dockerfile:
- Bun `1.3.13-debian` → `1.3.14-debian` (released 2026-05-13)
- Pinned to digest: `@sha256:9dba1a1b...db6f` (multi-arch — `linux/amd64` and `linux/arm64`)
- Applies to both the `base` and `runner` stages in the Dockerfile
A tag on Docker Hub is just as mutable as a tag on GitHub; pinning to the digest closes the same class of attack at the container layer.
Downloads
-
released this
2026-05-16 01:33:53 -05:00 | 5 commits to main since this release📅 Originally published on GitHub: Sat, 16 May 2026 06:44:56 GMT
🏷️ Git tag created: Sat, 16 May 2026 06:33:53 GMTWhat's new
chore: patch 9 HIGH-severity npm CVE alerts (#289)The weekly Docker Scout scan surfaced 9 HIGH alerts in transitive npm deps. All have fixed versions upstream; pinned via
package.jsonoverrides.Package Bumped to CVEs @xmldom/xmldom0.8.13 CVE-2026-41672, 41673, 41674, 41675 devalue5.8.1 CVE-2026-42570 kysely0.28.17 CVE-2026-44635 fast-uri3.1.2 CVE-2026-6321, 6322 fast-xml-builder1.1.7 CVE-2026-44665 chore: prune npm overrides that are no longer load-bearing (#290)Internal cleanup. Removed 5 stale overrides (
defu,fast-xml-parser,node-forge,rollup,svgo) whose constraints are now satisfied naturally by the transitive dep graph. Verified by removing each and confirming the resolved version and tree shape are identical.No behavior change — only
package.jsonhousekeeping.Note on remaining Docker Scout alerts
The remaining HIGH alerts in the image are not addressable via npm and will be picked up separately:
git-lfsGo stdlib (5 CVEs) — needs the git-lfs binary in the Dockerfile bumped to a build that uses Go ≥1.25.10- Debian
gnutls28(4 CVEs) — upstream shows "not fixed" yet - Debian
nghttp2(1 CVE) — base image rebuild will pick it up on nextbun:debianbump
Downloads
-
released this
2026-05-15 23:10:48 -05:00 | 8 commits to main since this release📅 Originally published on GitHub: Sat, 16 May 2026 04:22:43 GMT
🏷️ Git tag created: Sat, 16 May 2026 04:10:48 GMTWhat's new
fix: org-owned repos visible again to sync, scheduler, and cleanup (#286)#283 dropped
organization_memberfrom the GitHub repo-listing affiliation filter. Repos owned by orgs the user belongs to became invisible to the main sync, the scheduler, and — worst of all — the orphan-cleanup pass, which would archive (or withCLEANUP_DELETE_IF_NOT_IN_GITHUB=true, delete) them on every restart.The affiliation filter now always includes
organization_member, regardless of theINCLUDE_COLLABORATOR_REPOStoggle. The toggle's original semantics from #283 are preserved.fix: reconcile issue/PR/label/milestone metadata on every sync (#287)A one-shot guard added in #266 meant metadata only mirrored on the first sync of a repo. Edits made on GitHub afterwards — renamed issues, new labels, edited bodies — never propagated. This was a regression of #165, which #184 had already fixed via marker-based idempotent upserts.
Reconciliation now runs every sync. The underlying mirror functions remain idempotent: issues match by
[GH-ISSUE #N]markers, PRs by[PR #N], labels by name, milestones by title. Existing entries are PATCH'd in place — no duplicates.Note: slightly increases GitHub API usage per sync for repos with many issues/PRs. A
since=lastSyncedAtoptimization is planned as a follow-up.
Thanks to @riguettodev for both fixes.
Downloads
-
released this
2026-05-04 03:30:10 -05:00 | 11 commits to main since this release📅 Originally published on GitHub: Mon, 04 May 2026 08:30:39 GMT
🏷️ Git tag created: Mon, 04 May 2026 08:30:10 GMTWhat's new
feat: opt out of collaborator repos in GitHub imports (#283, closes #279)GitHub's authenticated repo listing returns every repo the user has access to by default — owner, collaborator, and organization member. For users who only want to mirror their own work, collaborator repos showed up as noise.
This release adds an Include collaborator repositories toggle in the GitHub configuration panel. When unchecked, the import scopes the GitHub API affiliation filter to
owneronly, so collaborator-only repos are excluded.- Default: on. Existing users see no behavior change. Uncheck to opt out.
- New env var
INCLUDE_COLLABORATOR_REPOS(defaulttrue) for env-driven (Docker) deployments. Set tofalseto disable from the environment without touching the UI. - Cleanup safety net. When the toggle is off, the orphan-cleanup pass still asks GitHub for the full list (owner + collaborator), so previously-mirrored collaborator repos are not flagged as orphaned and archived/deleted. Toggling the option off only affects what gets imported, never what gets removed.
- Round-trip and affiliation tests in
src/lib/utils/config-mapper.test.tsandsrc/lib/github-affiliation.test.ts.
This is the proper rewrite of #279, which was closed because the field had been added to the UI type only and never reached the runtime read site.
Downloads
-
released this
2026-05-03 23:44:09 -05:00 | 13 commits to main since this release📅 Originally published on GitHub: Mon, 04 May 2026 04:44:30 GMT
🏷️ Git tag created: Mon, 04 May 2026 04:44:09 GMTWhat's new
feat: surface auto-mirror toggle in Automation settings (refs #278)Follow-up to v3.15.8. That release made
scheduleConfig.autoMirroran independent trigger in the scheduler, but it could still only be enabled via theAUTO_MIRROR_REPOSenv var. This release adds a UI toggle so the option is reachable from the Automation tab without touching the environment.- New checkbox "Auto-mirror new repositories" in Automation → Automatic Syncing
- Visible only when scheduling is enabled (auto-mirror without a scheduler is meaningless)
- Independent of the existing "Auto-mirror new starred repositories" toggle in GitHub settings — together they cover the full owned/starred matrix
Together with v3.15.8, this completes the auto-mirror UX described in #278: new repos discovered on GitHub are now mirrored on the next scheduled sync without any manual click, and both owned and starred scopes are independently controllable from the UI.
No schema or migration change.
Downloads
-
released this
2026-05-03 22:42:57 -05:00 | 15 commits to main since this release📅 Originally published on GitHub: Mon, 04 May 2026 03:43:27 GMT
🏷️ Git tag created: Mon, 04 May 2026 03:42:57 GMTWhat's new
fix: make autoMirrorStarred actually trigger auto-mirror (fixes #278)The "Auto-mirror new starred repositories" checkbox in the GitHub settings was a filter layered on top of
scheduleConfig.autoMirror, which itself is only settable via theAUTO_MIRROR_REPOSenv var (no UI). So users who checked the box saw their starred repos auto-imported but never mirrored — contradicting the label.This release makes the two flags independent triggers in the scheduler:
autoMirror=true→ auto-mirror owned (and self-starred) reposautoMirrorStarred=true→ auto-mirror repos starred from other owners- Either flag on its own enters the auto-mirror phase; the filter scopes the work accordingly
Also normalized the owner comparison to lowercase since GitHub usernames are case-insensitive — previously a self-starred repo whose stored owner casing differed from
githubConfig.ownerwould be misclassified as a third-party star and silently skipped.Behavior change to flag: anyone who currently has the starred checkbox on (broken state) will start getting starred repos mirrored after upgrading. Users with
AUTO_MIRROR_REPOS=truesee no change.autoMirrorautoMirrorStarredBefore After off off nothing nothing on off owned + self-starred owned + self-starred (unchanged) off on nothing (bug) third-party starred only on on everything everything (unchanged) A truth-table test in
src/lib/scheduler-service.test.tsguards against re-introducing the bug.Note: this release fixes the starred half of #278. Auto-mirroring all owned repos still requires
AUTO_MIRROR_REPOS=trueat container start; surfacing that in the UI is the remaining tracked work on the issue.Downloads
-
released this
2026-05-03 21:50:26 -05:00 | 16 commits to main since this release📅 Originally published on GitHub: Mon, 04 May 2026 02:50:36 GMT
🏷️ Git tag created: Mon, 04 May 2026 02:50:26 GMTWhat's new
fix: unstick repos in 'mirroring' on transient errors (fixes #268)Repositories could get permanently stuck in the
mirroringstate — with no failure entry in the activity log — when a transient error hit during the Gitea migrate call. The catch block referencedlet migrateSucceededthat had been declared inside the sametryblock; block-scoping made it invisible fromcatch, so thecatchcrashed withReferenceError: migrateSucceeded is not definedbefore it could update the DB tofailed.This release hoists the declaration above the
tryin bothmirrorGithubRepoToGiteaandmirrorGitHubRepoToGiteaOrg, restoring the intended behavior:- transient errors (timeouts, 5xx, etc.) now correctly transition the repo to
failedinstead of leaving it stuck inmirroring mirroredLocationis cleared when the migrate call itself never succeeded- a failure entry is written to the activity log
- the original error message is preserved on retry (no more misleading
Failed to mirror repository: migrateSucceeded is not defined)
Upgrade note: anyone who saw repos pile up in
mirroringafter upgrading from older versions can retry those repos after this release — they will now move tofailedand become retriable instead of getting stuck again.A structural regression test in
src/lib/gitea-mirror-failure-recovery.test.tsguards against re-introducing the scoping bug.See full discussion in #268.
Downloads
- transient errors (timeouts, 5xx, etc.) now correctly transition the repo to
-
released this
2026-04-26 03:13:51 -05:00 | 18 commits to main since this release📅 Originally published on GitHub: Sun, 26 Apr 2026 08:14:06 GMT
🏷️ Git tag created: Sun, 26 Apr 2026 08:13:51 GMTWhat's new
feat: warn when destination Forgejo has the known mirror-credential bug (refs #263)Forgejo versions before v15.0.0 silently discard
auth_username/auth_passwordsent to/api/v1/repos/migrate, so subsequent pull-mirror sync of private repos fails withterminal prompts disabled. The bug was fixed upstream in Forgejo PR #11909 and the fix is only in v15.0.0+ — it was not backported to v12.x, v13.x, or v14.x.The Gitea config "Test Connection" flow now probes
/api/v1/version, detects Forgejo via the+gitea-suffix, and shows a clear in-app warning when the connected server reports a Forgejo major version below 15. The warning links to the upstream PR and tells users exactly what to do (upgrade Forgejo, then delete + re-mirror affected repos).Pure Gitea servers and Forgejo v15.0.0+ are unaffected — no warning shown.
See full discussion in #263.
Downloads
-
released this
2026-04-22 08:51:13 -05:00 | 20 commits to main since this release📅 Originally published on GitHub: Wed, 22 Apr 2026 13:51:35 GMT
🏷️ Git tag created: Wed, 22 Apr 2026 13:51:13 GMTWhat's Changed
Follow-up to v3.15.4 — relaxes the dashboard config gate so users with tokens but no username don't get locked out.
Fixed
-
Dashboard rendered all zeros for users whose config had empty
usernamefields (#271). TheuseConfigStatushook requiredgithubConfig.usernameandgiteaConfig.usernameto be non-empty before letting the dashboard fetch data. In practice neither is required at runtime:- The GitHub token is self-authenticating via
listForAuthenticatedUser— no username needed. - The Gitea username isn't used under
single-orgorflat-usermirror strategies.
Users who configured via env vars without setting
GITHUB_USERNAME/GITEA_USERNAME(the form'srequiredattribute is only client-side and the save endpoint doesn't enforce it either) ended up with empty strings in those fields. Mirroring kept running fine because tokens alone are sufficient — but the dashboard refused to fetch and rendered zeros.The gate now only requires what's actually needed at runtime: the GitHub token, and the Gitea URL + token. The
githubOwnerfield is still exported for consumers that want to display an owner; only the gate is relaxed. - The GitHub token is self-authenticating via
Compatibility
No schema changes, no migrations. Pure frontend hook change.
Verification
All 231 unit tests pass.
bun run buildsucceeds.Full Changelog: https://github.com/RayLabsHQ/gitea-mirror/compare/v3.15.4...v3.15.5
Downloads
-
-
released this
2026-04-21 21:41:17 -05:00 | 22 commits to main since this release📅 Originally published on GitHub: Wed, 22 Apr 2026 02:41:43 GMT
🏷️ Git tag created: Wed, 22 Apr 2026 02:41:17 GMTWhat's Changed
Bug fix release — dashboard no longer renders empty when a user accidentally has more than one
configsrow.Fixed
-
Dashboard showed zeros / "no repositories" while data was intact in the database (#271). Several
SELECT … FROM configs WHERE userId = ? LIMIT 1queries had noORDER BY, so when a user's database accidentally contained more than oneconfigsrow for the same user (from an env-loader insert path or a partial default-config create), SQLite returned a non-deterministic row.In the reported case
/api/confighanded back an empty stub while/api/dashboard's repo and org counts came from the populated active row. The dashboard'suseConfigStatushook then saw missingusername/token, treated config as incomplete, and never fetched dashboard data — the UI rendered with all zeros even though hundreds of repos were sitting in the database, mirroring fine in the background.Every "fetch the user's config" query now applies
ORDER BY isActive DESC, updatedAt DESCbeforeLIMIT 1, so the active and most-recently-updated row consistently wins. The env-config-loader's "first user" pick is now ordered bycreatedAt ASCfor the same deterministic-across-restarts reason.Sites that already filter on
isActive = trueexplicitly (cleanup service, scheduler, repositories/organizations/orgs-sync/cleanup-trigger endpoints) are unchanged.
Compatibility
No schema changes, no migrations. The fix is purely a query-level change: for the ~99% of installs that have a single config row, behavior is identical. For installs with duplicate config rows, the active populated row is now selected instead of a random one.
Verification
All 231 unit tests pass.
bun run buildsucceeds.Full Changelog: https://github.com/RayLabsHQ/gitea-mirror/compare/v3.15.3...v3.15.4
Downloads
-
mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-05-22 23:51:42 -05:00