Release 5/11: Gitea Actions mirror workflow (non-force push) #45

Closed
opened 2026-08-08 18:43:40 -04:00 by jared · 1 comment
Owner

Depends on #44 (mirror repo exists).

Sync Gitea → GitHub without --force, so a divergence fails loudly in CI instead of silently overwriting.

Why not Gitea's built-in push mirror

A push mirror force-updates the refs it owns. If anyone ever clicks Merge on a GitHub PR, the next sync overwrites main, the PR still displays "Merged", the commit becomes unreachable, and nothing anywhere says so. A plain git push is rejected as non-fast-forward the moment that happens — turning a silent data-loss trap into a red CI run in a place you already look.

The workflow

.gitea/workflows/mirror-github.yml:

name: Mirror to GitHub
on:
  push:
    branches: [main]
    tags: ['v*']
jobs:
  mirror:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - run: |
          git push https://x-access-token:${{ secrets.GITHUB_MIRROR_PAT }}@github.com/civilytics/uscogdata.git \
            main --tags     # no --force, on purpose

Setup

  1. GitHub → Settings → Developer settings → PAT with repo scope on civilytics/uscogdata.
  2. Gitea → repo Settings → Actions → Secrets → add GITHUB_MIRROR_PAT.

Do NOT add GitHub branch protection

Protection rules that block force-pushes also block the mirror's legitimate pushes. It breaks normal syncing to catch an abnormal case; the non-force push above already gets you the loud failure.

Done when

  • Secret added
  • Workflow committed and a push to main lands on GitHub
Depends on #44 (mirror repo exists). Sync Gitea → GitHub **without `--force`**, so a divergence fails loudly in CI instead of silently overwriting. ## Why not Gitea's built-in push mirror A push mirror force-updates the refs it owns. If anyone ever clicks **Merge** on a GitHub PR, the next sync overwrites `main`, the PR still displays "Merged", the commit becomes unreachable, and **nothing anywhere says so**. A plain `git push` is rejected as non-fast-forward the moment that happens — turning a silent data-loss trap into a red CI run in a place you already look. ## The workflow `.gitea/workflows/mirror-github.yml`: ```yaml name: Mirror to GitHub on: push: branches: [main] tags: ['v*'] jobs: mirror: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } - run: | git push https://x-access-token:${{ secrets.GITHUB_MIRROR_PAT }}@github.com/civilytics/uscogdata.git \ main --tags # no --force, on purpose ``` ## Setup 1. GitHub → Settings → Developer settings → PAT with `repo` scope on `civilytics/uscogdata`. 2. Gitea → repo Settings → Actions → Secrets → add `GITHUB_MIRROR_PAT`. ## Do NOT add GitHub branch protection Protection rules that block force-pushes also block the mirror's legitimate pushes. It breaks normal syncing to catch an abnormal case; the non-force push above already gets you the loud failure. ## Done when - [ ] Secret added - [ ] Workflow committed and a push to `main` lands on GitHub
jared changed title from Release 4/11: Gitea Actions mirror workflow (non-force push) to Release 5/11: Gitea Actions mirror workflow (non-force push) 2026-08-08 18:44:09 -04:00
Author
Owner

@/tmp/claude-1000/-home-jared-Nextcloud-Civilytics-Code-Civilytics-cog-explorer/4bbb145c-ac06-4d88-84be-1e596655c718/scratchpad/c45.md

@/tmp/claude-1000/-home-jared-Nextcloud-Civilytics-Code-Civilytics-cog-explorer/4bbb145c-ac06-4d88-84be-1e596655c718/scratchpad/c45.md
jared closed this issue 2026-08-09 09:20:27 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Civilytics/uscogdata#45