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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
194 changes: 194 additions & 0 deletions .github/workflows/_publish_wheel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT

name: Publish wheels

on:
workflow_call:
inputs:
artifact-pattern:
description: Pattern selecting the wheel artifacts to publish.
required: true
type: string
artifact-path:
description: Directory into which wheel artifacts are downloaded.
required: false
default: dist
type: string
gpl-sources-artifact:
description: Optional artifact containing gpl-sources.tar.
required: false
default: ''
type: string
gpl-sources-description:
description: Optional description of the bundled GPL sources.
required: false
default: ''
type: string

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout python-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Download wheels
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: ${{ inputs.artifact-pattern }}
path: ${{ inputs.artifact-path }}
merge-multiple: true

- name: Download GPL sources artifact
if: inputs.gpl-sources-artifact != ''
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ inputs.gpl-sources-artifact }}
path: gpl-sources

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3'

- name: Install publishing dependencies
run: pip install pyyaml

- name: Inspect wheels and prepare release
id: release
env:
ARTIFACTS_PATH: ${{ inputs.artifact-path }}
run: |
python3 - <<'PY'
import hashlib
import os
import re
import zipfile
from datetime import datetime, timezone
from email.parser import Parser
from pathlib import Path

wheels = sorted(Path(os.environ["ARTIFACTS_PATH"]).glob("*.whl"))
if not wheels:
raise SystemExit(f"No wheels found in {os.environ['ARTIFACTS_PATH']}")

metadata = []
for wheel in wheels:
with zipfile.ZipFile(wheel) as archive:
metadata_path = next(
(name for name in archive.namelist() if name.endswith(".dist-info/METADATA")),
None,
)
if metadata_path is None:
raise SystemExit(f"{wheel} has no .dist-info/METADATA")
message = Parser().parsestr(archive.read(metadata_path).decode())
name = message.get("Name")
version = message.get("Version")
if not name or not version:
raise SystemExit(f"Name or Version is missing from {wheel}")
metadata.append((name, version, wheel))

normalized_names = {re.sub(r"[-_.]+", "-", name).lower() for name, _, _ in metadata}
versions = {version for _, version, _ in metadata}
if len(normalized_names) != 1 or len(versions) != 1:
raise SystemExit(f"Wheels contain mixed projects or versions: {metadata}")

package = normalized_names.pop()
version = versions.pop()
title = f"{package}-v{version}"
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
tag = f"{title}-{timestamp}"

output = Path(os.environ["GITHUB_OUTPUT"])
with output.open("a") as stream:
stream.write(f"package={package}\nversion={version}\ntitle={title}\ntag={tag}\n")

print(f"Release title: {title}")
print(f"Release tag: {tag}")
for _, _, wheel in metadata:
print(f"{hashlib.sha256(wheel.read_bytes()).hexdigest()} {wheel}")
PY

- name: Validate GPL sources artifact
if: inputs.gpl-sources-artifact != ''
run: test -f gpl-sources/gpl-sources.tar

- name: Show dry run
if: github.ref != 'refs/heads/main'
env:
RELEASE_TAG: ${{ steps.release.outputs.tag }}
RELEASE_TITLE: ${{ steps.release.outputs.title }}
ARTIFACTS_PATH: ${{ inputs.artifact-path }}
run: |
{
echo "### GitHub Release dry run"
echo "Would create release \`$RELEASE_TAG\` with title \`$RELEASE_TITLE\`."
find "$ARTIFACTS_PATH" -maxdepth 1 -type f -name "*.whl" -printf "- \`%f\`\n"
} >> "$GITHUB_STEP_SUMMARY"

- name: Require immutable releases
if: github.ref == 'refs/heads/main'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
enabled=$(gh api \
"repos/${{ github.repository }}/immutable-releases" \
--jq '.enabled')
if [[ "$enabled" != 'true' ]]; then
echo "::error::Immutable releases must be enabled for ${{ github.repository }}."
exit 1
fi

- name: Create draft release and upload assets
if: github.ref == 'refs/heads/main'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ steps.release.outputs.tag }}
RELEASE_TITLE: ${{ steps.release.outputs.title }}
run: |
set -euo pipefail
notes=$(cat <<EOF
Published by [GitHub Actions workflow run ${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).
EOF
)
gh release create "$RELEASE_TAG" \
--repo "${{ github.repository }}" \
--target "${{ github.sha }}" \
--title "$RELEASE_TITLE" \
--notes "$notes" \
--draft \
--latest=false
gh release upload "$RELEASE_TAG" "${{ inputs.artifact-path }}"/*.whl \
--repo "${{ github.repository }}"
if [[ "${{ inputs.gpl-sources-artifact }}" != '' ]]; then
gh release upload "$RELEASE_TAG" gpl-sources/gpl-sources.tar \
--repo "${{ github.repository }}"
fi
gh release edit "$RELEASE_TAG" \
--repo "${{ github.repository }}" \
--draft=false \
--latest=false

- name: Verify release is immutable
if: github.ref == 'refs/heads/main'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
immutable=$(gh api \
"repos/${{ github.repository }}/releases/tags/${{ steps.release.outputs.tag }}" \
--jq '.immutable')
if [[ "$immutable" != 'true' ]]; then
echo "::error::Published release is not immutable."
exit 1
fi

- name: Update package documentation
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ARTIFACTS_PATH: ${{ inputs.artifact-path }}
RELEASE_TAG: ${{ steps.release.outputs.tag }}
GPL_SOURCES_DESCRIPTION: ${{ inputs.gpl-sources-description }}
DRY_RUN: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }}
run: python3 ci_scripts/update_doc.py
16 changes: 4 additions & 12 deletions .github/workflows/build-amazon-ion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish amazon-ion ${{ inputs.version || '0.14.6' }} to GitLab
name: Publish amazon-ion ${{ inputs.version || '0.14.6' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: amazon-ion-${{ env.AMAZON_ION_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: amazon-ion-${{ inputs.version || '0.14.6' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-apache-tvm-ffi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,19 +178,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish apache-tvm-ffi ${{ inputs.version || '0.1.12' }} to GitLab
name: Publish apache-tvm-ffi ${{ inputs.version || '0.1.12' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: apache-tvm-ffi-${{ env.TVM_FFI_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: apache-tvm-ffi-${{ inputs.version || '0.1.12' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-array-record.yml
Original file line number Diff line number Diff line change
Expand Up @@ -311,19 +311,11 @@ jobs:
SCRIPT

publish:
name: Publish array-record ${{ inputs.version || '0.8.3' }} to GitLab
name: Publish array-record ${{ inputs.version || '0.8.3' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: array-record-${{ env.ARRAY_RECORD_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: array-record-${{ inputs.version || '0.8.3' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-arro3-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,19 +302,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish arro3-core ${{ inputs.version || '0.8.1' }} to GitLab
name: Publish arro3-core ${{ inputs.version || '0.8.1' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: arro3-core-${{ env.ARRO3_CORE_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: arro3-core-${{ inputs.version || '0.8.1' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-astropy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish astropy ${{ inputs.version || '8.0.1' }} to GitLab
name: Publish astropy ${{ inputs.version || '8.0.1' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: astropy-${{ env.ASTROPY_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: astropy-${{ inputs.version || '8.0.1' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-asyncpg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish asyncpg ${{ inputs.version || '0.31.0' }} to GitLab
name: Publish asyncpg ${{ inputs.version || '0.31.0' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: asyncpg-${{ env.ASYNCPG_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: asyncpg-${{ inputs.version || '0.31.0' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-awscrt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish awscrt ${{ inputs.version || '0.36.2' }} to GitLab
name: Publish awscrt ${{ inputs.version || '0.36.2' }}
needs: [setup, build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: awscrt-${{ env.AWSCRT_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: awscrt-${{ inputs.version || '0.36.2' }}-*-manylinux_riscv64
16 changes: 4 additions & 12 deletions .github/workflows/build-bcrypt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,11 @@ jobs:
if-no-files-found: error

publish:
name: Publish bcrypt ${{ inputs.version || '5.0.0' }} to GitLab
name: Publish bcrypt ${{ inputs.version || '5.0.0' }}
needs: [setup, build_sdist, build_abi3, build_freethreaded]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: bcrypt-${{ needs.build_sdist.outputs.package_version }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
uses: $/.github/workflows/_publish_wheel.yml
with:
artifact-pattern: bcrypt-${{ needs.build_sdist.outputs.package_version }}-*-manylinux_riscv64
Loading
Loading