Docs sync → radieu/p24-infra-docs — Operations
Automation: .github/workflows/sync-docs-to-p24-infra-docs.yml
Target repo: radieu/p24-infra-docs (private)
Source of truth: radieu/p24-infra — docs/** on main
Issue: Etap 2 of #2640
What it does
On every push to main in radieu/p24-infra that touches docs/**, a GitHub Action mirrors the
entire docs/ tree into the standalone private repo radieu/p24-infra-docs and commits it there.
rsync --delete makes the mirror exact — files removed from p24-infra/docs/ are removed from
the mirror too. p24-infra-docs is a read-only downstream mirror: never edit docs there
directly, edits are overwritten on the next sync. All doc changes go through p24-infra.
Why a separate repo (decisions closed 2026-07-03 on #2640)
| # | Question | Decision | Reason |
|---|---|---|---|
| 1 | Sync mechanism | GH Action auto-copy on merge to main | Zero manual work; docs always current |
| 2 | Submodule vs independent | Independent repo (no submodule) | Workers want latest docs; pinning/submodule adds CI + git pain for no value |
| 3 | Access | Private | Docs carry internal topology, server IPs, workflow detail |
| 4 | Versioning | main only, no releases | Docs have no release cycle; git log is enough history |
Scope of the mirror
- Mirrored: the whole
docs/tree (topic-indexed Quartz/Obsidian vault,docs/01-…–docs/18-…index pages plus the flat operational docs they link to). - NOT mirrored (stays in
p24-infra):CLAUDE.mdand the per-project ecosystem instructions — per-project agent instructions must live beside the code they govern (established on #2640, 2026-08-06);secrets/;.claude/task-playbooks/(read by hooks/classifier locally);CHANGELOG.md(tied to the p24-infra history, not docs).
Credential
No static PAT is used (#6239). The workflow mints a short-lived (1h) GitHub App installation
token at run time via actions/create-github-app-token@v3, scoped to just radieu/p24-infra-docs
with contents: write:
- uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: radieu
repositories: p24-infra-docs
permission-contents: writeGH_APP_ID / GH_APP_PRIVATE_KEY are the existing GH Secrets for the p24-infra-admin GitHub App
(App 2109526 / installation 142989418, account radieu, repository_selection: all) — already used
by credential-rotation.yml, reregister-ionos-runners.yml, secrets-sync.yml, and others. Because
the App’s installation covers every repo in the radieu account (including new ones created after
install), no per-target-repo credential ever needs to be minted or stored — this same mechanism
covers any future repo the App can already reach.
owner:/repositories:are required for cross-repo scoping — without them the token is restricted to the current repo (p24-infra) and 403s againstp24-infra-docs(same gotcha documented inreregister-ionos-runners.yml/provision-new-vps.yml, 4221).actions/checkoutinjects the token viahttp.extraheaderand strips it in post-run cleanup, so it never lands in a remote URL or a persisted.git/config.- The token is minted fresh on every run and expires in 1h — nothing to rotate, nothing to store.
History — the PAT that was never needed
The workflow originally (Etap 2 of #2640 / #6234) speced a static fine-grained PAT
(P24_INFRA_DOCS_PUSH_PAT) as the push credential, gated behind a first-step no-op guard until the
secret existed. That PAT could only be minted by a human via the GitHub web UI (no API for minting a
user PAT) — escalated as #6239. A live check (read-only, via the App’s own JWT) found the App
already had the access needed, making the PAT unnecessary; #6239 fixed the workflow to use the App
mechanism instead and was closed without ever minting the PAT. No P24_INFRA_DOCS_PUSH_PAT secret
exists or is needed.
Manual trigger / verification
# Force a full re-mirror:
gh workflow run sync-docs-to-p24-infra-docs.yml --repo radieu/p24-infra
# Watch the run:
gh run list --repo radieu/p24-infra --workflow sync-docs-to-p24-infra-docs.yml --limit 3
# Confirm the mirror populated:
gh repo view radieu/p24-infra-docs --json pushedAt,defaultBranchRefFailure handling
The workflow is a standard GH Action — a failed run surfaces in the Actions tab. Auth failures now
point at the App mechanism, not a PAT: check that GH_APP_ID/GH_APP_PRIVATE_KEY are still valid
and that the p24-infra-admin App installation still covers radieu/p24-infra-docs (Settings →
Installed GitHub Apps on the target repo, or repository_selection: all on the installation).
Related
- Etap 1 (the docs restructure itself): #2640, PR #5050 / #5793
docs/11-automations/README.md— automation index