aur-publish #214
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: aur-publish | |
| # Reconcile only mcpp-bin. This workflow is downstream of `release`, so its | |
| # failure is visible without changing the already-terminal release conclusion. | |
| on: | |
| workflow_run: | |
| workflows: [release] | |
| types: [completed] | |
| schedule: | |
| - cron: '17 */6 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| publish: | |
| description: 'Publish the validated diff (false performs a dry-run only)' | |
| type: boolean | |
| required: true | |
| default: false | |
| tag: | |
| description: 'Optional exact latest complete stable tag (no downgrade override)' | |
| type: string | |
| required: false | |
| concurrency: | |
| group: aur-mcpp-bin-reconcile | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| reconcile: | |
| name: reconcile mcpp-bin | |
| if: >- | |
| github.event_name != 'workflow_run' || | |
| github.event.workflow_run.conclusion == 'success' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PYTHONDONTWRITEBYTECODE: '1' | |
| REQUESTED_TAG: ${{ inputs.tag }} | |
| steps: | |
| - name: Checkout reconciler source | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha || github.ref }} | |
| - name: Reconciler contract tests | |
| run: python3 tests/scripts/test_aur_reconcile.py | |
| # This phase has no SSH private key in its environment. It downloads the | |
| # immutable manifest and both Linux payload/sidecars, recomputes hashes, | |
| # runs makepkg as non-root in Arch, inspects RPC + HTTPS git, and emits the | |
| # exact diff before any publishing secret is loaded. | |
| - name: Inspect and validate desired state | |
| id: plan | |
| env: | |
| TRIGGER: ${{ github.event_name }} | |
| MANUAL_PUBLISH: ${{ inputs.publish }} | |
| # Repository variable, absent until a human has watched one publish | |
| # succeed. See "Arming the automatic triggers" in scripts/aur/README.md. | |
| AUTOPUBLISH: ${{ vars.AUR_AUTOPUBLISH }} | |
| run: | | |
| args=( | |
| --trigger "$TRIGGER" | |
| --report-json "$RUNNER_TEMP/aur-plan.json" | |
| --summary "$GITHUB_STEP_SUMMARY" | |
| ) | |
| [[ -z "$REQUESTED_TAG" ]] || args+=(--tag "$REQUESTED_TAG") | |
| python3 scripts/aur/reconcile_mcpp_bin.py "${args[@]}" | |
| # An unattended push to a third-party service must be ARMED, not | |
| # inherited from a merge. `schedule` fires every six hours off the | |
| # default branch, so merging this workflow used to be enough to make | |
| # mcpp start writing to the AUR on its own — before anyone had seen | |
| # the reconciler complete a real push even once. Both automatic | |
| # triggers therefore plan-and-report until AUR_AUTOPUBLISH is set; | |
| # `workflow_dispatch` keeps its explicit per-run switch, which is how | |
| # that first push is meant to happen. | |
| case "$TRIGGER" in | |
| workflow_run | schedule) | |
| if [[ "${AUTOPUBLISH:-}" == "true" ]]; then | |
| publish=true | |
| else | |
| publish=false | |
| echo "::notice::AUR_AUTOPUBLISH is not set — reporting the desired state without publishing." | |
| fi | |
| ;; | |
| *) | |
| publish=${MANUAL_PUBLISH:-false} | |
| ;; | |
| esac | |
| echo "needs_publish=$(jq -r '.needs_publish' "$RUNNER_TEMP/aur-plan.json")" >> "$GITHUB_OUTPUT" | |
| echo "publish=$publish" >> "$GITHUB_OUTPUT" | |
| - name: Configure pinned AUR SSH identity | |
| if: steps.plan.outputs.needs_publish == 'true' && steps.plan.outputs.publish == 'true' | |
| env: | |
| AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }} | |
| run: | | |
| test -n "$AUR_SSH_PRIVATE_KEY" || { echo 'AUR_SSH_PRIVATE_KEY is empty'; exit 1; } | |
| install -dm700 "$HOME/.ssh" | |
| install -m600 /dev/null "$HOME/.ssh/aur" | |
| printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > "$HOME/.ssh/aur" | |
| install -m600 scripts/aur/aur.archlinux.org.known_hosts "$HOME/.ssh/known_hosts" | |
| ssh-keygen -lf "$HOME/.ssh/known_hosts" -E sha256 \ | |
| | grep -F 'SHA256:RFzBCUItH9LZS0cKB5UE6ceAYhBD5C8GeOBip8Z11+4' | |
| install -m600 /dev/null "$HOME/.ssh/config" | |
| printf '%s\n' \ | |
| 'Host aur.archlinux.org' \ | |
| ' User aur' \ | |
| ' IdentityFile ~/.ssh/aur' \ | |
| ' IdentitiesOnly yes' \ | |
| ' StrictHostKeyChecking yes' \ | |
| ' UserKnownHostsFile ~/.ssh/known_hosts' \ | |
| > "$HOME/.ssh/config" | |
| - name: Fast-forward publish and verify convergence | |
| if: steps.plan.outputs.needs_publish == 'true' && steps.plan.outputs.publish == 'true' | |
| env: | |
| TRIGGER: ${{ github.event_name }} | |
| run: | | |
| args=( | |
| --publish | |
| --trigger "$TRIGGER" | |
| --report-json "$RUNNER_TEMP/aur-final.json" | |
| --summary "$GITHUB_STEP_SUMMARY" | |
| ) | |
| [[ -z "$REQUESTED_TAG" ]] || args+=(--tag "$REQUESTED_TAG") | |
| # ⚠️ EXIT 75 IS "THE PUSH LANDED, THE AUR'S INDEX HAS NOT CAUGHT UP", | |
| # AND FAILING ON IT MAKES THIS REPOSITORY'S CI RED FOR SOMEBODY ELSE'S | |
| # REFRESH SCHEDULE. | |
| # | |
| # The reconciler already classifies that case as TRANSIENT and exits | |
| # 75 (the conventional EX_TEMPFAIL) rather than 2. It is reached only | |
| # AFTER the git push has succeeded, so the AUR holds the new version | |
| # at that point; what has not happened is the AUR's own RPC metadata | |
| # refresh, which runs on a schedule measured in minutes. | |
| # | |
| # Measured twice (2026.8.21.2 and 2026.8.21.3): this step reported | |
| # `AUR RPC did not converge to <ver>` and the AUR RPC answered with | |
| # that exact version when asked afterwards. | |
| # | |
| # ⚠️ EVERY OTHER NON-ZERO CODE STILL FAILS. A refused downgrade (3) and | |
| # a permanent error (2) are this repository's problem and stay red. | |
| set +e | |
| python3 scripts/aur/reconcile_mcpp_bin.py "${args[@]}" | |
| rc=$? | |
| set -e | |
| if [[ "$rc" == "75" ]]; then | |
| echo "::warning::The push to the AUR succeeded; its RPC metadata had not refreshed within the poll window. Verify with: curl -s 'https://aur.archlinux.org/rpc/v5/info?arg[]=mcpp-bin'" | |
| elif [[ "$rc" != "0" ]]; then | |
| exit "$rc" | |
| fi | |
| - name: Preserve reconciliation reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: aur-mcpp-bin-reconciliation | |
| path: ${{ runner.temp }}/aur-*.json | |
| if-no-files-found: error |