Skip to content

Release from main

Release from main #7

name: Release Publish
run-name: Release from main
on:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: release-publish-${{ github.ref }}
cancel-in-progress: false
jobs:
build_binaries:
name: Build binaries (${{ matrix.package-suffix }})
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
package-suffix: linux-amd64
- os: ubuntu-arm
package-suffix: linux-aarch64
runsOn: ubuntu-24.04-arm64-2-core
- os: macos-intel
package-suffix: macos-amd64
runsOn: macos-15-intel
- os: macos-arm
package-suffix: macos-aarch64
runsOn: macos-14
- os: windows-latest
package-suffix: windows-amd64
runs-on: ${{ matrix.runsOn || matrix.os }}
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.sha }}
submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.14"
# Install Rust locally for non-Linux (Linux uses an internal docker
# command to build with cibuildwheel which uses rustup install defined
# in pyproject.toml)
- if: ${{ runner.os != 'Linux' }}
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- if: ${{ runner.os != 'Linux' }}
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
cache-bin: false
workspaces: temporalio/bridge -> target
key: ${{ env.pythonLocation }}
- uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
- run: uv sync --all-extras
# Add the source dist only for Linux x64 for now
- if: ${{ matrix.package-suffix == 'linux-amd64' }}
run: uv build --sdist
# Build the wheel
- run: uv run cibuildwheel --output-dir dist
# Install the wheel in a new venv and run a test
- name: Test wheel
shell: bash
run: |
mkdir __test_wheel__
cd __test_wheel__
cp -r ../tests .
python -m venv .venv
bindir=bin
if [ "$RUNNER_OS" = "Windows" ]; then
bindir=Scripts
fi
./.venv/$bindir/pip install pytest pytest_asyncio grpcio pydantic opentelemetry-api opentelemetry-sdk
./.venv/$bindir/pip install --prefer-binary ../dist/*.whl
./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello
# Upload dist
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: packages-${{ matrix.package-suffix }}
path: dist
verify_artifacts:
name: Verify release artifacts
needs: build_binaries
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
actions: read
contents: read
outputs:
release_sha: ${{ steps.validate_versions.outputs.sha }}
version: ${{ steps.validate_versions.outputs.version }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.sha }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.11"
- name: Validate checked-in versions
id: validate_versions
run: |
set -euo pipefail
python .github/scripts/release_verify.py validate-version \
--sha "$(git rev-parse HEAD)" \
--github-output "$GITHUB_OUTPUT"
- name: Download and flatten artifacts
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir artifacts dist
gh run download "$GITHUB_RUN_ID" \
--repo "$GITHUB_REPOSITORY" \
--dir artifacts \
--pattern 'packages-*'
while IFS= read -r -d '' file; do
dest="dist/$(basename "$file")"
if [[ -e "$dest" ]]; then
echo "Duplicate distribution filename: $(basename "$file")" >&2
exit 1
fi
cp "$file" "$dest"
done < <(find artifacts -type f \( -name '*.whl' -o -name '*.tar.gz' \) -print0)
- name: Verify release artifacts
env:
VERSION: ${{ steps.validate_versions.outputs.version }}
run: |
set -euo pipefail
python .github/scripts/release_verify.py verify-dist --version "$VERSION"
- name: Upload verified release artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: release-dist-${{ steps.validate_versions.outputs.version }}
path: dist
if-no-files-found: error
retention-days: 14
publish_testpypi:
name: Publish to TestPyPI
needs: verify_artifacts
runs-on: ubuntu-latest
timeout-minutes: 10
environment: testpypi
permissions:
actions: read
contents: read
id-token: write
steps:
- name: Download verified release artifact
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.verify_artifacts.outputs.version }}
run: |
set -euo pipefail
mkdir downloaded dist
gh run download "$GITHUB_RUN_ID" \
--repo "$GITHUB_REPOSITORY" \
--name "release-dist-$VERSION" \
--dir downloaded
while IFS= read -r -d '' file; do
cp "$file" "dist/$(basename "$file")"
done < <(find downloaded -type f \( -name '*.whl' -o -name '*.tar.gz' \) -print0)
test "$(find dist -type f | wc -l)" -gt 0
- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
with:
packages-dir: dist/
repository-url: https://test.pypi.org/legacy/
skip-existing: true
smoke_testpypi:
name: Smoke test TestPyPI package
needs:
- verify_artifacts
- publish_testpypi
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: ./.github/actions/release-smoke-package
with:
version: ${{ needs.verify_artifacts.outputs.version }}
index-url: https://test.pypi.org/simple/
dependency-index-url: https://pypi.org/simple/
publish_pypi:
name: Publish to PyPI
needs:
- verify_artifacts
- smoke_testpypi
runs-on: ubuntu-latest
timeout-minutes: 10
environment: pypi
permissions:
actions: read
contents: read
id-token: write
steps:
- name: Download verified release artifact
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.verify_artifacts.outputs.version }}
run: |
set -euo pipefail
mkdir downloaded dist
gh run download "$GITHUB_RUN_ID" \
--repo "$GITHUB_REPOSITORY" \
--name "release-dist-$VERSION" \
--dir downloaded
while IFS= read -r -d '' file; do
cp "$file" "dist/$(basename "$file")"
done < <(find downloaded -type f \( -name '*.whl' -o -name '*.tar.gz' \) -print0)
test "$(find dist -type f | wc -l)" -gt 0
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
with:
packages-dir: dist/
smoke_pypi:
name: Smoke test PyPI package
needs:
- verify_artifacts
- publish_pypi
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: ./.github/actions/release-smoke-package
with:
version: ${{ needs.verify_artifacts.outputs.version }}
index-url: https://pypi.org/simple/
create_draft_release:
name: Create draft GitHub Release
needs:
- verify_artifacts
- smoke_pypi
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: write
steps:
- name: Create draft release with generated notes
env:
GH_TOKEN: ${{ github.token }}
RELEASE_SHA: ${{ needs.verify_artifacts.outputs.release_sha }}
VERSION: ${{ needs.verify_artifacts.outputs.version }}
run: |
set -euo pipefail
gh release create "$VERSION" \
--repo "$GITHUB_REPOSITORY" \
--target "$RELEASE_SHA" \
--title "$VERSION" \
--draft \
--generate-notes