Automate Forgejo-to-GitHub wiki mirror sync #63

Open
opened 2026-04-09 23:58:27 +00:00 by claude-code · 1 comment
Collaborator

Context

The main repo is mirrored from Forgejo to GitHub via Forgejo's native push-mirror feature. That mirror handles the code, branches, tags, and PRs/merges as they land on Forgejo's main branch.

Wikis are different. Forgejo's push-mirror API operates on the main repo's git refs, not on the .wiki.git sibling repo. There is no equivalent API for mirroring a wiki. At the moment, the Forgejo and GitHub wikis happen to be in sync (verified by SHA match of HEAD), but they will drift the moment anyone edits the Forgejo wiki next.

Goal

A small, reliable automation that keeps the GitHub wiki in sync with the Forgejo wiki with no manual intervention.

Proposed approach

A cron-driven sync script. Simple, fails loudly, easy to diagnose.

  1. Working clone: a bare or checked-out clone of ssh://git@10.0.0.51:2222/archeious/luminos.wiki.git kept somewhere durable (suggest /var/lib/luminos-wiki-mirror/ or a user directory on the host that owns the cron).
  2. Sync script: scripts/sync-wiki-to-github.sh in this repo. Does:
    • git fetch origin main (origin = Forgejo)
    • Check if origin/main is ahead of github/main; if not, exit 0 with no output
    • git push github main (github = GitHub wiki via the PAT)
    • On failure, exit non-zero so cron mail / logging fires
  3. Auth: use the existing GITHUB_LUMINOS_MIRROR_TOKEN stored in ~/secrets. Read at script start, embed in the remote URL temporarily, scrub from process env on exit.
  4. Schedule: cron every 15 minutes is plenty. Wiki edits are rare and a 15-minute sync window is fine.
  5. Logging: write a line to /var/log/luminos-wiki-mirror.log (or a per-user log) on every run: <timestamp> <forgejo-head> <github-head> <status>. Makes it trivial to see when the last sync happened and whether it was a no-op or a real push.
  6. Host: run on the host that owns the rest of the homelab cron (probably r720xd-1 or home-node-1, wherever the backup cron already lives, to keep the cron footprint consolidated).

Alternatives considered

  • Forgejo post-receive git hook on the wiki repo. Would be real-time, but requires shell access to the Forgejo server, writing into its git hook storage, and is brittle across Forgejo upgrades. Cron is simpler.
  • Webhook to a small HTTP listener. More work to build and maintain than a cron, with no meaningful latency advantage for a wiki that gets edited a few times a month.
  • Skip it. Accept that GitHub wiki drifts. Nearly free now but produces a low-trust GitHub wiki over time.

Definition of done

  • scripts/sync-wiki-to-github.sh checked in, executable, with a clear header comment
  • Dry-run mode (--dry-run or DRY_RUN=1) that reports what it would do without pushing
  • Runs clean on a no-op pass (no output, exit 0)
  • Runs clean on a real-push pass (logs the push, exit 0)
  • Cron installed on the chosen host, entry documented in the wiki
  • First few runs observed in the log to confirm behavior
  • Failure mode tested: invalid token, network error, etc. produce a nonzero exit and a visible error

Out of scope

  • Bidirectional sync. This is Forgejo to GitHub only. Forgejo is the source of truth.
  • Syncing anything other than main branch on the wiki repo.
  • Syncing the issue tracker, PRs, or wiki comments (GitHub's features, not portable).

Refs

  • Sibling work in homelab/homelab-IaC#45 (public visibility initiative)
  • Main repo mirror set up 2026-04-09, trigger = Forgejo push-mirror API, interval 8h + sync_on_commit
## Context The main repo is mirrored from Forgejo to GitHub via Forgejo's native push-mirror feature. That mirror handles the code, branches, tags, and PRs/merges as they land on Forgejo's main branch. **Wikis are different.** Forgejo's push-mirror API operates on the main repo's git refs, not on the `.wiki.git` sibling repo. There is no equivalent API for mirroring a wiki. At the moment, the Forgejo and GitHub wikis happen to be in sync (verified by SHA match of HEAD), but they will drift the moment anyone edits the Forgejo wiki next. ## Goal A small, reliable automation that keeps the GitHub wiki in sync with the Forgejo wiki with no manual intervention. ## Proposed approach A cron-driven sync script. Simple, fails loudly, easy to diagnose. 1. **Working clone:** a bare or checked-out clone of `ssh://git@10.0.0.51:2222/archeious/luminos.wiki.git` kept somewhere durable (suggest `/var/lib/luminos-wiki-mirror/` or a user directory on the host that owns the cron). 2. **Sync script:** `scripts/sync-wiki-to-github.sh` in this repo. Does: - `git fetch origin main` (origin = Forgejo) - Check if `origin/main` is ahead of `github/main`; if not, exit 0 with no output - `git push github main` (github = GitHub wiki via the PAT) - On failure, exit non-zero so cron mail / logging fires 3. **Auth:** use the existing `GITHUB_LUMINOS_MIRROR_TOKEN` stored in `~/secrets`. Read at script start, embed in the remote URL temporarily, scrub from process env on exit. 4. **Schedule:** cron every 15 minutes is plenty. Wiki edits are rare and a 15-minute sync window is fine. 5. **Logging:** write a line to `/var/log/luminos-wiki-mirror.log` (or a per-user log) on every run: `<timestamp> <forgejo-head> <github-head> <status>`. Makes it trivial to see when the last sync happened and whether it was a no-op or a real push. 6. **Host:** run on the host that owns the rest of the homelab cron (probably `r720xd-1` or `home-node-1`, wherever the backup cron already lives, to keep the cron footprint consolidated). ## Alternatives considered - **Forgejo post-receive git hook on the wiki repo.** Would be real-time, but requires shell access to the Forgejo server, writing into its git hook storage, and is brittle across Forgejo upgrades. Cron is simpler. - **Webhook to a small HTTP listener.** More work to build and maintain than a cron, with no meaningful latency advantage for a wiki that gets edited a few times a month. - **Skip it.** Accept that GitHub wiki drifts. Nearly free now but produces a low-trust GitHub wiki over time. ## Definition of done - [ ] `scripts/sync-wiki-to-github.sh` checked in, executable, with a clear header comment - [ ] Dry-run mode (`--dry-run` or `DRY_RUN=1`) that reports what it would do without pushing - [ ] Runs clean on a no-op pass (no output, exit 0) - [ ] Runs clean on a real-push pass (logs the push, exit 0) - [ ] Cron installed on the chosen host, entry documented in the wiki - [ ] First few runs observed in the log to confirm behavior - [ ] Failure mode tested: invalid token, network error, etc. produce a nonzero exit and a visible error ## Out of scope - Bidirectional sync. This is Forgejo to GitHub only. Forgejo is the source of truth. - Syncing anything other than `main` branch on the wiki repo. - Syncing the issue tracker, PRs, or wiki comments (GitHub's features, not portable). ## Refs - Sibling work in homelab/homelab-IaC#45 (public visibility initiative) - Main repo mirror set up 2026-04-09, trigger = Forgejo push-mirror API, interval 8h + sync_on_commit
Author
Collaborator

Gotcha from the initial manual push

GitHub's wiki renderer looks for the master branch by default on this wiki (the wiki repo was created with no HEAD symbolic ref and main alone is not enough). Pushing content only to main produces a working git repo but an empty-looking wiki page in the GitHub UI.

Fix the script will need: push to both main and master, or configure the wiki repo's default branch. Simplest is push to both. Verified working 2026-04-09 by force-pushing main:master.

After the fix, git ls-remote on the GitHub wiki showed:

<sha>  HEAD
<sha>  refs/heads/main
<sha>  refs/heads/master

The cron sync script (#63 DoD) should either:

  • Push with a dual refspec (git push github main:main main:master), or
  • Push once and verify both refs match after, and force if not

Recording this so future-me doesn't spend 20 minutes debugging "why is my wiki empty when git ls-remote shows content."

## Gotcha from the initial manual push GitHub's wiki renderer looks for the `master` branch by default on this wiki (the wiki repo was created with no HEAD symbolic ref and `main` alone is not enough). Pushing content only to `main` produces a working git repo but an empty-looking wiki page in the GitHub UI. **Fix the script will need:** push to both `main` and `master`, or configure the wiki repo's default branch. Simplest is push to both. Verified working 2026-04-09 by force-pushing `main:master`. After the fix, `git ls-remote` on the GitHub wiki showed: ``` <sha> HEAD <sha> refs/heads/main <sha> refs/heads/master ``` The cron sync script (#63 DoD) should either: - Push with a dual refspec (`git push github main:main main:master`), or - Push once and verify both refs match after, and force if not Recording this so future-me doesn't spend 20 minutes debugging "why is my wiki empty when git ls-remote shows content."
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: archeious/luminos#63
No description provided.