release #38
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
| # GitHub Actions workflow for building and publishing txaio releases. | |
| # This follows the autobahn-python/zlmdb/crossbar model using workflow_run triggers. | |
| name: release | |
| on: | |
| # Auto-trigger after main workflow completes (NOT direct push/pr triggers) | |
| workflow_run: | |
| workflows: ["main"] | |
| types: [completed] | |
| # Manual dispatch for debugging | |
| workflow_dispatch: | |
| permissions: | |
| id-token: write # Required for PyPI trusted publishing (OIDC) | |
| contents: write # Required for creating GitHub releases | |
| pull-requests: read # Required for identifiers workflow | |
| env: | |
| UV_CACHE_DIR: ${{ github.workspace }}/.uv-cache | |
| jobs: | |
| check-main-workflow: | |
| name: Check if main workflow completed successfully | |
| runs-on: ubuntu-latest | |
| outputs: | |
| main_run_id: ${{ steps.check.outputs.main_run_id }} | |
| should_proceed: ${{ steps.check.outputs.should_proceed }} | |
| steps: | |
| - name: Check main workflow completion | |
| id: check | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const commitSha = context.payload.workflow_run?.head_sha || context.sha; | |
| const triggeredBy = context.payload.workflow_run?.name || 'manual (workflow_dispatch)'; | |
| console.log('─────────────────────────────────────────────────'); | |
| console.log('🔍 Checking main workflow completion status'); | |
| console.log('─────────────────────────────────────────────────'); | |
| console.log(`Event: ${context.eventName}`); | |
| console.log(`Commit SHA: ${commitSha}`); | |
| console.log(`Triggered by: ${triggeredBy}`); | |
| console.log(''); | |
| // Get workflow runs for this commit | |
| const { data: runs } = await github.rest.actions.listWorkflowRunsForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| head_sha: commitSha, | |
| per_page: 100 | |
| }); | |
| // Find latest main workflow run | |
| const mainRun = runs.workflow_runs | |
| .filter(run => run.name === 'main') | |
| .sort((a, b) => b.id - a.id)[0]; | |
| const mainComplete = mainRun && mainRun.status === 'completed' && mainRun.conclusion === 'success'; | |
| const status = mainRun ? `${mainRun.status}/${mainRun.conclusion}` : 'not found'; | |
| console.log(`Main workflow: ${status}`); | |
| console.log(''); | |
| if (!mainComplete) { | |
| console.log('⏳ Main workflow not complete yet - exiting early'); | |
| console.log(' This is normal! Release will proceed once main workflow finishes.'); | |
| } else { | |
| console.log('✅ Main workflow complete - proceeding with release!'); | |
| } | |
| console.log('─────────────────────────────────────────────────'); | |
| core.setOutput('should_proceed', mainComplete ? 'true' : 'false'); | |
| core.setOutput('main_run_id', mainRun?.id || ''); | |
| identifiers: | |
| name: Identifiers | |
| needs: check-main-workflow | |
| if: needs.check-main-workflow.outputs.should_proceed == 'true' | |
| # GitHub needs to know where .cicd/workflows/identifiers.yml lives at parse time, | |
| # and submodules aren't included in that context! thus the following does NOT work: | |
| # uses: ./.cicd/workflows/identifiers.yml | |
| # we MUST reference the remote repo directly: | |
| uses: wamp-proto/wamp-cicd/.github/workflows/identifiers.yml@main | |
| # IMPORTANT: we still need .cicd as a Git submodule in the using repo though! | |
| # because e.g. identifiers.yml wants to access scripts/sanitize.sh ! | |
| # Development/Nightly GitHub releases (for untagged master builds) | |
| release-development: | |
| name: Development/Nightly GitHub Release | |
| needs: [check-main-workflow, identifiers] | |
| runs-on: ubuntu-latest | |
| # Only create releases for development/nightly builds (not stable tags) | |
| if: | | |
| needs.check-main-workflow.outputs.should_proceed == 'true' && | |
| (github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')) && | |
| (needs.identifiers.outputs.release_type == 'development' || needs.identifiers.outputs.release_type == 'nightly') | |
| env: | |
| RELEASE_TYPE: ${{ needs.identifiers.outputs.release_type }} | |
| RELEASE_NAME: ${{ needs.identifiers.outputs.release_name }} | |
| permissions: | |
| contents: write # Required for creating releases | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Install Just | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/bin | |
| echo "$HOME/bin" >> $GITHUB_PATH | |
| - name: Install uv | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| source $HOME/.cargo/env | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| - name: Setup uv cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ env.UV_CACHE_DIR }} | |
| key: uv-cache-ubuntu-release-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| uv-cache-ubuntu-release- | |
| - name: Build package (wheel and source distribution) | |
| run: just build cpy311 | |
| - name: Build documentation | |
| run: | | |
| just create cpy314 | |
| just install-tools cpy314 | |
| just docs cpy314 | |
| - name: Create documentation archive | |
| run: | | |
| cd docs/_build/html | |
| tar -czf ../../../dist/txaio-docs.tar.gz * | |
| cd ../../.. | |
| - name: Generate checksums | |
| run: | | |
| cd dist | |
| sha256sum * > CHECKSUMS-ALL.sha256 | |
| cat CHECKSUMS-ALL.sha256 | |
| - name: List built packages | |
| run: | | |
| echo "Built packages:" | |
| ls -lh dist/ | |
| - name: Create development GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.identifiers.outputs.release_name }} | |
| name: Development Build ${{ needs.identifiers.outputs.release_name }} | |
| body: | | |
| ## txaio Development Build | |
| **Release:** ${{ needs.identifiers.outputs.release_name }} | |
| **Type:** ${{ needs.identifiers.outputs.release_type }} | |
| **Branch:** ${{ needs.identifiers.outputs.base_branch }} | |
| **Commit:** ${{ needs.identifiers.outputs.head_sha }} | |
| This is an automated development/nightly build for testing purposes. | |
| **Installation:** | |
| ```bash | |
| pip install https://github.com/crossbario/txaio/releases/download/${{ needs.identifiers.outputs.release_name }}/txaio-*.whl | |
| ``` | |
| **Files:** | |
| - Universal wheel (py3-none-any) | |
| - Source distribution (.tar.gz) | |
| - Documentation archive | |
| - SHA256 checksums (CHECKSUMS-ALL.sha256) | |
| ⚠️ This is a development build - for production use, install from PyPI. | |
| files: dist/* | |
| draft: false | |
| prerelease: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Production releases (for tagged stable builds) - GitHub + PyPI | |
| release-production: | |
| name: Production Release (GitHub + PyPI) | |
| needs: [check-main-workflow, identifiers] | |
| runs-on: ubuntu-latest | |
| # Only publish to PyPI for stable releases (explicit tag check) | |
| if: | | |
| needs.check-main-workflow.outputs.should_proceed == 'true' && | |
| (github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')) && | |
| needs.identifiers.outputs.release_type == 'stable' | |
| env: | |
| RELEASE_TYPE: ${{ needs.identifiers.outputs.release_type }} | |
| RELEASE_NAME: ${{ needs.identifiers.outputs.release_name }} | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/txaio | |
| permissions: | |
| id-token: write # For trusted publishing | |
| contents: write # For GitHub releases | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Install Just | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/bin | |
| echo "$HOME/bin" >> $GITHUB_PATH | |
| - name: Install uv | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| source $HOME/.cargo/env | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| - name: Setup uv cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ env.UV_CACHE_DIR }} | |
| key: uv-cache-ubuntu-release-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| uv-cache-ubuntu-release- | |
| - name: Build package (wheel and source distribution) | |
| run: just build cpy311 | |
| - name: Build documentation | |
| run: | | |
| just create cpy314 | |
| just install-tools cpy314 | |
| just docs cpy314 | |
| - name: Create documentation archive | |
| run: | | |
| cd docs/_build/html | |
| tar -czf ../../../dist/txaio-docs.tar.gz * | |
| cd ../../.. | |
| - name: Generate checksums (for GitHub release) | |
| run: | | |
| cd dist | |
| sha256sum * > CHECKSUMS-ALL.sha256 | |
| cat CHECKSUMS-ALL.sha256 | |
| - name: List built packages | |
| run: | | |
| echo "Built packages:" | |
| ls -lh dist/ | |
| - name: Get version | |
| id: get_version | |
| run: | | |
| VERSION="${RELEASE_NAME#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Version: $VERSION" | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: v${{ steps.get_version.outputs.version }} | |
| body: | | |
| ## txaio v${{ steps.get_version.outputs.version }} | |
| txaio - Compatibility API for Twisted and asyncio | |
| **Installation:** | |
| ```bash | |
| pip install txaio==${{ steps.get_version.outputs.version }} | |
| ``` | |
| **Links:** | |
| - 📦 PyPI: https://pypi.org/project/txaio/${{ steps.get_version.outputs.version }}/ | |
| - 📖 Docs: https://txaio.readthedocs.io/ | |
| - 💻 Source: https://github.com/crossbario/txaio/tree/v${{ steps.get_version.outputs.version }} | |
| See [CHANGELOG](https://github.com/crossbario/txaio/blob/master/docs/changelog.rst) for details. | |
| files: dist/* | |
| draft: false | |
| prerelease: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Remove non-PyPI files before upload | |
| run: | | |
| echo "======================================================================" | |
| echo "Removing files that PyPI doesn't accept" | |
| echo "======================================================================" | |
| rm -f dist/CHECKSUMS*.sha256 dist/*-docs.tar.gz | |
| echo "" | |
| echo "Files to upload to PyPI:" | |
| ls -lh dist/ | |
| echo "======================================================================" | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: dist/ | |
| verify-metadata: true | |
| skip-existing: false | |
| print-hash: true | |
| attestations: true | |
| - name: Trigger RTD build | |
| env: | |
| RTD_TOKEN: ${{ secrets.RTD_TOKEN }} | |
| run: | | |
| if [ -n "$RTD_TOKEN" ]; then | |
| echo "Triggering Read the Docs build for txaio..." | |
| curl -X POST \ | |
| -H "Authorization: Token $RTD_TOKEN" \ | |
| "https://readthedocs.org/api/v3/projects/txaio/versions/latest/builds/" | |
| else | |
| echo "RTD_TOKEN not configured, skipping RTD build trigger" | |
| fi |