# Auto-sync this Gitea repo to its public GitHub mirror on every push to main.
#
# Design (deliberate trade-offs):
# - Push-driven from Gitea (this repo IS the source of truth); GitHub is a mirror.
# - Each sync = one snapshot commit on GitHub referencing the source Gitea SHA.
#   GitHub gets a real, growing history (one commit per Gitea push that changed
#   the mirrored tree); NO force-push, NO history rewrites.
# - The mirror tree is FILTERED: `blog/`, `handoff.md`, `.claude/`, `.gitea/`,
#   and the usual generated junk are never copied. They are not in the GitHub
#   history either (per the original "do not push these" rule).
# - If a Gitea push touches only excluded paths, the rsync produces no diff and
#   the workflow exits clean (no empty commit on GitHub).
#
# Prereqs (one-time):
# - Repo secret GH_MIRROR_TOKEN holds a GitHub PAT with `repo` scope (push to
#   recklessop/ai-workflow-course). Name avoids the GITHUB_ reserved prefix.
# - The GitHub mirror exists at github.com/recklessop/ai-workflow-course.
name: Sync to GitHub mirror
on:
  push:
    branches: [main]
  workflow_dispatch: {}

concurrency:
  group: sync-github-mirror
  cancel-in-progress: false   # serialize; never cancel a sync mid-push

jobs:
  sync:
    runs-on: docker
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
      - name: Sync filtered tree to GitHub
        shell: bash
        env:
          GH_MIRROR_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
        run: |
          set -euo pipefail
          if [ -z "${GH_MIRROR_TOKEN:-}" ]; then
            echo "::error::GH_MIRROR_TOKEN secret not set; see this workflow's header."
            exit 1
          fi
          command -v rsync >/dev/null || { apt-get update && apt-get install -y --no-install-recommends rsync; }

          GH_REPO="recklessop/ai-workflow-course"
          SRC_SHA="$(git rev-parse --short HEAD)"

          # Clone the GitHub mirror into a sibling working dir
          GH_DIR="${RUNNER_TEMP:-/tmp}/awc-gh-mirror"; rm -rf "$GH_DIR"; git clone --depth=1 "https://x-access-token:${GH_MIRROR_TOKEN}@github.com/${GH_REPO}.git" "$GH_DIR"

          # Mirror this checkout's tree into gh-mirror/ with the exclusions.
          # --delete drops files removed on the source; --exclude='.git' protects
          # both repos' .git dirs from rsync touching them.
          # NOTE: do NOT add an --exclude for the clone target dir name; rsync's --exclude also
          # protects the matching path at the DESTINATION from --delete, which would prevent
          # any stray copy of that dir from ever being cleaned up. The clone living in
          # $RUNNER_TEMP (outside ./) already prevents the recursive self-include.
          rsync -a --delete \
            --exclude='.git' \
            --exclude='.gitea/' \
            --exclude='.claude/' \
            --exclude='blog/' \
            --exclude='handoff.md' \
            --exclude='__pycache__/' \
            --exclude='*.pyc' \
            --exclude='tasks.json' \
            --exclude='.DS_Store' \
            ./ "$GH_DIR"/

          cd "$GH_DIR"
          git add -A
          if git diff --cached --quiet; then
            echo "no relevant changes for the mirror (source push only touched excluded paths); skipping"
            exit 0
          fi

          git config user.name  "Justin Paul"
          git config user.email "justin@jpaul.me"
          git commit -m "sync from gitea @ ${SRC_SHA}"
          # Plain push: each sync is a fast-forward append (no rewrites). If a
          # stranger pushed to GitHub main between clone and push, --force-with-lease
          # would tell us; here we let it fail loudly so we notice the divergence.
          git push origin HEAD:main
