Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/forge-mirror.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Mirror canonical main to Gitea

# GitHub is the canonical line. This workflow mirrors main and tags to the
# Gitea mirror and then verifies that .github/ and scripts/ are byte-identical
# on both forges, so the #342 reconciliation invariant is enforced by CI
# rather than by hand.

# Requires a repository secret:
# GITEA_MIRROR_TOKEN - a Gitea token with Contents: write on
# terraphim/terraphim-clients.

on:
push:
branches: [main]
tags: ["v*"]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: forge-mirror-terraphim-clients
cancel-in-progress: false

jobs:
mirror:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Mirror main and tags to Gitea
env:
GITEA_MIRROR_TOKEN: ${{ secrets.GITEA_MIRROR_TOKEN }}
run: |
set -euo pipefail
if [ -z "${GITEA_MIRROR_TOKEN:-}" ]; then
echo "::error::GITEA_MIRROR_TOKEN secret is not configured; cannot mirror to Gitea."
exit 1
fi
git remote add gitea "https://x-access-token:${GITEA_MIRROR_TOKEN}@git.terraphim.cloud/terraphim/terraphim-clients.git"
git push gitea "refs/remotes/origin/main:refs/heads/main"
git push gitea --tags
- name: Verify .github and scripts are identical on both forges
run: |
set -euo pipefail
git fetch --no-tags gitea "main:refs/remotes/gitea/main"
scripts/ci/check-forge-drift.sh origin/main gitea/main .github scripts
36 changes: 36 additions & 0 deletions scripts/ci/check-forge-drift.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Fail when two git refs differ on a set of paths.
#
# Usage: check-forge-drift.sh REF_A REF_B [PATH...]
#
# Defaults to the reconciliation scope (.github scripts). Used by the
# forge-mirror workflow to prove GitHub and the Gitea mirror are identical
# (Gitea terraphim-clients#342).
set -euo pipefail

if [ "$#" -lt 2 ]; then
echo "usage: check-forge-drift.sh REF_A REF_B [PATH...]" >&2
exit 2
fi

ref_a="$1"; shift
ref_b="$1"; shift
paths=("$@")
if [ "${#paths[@]}" -eq 0 ]; then
paths=(.github scripts)
fi

tmp_a="$(mktemp)"; tmp_b="$(mktemp)"
trap 'rm -f "$tmp_a" "$tmp_b"' EXIT

git ls-tree -r "$ref_a" -- "${paths[@]}" | sort > "$tmp_a"
git ls-tree -r "$ref_b" -- "${paths[@]}" | sort > "$tmp_b"

if diff -u "$tmp_a" "$tmp_b"; then
echo "forge drift: ${ref_a} == ${ref_b} on: ${paths[*]}"
exit 0
fi

echo "forge drift: ${ref_a} and ${ref_b} differ on: ${paths[*]}" >&2
echo "A Gitea-side change must be mirrored to GitHub first (or vice versa)." >&2
exit 1
Loading