Skip to content

Release

Release #299

Workflow file for this run

name: Release
on:
workflow_run:
workflows: ["Tests"]
types: [completed]
jobs:
check-tag:
name: Verify release trigger
runs-on: ubuntu-latest
timeout-minutes: 2
if: github.event.repository.fork == false && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push'
permissions:
contents: read
outputs:
is_tag: ${{ steps.tag.outputs.is_tag }}
tag: ${{ steps.tag.outputs.tag }}
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
- name: Verify HEAD is tagged
id: tag
run: |
T=$(git describe --tags --exact-match HEAD 2>/dev/null) || true
if [ -n "$T" ]; then echo "is_tag=true" >> $GITHUB_OUTPUT; echo "tag=$T" >> $GITHUB_OUTPUT; else echo "is_tag=false" >> $GITHUB_OUTPUT; echo "tag=" >> $GITHUB_OUTPUT; fi
reproducible-build:
name: Reproducible build verification
needs: [check-tag]
timeout-minutes: 5
if: needs.check-tag.outputs.is_tag == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
- name: Install uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: true
cache-python: true
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
run: uv python install 3.12
- name: First build (from lockfile)
env:
SOURCE_DATE_EPOCH: "0"
run: |
uv sync --frozen --group dev --all-extras
uv build
mkdir -p dist1 && cp dist/*.whl dist/*.tar.gz dist1/
- name: Second build (same environment)
env:
SOURCE_DATE_EPOCH: "0"
run: |
rm -rf dist build src/*.egg-info *.egg-info 2>/dev/null || true
uv sync --frozen --group dev --all-extras
uv build
mkdir -p dist2 && cp dist/*.whl dist/*.tar.gz dist2/
- name: Compare wheel hashes
run: |
for f in dist1/*.whl; do
name=$(basename "$f")
h1=$(sha256sum "dist1/$name" | cut -d' ' -f1)
h2=$(sha256sum "dist2/$name" | cut -d' ' -f1)
if [ "$h1" != "$h2" ]; then
echo "Hash mismatch for $name"
exit 1
fi
echo "OK $name"
done
echo "Reproducible: wheel hashes match (same runner, Python 3.12, lockfile, SOURCE_DATE_EPOCH=0)."
- name: Upload verified dist
run: mkdir -p dist && cp dist1/* dist/
- name: Upload dist
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dist
path: dist/
release-assets:
name: Attach dist to GitHub Release
needs: [check-tag, reproducible-build]
if: needs.check-tag.outputs.is_tag == 'true'
runs-on: ubuntu-latest
timeout-minutes: 3
permissions:
contents: write
steps:
- name: Download dist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: dist
merge-multiple: true
- name: Attach wheel and sdist to Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
shopt -s nullglob
assets=(dist/*.whl dist/*.tar.gz)
if [ "${#assets[@]}" -eq 0 ]; then
echo "No wheel or sdist found under dist/"
exit 1
fi
gh release upload "${{ needs.check-tag.outputs.tag }}" "${assets[@]}" \
--repo "${{ github.repository }}" \
--clobber
pypi:
name: Publish to PyPI
needs: [check-tag, reproducible-build]
timeout-minutes: 5
if: needs.check-tag.outputs.is_tag == 'true'
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/litestar-auth
permissions:
contents: read
id-token: write
steps:
- name: Download dist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: dist
merge-multiple: true
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
docs:
name: Deploy documentation
needs: [check-tag]
if: needs.check-tag.outputs.is_tag == 'true'
runs-on: ubuntu-latest
timeout-minutes: 5
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
contents: read
pages: write
id-token: write
steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
- name: Configure Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Install uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
enable-cache: true
cache-python: true
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
run: uv python install 3.12
- name: Install docs dependencies
run: uv sync --frozen --group docs
- name: Build documentation
run: uv run zensical build --clean
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: site
# Default name "github-pages" duplicates across re-runs; deploy-pages then fails with
# "Multiple artifacts named github-pages were unexpectedly found".
name: github-pages-${{ github.run_id }}-${{ github.run_attempt }}
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
id: deployment
with:
artifact_name: github-pages-${{ github.run_id }}-${{ github.run_attempt }}