Skip to content

Prepare Release - Step 3 - Build artifacts and draft a release #3

Prepare Release - Step 3 - Build artifacts and draft a release

Prepare Release - Step 3 - Build artifacts and draft a release #3

name: Prepare Release - Step 3 - Build artifacts and draft a release
on:
workflow_call:
inputs:
sha:
description: Full SHA of the commit to release from
required: true
type: string
workflow_dispatch:
jobs:
build:
name: Build package
runs-on: ubuntu-latest
permissions:
id-token: write
attestations: write
artifact-metadata: write
outputs:
attestation_artifact_id: ${{ steps.attestations_upload.outputs.artifact-id }}
sums_artifact_id: ${{ steps.sums_upload.outputs.artifact-id }}
sdist_artifact_id: ${{ steps.sdist_upload.outputs.artifact-id }}
wheel_artifact_id: ${{ steps.wheel_upload.outputs.artifact-id }}
attestation_url: ${{ steps.attest.outputs.attestation-url }}
run_id: ${{ github.run_id }}
run_attempt: ${{ github.run_attempt }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.sha || github.sha }}
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.8"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade build twine
- name: Build distributions
run: |
SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
python -m build
- name: Check built distributions
run: python -m twine check dist/*
- name: Generate checksums
working-directory: dist
run: |
sha256sum * | tee SHA256SUMS
- name: Generate attestations
id: attest
uses: actions/attest@v4
with:
subject-checksums: dist/SHA256SUMS
- name: Upload attestations bundle
id: attestations_upload
uses: actions/upload-artifact@v7
with:
name: attestation.json
path: ${{ steps.attest.outputs.bundle-path }}
archive: false
- name: Upload checksums
id: sums_upload
uses: actions/upload-artifact@v7
with:
path: ./dist/SHA256SUMS
archive: false
- name: Upload sdist
id: sdist_upload
uses: actions/upload-artifact@v7
with:
path: ./dist/*.tar.gz
archive: false
if-no-files-found: error
- name: Upload built wheel
id: wheel_upload
uses: actions/upload-artifact@v7
with:
path: ./dist/*.whl
archive: false
if-no-files-found: error
draft_release:
name: Make a draft release
runs-on: ubuntu-latest
needs: build
permissions:
attestations: read
contents: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.commit || github.sha }}
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.8"
- name: Get version to release
id: version_to_release
run: |
venv_dir=$(mktemp -d)
python -m venv "$venv_dir"
"$venv_dir"/bin/pip install -U packaging
"$venv_dir"/bin/python .github/workflows/scripts/bump_version.py
env:
JUST_RETURN_VERSION: '1'
- name: Download distributions
uses: actions/download-artifact@v8
with:
artifact-ids: >-
${{ needs.build.outputs.attestation_artifact_id }},
${{ needs.build.outputs.sums_artifact_id }},
${{ needs.build.outputs.sdist_artifact_id }},
${{ needs.build.outputs.wheel_artifact_id }}
path: dist/
merge-multiple: true
# This is done solely to verify that the attestations work as expected,
# not to actually verify the integrity since GitHub has control over
# both the artifacts and attestations here.
- name: Verify integrity of artifacts
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_RUN_ID: ${{ needs.build.outputs.run_id }}
BUILD_RUN_ATTEMPT: ${{ needs.build.outputs.run_attempt }}
working-directory: dist
run: |
expected_run_invocation_uri=(
"https://github.com/$GH_REPO/actions/runs/$BUILD_RUN_ID/attempts/$BUILD_RUN_ATTEMPT"
)
for file in *; do
if [[ "$file" == 'SHA256SUMS' || "$file" == 'attestation.json' ]]; then
continue
fi
run_invocation_uri=$(
GH_FORCE_TTY=1 gh attestation verify "$file" --repo "$GH_REPO" \
--format=json --jq '.[0].verificationResult.signature.certificate.runInvocationURI'
)
if [[ "$run_invocation_uri" != "$expected_run_invocation_uri" ]]; then
echo "Got unexpected invocation URI for file: $file"
echo "Expected: $expected_run_invocation_uri"
echo "Actual: $run_invocation_uri"
exit 1
fi
done
- name: Create a draft release
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version_to_release.outputs.version }}
PRERELEASE_FLAG: |-
${{
steps.version_to_release.outputs.is_prerelease == '1'
&& '--prerelease'
|| ''
}}
RELEASE_NOTES: |
TODO: UPDATE RELEASE DESCRIPTION
Artifact attestations available at:
${{ needs.build.outputs.attestation_url }}
RELEASE_TARGET: ${{ inputs.commit || github.sha }}
run: |
gh release create $PRERELEASE_FLAG "$VERSION" dist/* \
--draft \
--title "v$VERSION" \
--notes "$RELEASE_NOTES" \
--target $RELEASE_TARGET