feat(ci): mirror the source repository's main into a fork on every push

bf25eb2fc7 removed the sync-main job because the fork had no token that
may push .github/workflows/**: GITHUB_TOKEN cannot be granted the
workflows permission, and the bot App is installed on infinito-nexus/core
only. Since then a fork's main only moves when its owner syncs it by
hand, and the fork's main has fallen 368 commits behind.

The job is back with a token of its own: CI_SYNC_MAIN_TOKEN, a
fine-grained personal access token limited to the fork, with Contents
and Workflows write. main_from_repository.sh resolves the source through
baseline_remote.sh, so the normalization and the off switch exist once:
in infinito-nexus/core itself and with CI_SYNC_MAIN_SOURCE_REPOSITORY
disabled the job ends green without reading the secret. Everywhere else
a missing secret fails the job before any fetch or push and names the
page that explains how to create it. The token reaches git as an HTTP
header through GIT_CONFIG_* variables, never through argv or
.git/config; checkout runs without persisted credentials so its own
header does not compete.

The job runs beside run-policy, not before it: CI keeps fetching its
diff baseline from the source repository read-only, so a failed sync
turns the run red without holding CI back.

fix/ci-mirror-token tried the bot App instead (019fb572a7, 756b180f1d).
That needs the App installed on every fork and granted Workflows write,
which secrets.md rules out for the App, so the token here is a
per-fork PAT.

Checked: the script skips as infinito-nexus/core and with the sync
disabled, and fails before fetching as a fork without the secret.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5.5 committed 2026-10-28 13:12:22 +01:00
1 parent 34be0afdf7
commit ffe77cdba9
5 files changed
+82

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
# GitHub Sync Helpers 🔄
[main_from_repository.sh](main_from_repository.sh) force-pushes the source repository's `main` onto the current repository's `main`. The `🔄 Sync main` job of [entry-push-latest.yml](../../../.github/workflows/entry-push-latest.yml) runs it on every push.
The push needs the secret `CI_SYNC_MAIN_TOKEN`, see [secrets.md](../../../docs/contributing/tools/github/actions/secrets.md). The source repository and the switch to disable the sync are the repository variable `CI_SYNC_MAIN_SOURCE_REPOSITORY`, see [configuration.md](../../../docs/contributing/tools/github/actions/configuration.md).
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
#
# Env:
# GITHUB_REPOSITORY - owner/repo of the running job, whose main is overwritten
# CI_SYNC_MAIN_TOKEN - fine-grained token for GITHUB_REPOSITORY only, with Contents and Workflows write
# CI_SYNC_MAIN_SOURCE_REPOSITORY, CI_SYNC_MAIN_SOURCE_REPOSITORY_IS_SET,
# CI_SYNC_MAIN_SOURCE_REPOSITORY_DEFAULT - the source of main, see scripts/meta/resolve/baseline_remote.sh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
: "${GITHUB_REPOSITORY:?Missing GITHUB_REPOSITORY}"
source_remote="$(bash "${REPO_ROOT}/scripts/meta/resolve/baseline_remote.sh")"
if [[ "${source_remote}" == "origin" ]]; then
echo "Main sync skipped: no source repository other than ${GITHUB_REPOSITORY} is configured."
exit 0
fi
if [[ -z "${CI_SYNC_MAIN_TOKEN:-}" ]]; then
echo "ERROR: secret CI_SYNC_MAIN_TOKEN is not set, so ${GITHUB_REPOSITORY}:main cannot be synced from ${source_remote}." >&2
echo "Create it as described in docs/contributing/tools/github/actions/secrets.md, or disable the sync through the repository variable CI_SYNC_MAIN_SOURCE_REPOSITORY." >&2
exit 1
fi
echo "Syncing ${GITHUB_REPOSITORY}:main from ${source_remote}."
git fetch "${source_remote}" main:refs/remotes/main-sync-source/main --force
auth="$(printf 'x-access-token:%s' "${CI_SYNC_MAIN_TOKEN}" | base64 -w0)"
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0="http.https://github.com/.extraheader" \
GIT_CONFIG_VALUE_0="AUTHORIZATION: basic ${auth}" \
git push "https://github.com/${GITHUB_REPOSITORY}.git" refs/remotes/main-sync-source/main:refs/heads/main --force