Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ jobs:
- name: The tools of the CI stages pass their fixtures
run: |
python3 tests/scripts/test_classify_changes.py
python3 tests/scripts/test_notify_packages.py
python3 tests/scripts/test_check_e2e_coverage.py
python3 tests/scripts/test_check_default_toolchain_docs.py
python3 tests/scripts/test_check_provider_boundary.py
Expand Down
83 changes: 0 additions & 83 deletions .github/workflows/homebrew-publish.yml

This file was deleted.

119 changes: 119 additions & 0 deletions .github/workflows/publish-packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: publish-packages

# Notify repositories that own their package definitions. PyPI and AUR retain
# their own publishing workflows, credentials and verification contracts.
# Each target accepts mcpp-release and has a scheduled catch-up as a fallback.
# HOMEBREW_TAP_TOKEN and NIX_PUBLISH_TOKEN are optional fine-grained PATs with
# Contents: write on homebrew-mcpp and nix-mcpp respectively. Missing tokens
# are reported as skipped; accepted dispatches are not publication success.
on:
workflow_run:
workflows: [release]
types: [completed]
workflow_dispatch:
inputs:
tag:
description: 'Exact complete stable release tag, e.g. v2026.10.17.1'
type: string
required: true
channel:
description: 'Repository to notify'
type: choice
options: [all, homebrew, nix]
default: all

permissions:
contents: read

concurrency:
group: publish-packages
cancel-in-progress: false

jobs:
resolve:
name: resolve the sealed release
if: >-
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
contents: read
actions: read
outputs:
tag: ${{ steps.identity.outputs.tag }}
version: ${{ steps.identity.outputs.version }}
commit: ${{ steps.identity.outputs.commit }}
matrix: ${{ steps.identity.outputs.matrix }}
steps:
# Execute trusted notification code, never code from a downloaded artifact.
- uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false

- name: Read the manifest sealed by the completed release run
if: github.event_name == 'workflow_run'
uses: actions/download-artifact@v4
with:
name: mcpp-release-manifest
path: release-identity
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}

- name: Download the manually selected release manifest
if: github.event_name == 'workflow_dispatch'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
[[ "$TAG" =~ ^v[0-9]+(\.[0-9]+)+$ ]] || { echo 'Expected a stable release tag'; exit 1; }
mkdir -p release-identity
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" \
-p mcpp-release.json -O release-identity/mcpp-release.json

- name: Validate the manifest and select notification targets
id: identity
env:
REQUESTED_TAG: ${{ inputs.tag }}
CHANNEL: ${{ inputs.channel || 'all' }}
run: |
python3 tools/release/notify_packages.py resolve \
--manifest release-identity/mcpp-release.json \
--expected-tag "$REQUESTED_TAG" --channel "$CHANNEL"

- name: The public manifest matches the sealed release identity
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.identity.outputs.tag }}
run: |
set -euo pipefail
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" \
-p mcpp-release.json -O public-mcpp-release.json
cmp release-identity/mcpp-release.json public-mcpp-release.json

notify:
name: notify ${{ matrix.channel }}
needs: resolve
runs-on: ubuntu-24.04
timeout-minutes: 5
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.resolve.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false

- name: Send the release notification and report acceptance
env:
GH_TOKEN: ${{ secrets[matrix.token] }}
CHANNEL: ${{ matrix.channel }}
TAG: ${{ needs.resolve.outputs.tag }}
VERSION: ${{ needs.resolve.outputs.version }}
COMMIT: ${{ needs.resolve.outputs.commit }}
run: |
python3 tools/release/notify_packages.py notify \
--channel "$CHANNEL" --tag "$TAG" --version "$VERSION" --commit "$COMMIT"
2 changes: 1 addition & 1 deletion .github/workflows/pypi-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: pypi-publish

# Publish the `mcpp-bin` wheels to PyPI (`pip install mcpp-bin`).
#
# Downstream of `release`, like aur-publish.yml and homebrew-publish.yml: the
# Downstream of `release`, like aur-publish.yml and publish-packages.yml: the
# wheels are built from the release's own mcpp-release.json and payloads, so
# this runs only once the release workflow has completed.
#
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,18 @@ jobs:
cmp "$AUDIT_ROOT/final-assets/mcpp-release.json" \
"$AUDIT_ROOT/final-expected.json"
cat "$AUDIT_ROOT/final-assets/mcpp-release.json"
echo "SEALED_RELEASE_MANIFEST=$AUDIT_ROOT/final-assets/mcpp-release.json" >> "$GITHUB_ENV"

# Downstream notifications consume the identity sealed by THIS run,
# including workflow_dispatch rebuilds of a tag other than main's version.
- name: Save the sealed manifest for package notifications
uses: actions/upload-artifact@v4
with:
name: mcpp-release-manifest
path: ${{ env.SEALED_RELEASE_MANIFEST }}
if-no-files-found: error
overwrite: true # A rerun has already proved the public bytes identical.
retention-days: 30

# Publish this release into the xlings ecosystem, after ALL platform builds
# have uploaded their assets and the immutable manifest gate has passed:
Expand Down
Loading
Loading