misc #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| on: | |
| push: | |
| branches: [ main ] | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| concurrency: release | |
| env: | |
| FORCE_PATCH_IF_NO_COMMIT_TOKEN: true | |
| IGNORE_PATHS: | | |
| resources/** | |
| assets/** | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Compute bumped version | |
| id: version | |
| env: | |
| FORCE_PATCH_IF_NO_COMMIT_TOKEN: ${{ env.FORCE_PATCH_IF_NO_COMMIT_TOKEN }} | |
| IGNORE_PATHS: ${{ env.IGNORE_PATHS }} | |
| run: | | |
| set -euo pipefail | |
| echo "now: $(date -u +"%Y-%m-%dT%H:%M:%S.%3N")" | |
| echo | |
| # get the latest semantic-version style tag | |
| _latest_semver_tag=$(git tag --sort=-creatordate | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -n1 || true) | |
| echo "Latest semantic-version style tag: $_latest_semver_tag" | |
| echo | |
| if [ -z "$_latest_semver_tag" ]; then | |
| echo "No previous semver tag found — using 0.0.0" | |
| echo "version=0.0.0" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| else | |
| export LATEST_SEMVER_TAG_NO_V="${_latest_semver_tag#v}" | |
| fi | |
| # get info on what's changed since that tag | |
| _that_commit=$(git rev-list -n 1 "$_latest_semver_tag") | |
| echo "Looking at what's changed since $_latest_semver_tag / $_that_commit..." | |
| echo | |
| # | |
| export CHANGED_FILES=$(git diff --name-only "$_that_commit"..HEAD) # has newlines | |
| echo "Changed files:" | |
| echo "<start>" | |
| echo "$CHANGED_FILES" | |
| echo "<end>" | |
| echo | |
| # | |
| export COMMIT_LOG=$(git log "$_that_commit"..HEAD --pretty=%B) # has newlines | |
| echo "Commit log(s) since then:" | |
| echo "<start>" | |
| echo "$COMMIT_LOG" | |
| echo "<end>" | |
| echo | |
| # get next version | |
| VERSION=$(python compute_next_version.py) | |
| # handle output | |
| if [ -z "$VERSION" ]; then | |
| echo "No release needed — skipping" | |
| echo "version=" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Bumped version: $VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install build tools | |
| if: steps.version.outputs.version != '' | |
| run: | | |
| set -euo pipefail | |
| echo "now: $(date -u +"%Y-%m-%dT%H:%M:%S.%3N")" | |
| exit 1 # TODO: REMOVE | |
| python -m pip install --upgrade pip | |
| pip install build twine setuptools setuptools-scm | |
| - name: Build package | |
| if: steps.version.outputs.version != '' | |
| run: | | |
| set -euo pipefail | |
| echo "now: $(date -u +"%Y-%m-%dT%H:%M:%S.%3N")" | |
| # Validate setuptools-scm usage | |
| if ! grep -q 'setuptools-scm' pyproject.toml; then | |
| echo "❌ setuptools-scm not found in pyproject.toml — aborting" | |
| exit 1 | |
| fi | |
| if grep -A 5 '^\[project\]' pyproject.toml | grep -q '^version\s*='; then | |
| echo "❌ [project] version is explicitly set — must be managed by setuptools-scm" | |
| exit 1 | |
| fi | |
| echo "✅ setuptools-scm is configured properly" | |
| SETUPTOOLS_SCM_PRETEND_VERSION=${{ steps.version.outputs.version }} python -m build | |
| - name: Create GitHub Release via API | |
| if: steps.version.outputs.version != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| echo "now: $(date -u +"%Y-%m-%dT%H:%M:%S.%3N")" | |
| API_URL="https://api.github.com/repos/${{ github.repository }}/releases" | |
| TAG="release-${VERSION}" | |
| PAYLOAD=$(jq -n \ | |
| --arg tag_name "$TAG" \ | |
| --arg target_commitish "${{ github.sha }}" \ | |
| --arg name "Release $VERSION" \ | |
| --arg body "Automated release for commit ${{ github.sha }}" \ | |
| '{ tag_name: $tag_name, target_commitish: $target_commitish, name: $name, body: $body, draft: false, prerelease: false }') | |
| curl -sSf -X POST -H "Authorization: Bearer $GH_TOKEN" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$PAYLOAD" "$API_URL" | |
| - name: Upload to PyPI | |
| if: steps.version.outputs.version != '' | |
| env: | |
| TWINE_USERNAME: __token__ | |
| TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| echo "now: $(date -u +"%Y-%m-%dT%H:%M:%S.%3N")" | |
| twine upload dist/* |