Sync released repos #100
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Sync released repos | |
| # Publish-out sync: regenerate the released split repos from this monorepo | |
| # (scripts/release/released.yml + scripts/release/sync_released.py). | |
| # | |
| # Manual dispatch, defaulting to a dry run. A real sync (dry_run=false) overwrites | |
| # each released repo's managed paths, rewrites their cross-repo Lake pins, pushes | |
| # to their `main`, and advances the baseline — one dispatch drives it all the way | |
| # through. The uncoordinated-commit guard skips any released repo whose `main` has | |
| # moved off the baseline, so out-of-band commits are never clobbered. Needs the | |
| # `RELEASED_SYNC_PAT` and `RELEASED_SYNC_PAT_2` secrets (contents:write on the | |
| # released repos; the set is split across two fine-grained tokens because one | |
| # token caps its selected-repository list — the sync routes per repo). | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: "Dry run (print planned changes; do not push)" | |
| type: boolean | |
| default: true | |
| only: | |
| description: "Optional repository short name (for staged first publishes)" | |
| type: string | |
| required: false | |
| default: "" | |
| concurrency: | |
| group: sync-released | |
| cancel-in-progress: false | |
| # `main` is protected, so the advanced baseline is kept on a dedicated, | |
| # unprotected `release-sync-baseline` branch that this job pushes to with the | |
| # built-in token. One dispatch drives the whole publish end to end. | |
| permissions: | |
| contents: write | |
| env: | |
| BASELINE_BRANCH: release-sync-baseline | |
| jobs: | |
| sync: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - run: python3 -m pip install --user pyyaml | |
| - name: Load live baseline | |
| # From the dedicated branch if it exists; otherwise seed from the | |
| # committed scripts/release/synced.json (first run / bootstrap). | |
| run: | | |
| if git fetch origin "$BASELINE_BRANCH" 2>/dev/null; then | |
| git show "origin/$BASELINE_BRANCH:synced.json" > /tmp/baseline.json | |
| else | |
| cp scripts/release/synced.json /tmp/baseline.json | |
| fi | |
| - name: Sync released repos | |
| env: | |
| RELEASED_SYNC_PAT: ${{ secrets.RELEASED_SYNC_PAT }} | |
| RELEASED_SYNC_PAT_2: ${{ secrets.RELEASED_SYNC_PAT_2 }} | |
| run: | | |
| args=() | |
| [ "${{ inputs.dry_run }}" = "false" ] || args+=(--dry-run) | |
| [ -z "${{ inputs.only }}" ] || args+=(--only "${{ inputs.only }}") | |
| python3 scripts/release/sync_released.py \ | |
| --baseline /tmp/baseline.json "${args[@]}" | |
| - name: Publish advanced baseline | |
| # A later mirror can fail after earlier mirrors were pushed. Preserve | |
| # those exact heads even when the sync step reports that failure. | |
| if: ${{ always() && inputs.dry_run == false }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| if [ ! -f /tmp/baseline.json ]; then | |
| echo "::warning::No baseline file was produced; nothing to publish." | |
| exit 0 | |
| fi | |
| work=$(mktemp -d); cd "$work" | |
| git init -q -b "$BASELINE_BRANCH" | |
| cp /tmp/baseline.json synced.json | |
| git add synced.json | |
| git -c user.name="hex-dev sync" -c user.email="noreply@anthropic.com" \ | |
| commit -q -m "chore: sync baseline @ ${GITHUB_SHA:0:12}" | |
| git push -q -f \ | |
| "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \ | |
| "$BASELINE_BRANCH" | |
| echo "::notice::Advanced baseline pushed to $BASELINE_BRANCH." |