Repository navigation
Publish #8
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: Publish | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Release tag to publish, for example v0.1.0" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| jobs: | |
| release-tag: | |
| name: Resolve release tag | |
| runs-on: ubuntu-latest | |
| outputs: | |
| tag: ${{ steps.release-tag.outputs.tag }} | |
| version: ${{ steps.release-tag.outputs.version }} | |
| steps: | |
| - name: Resolve release tag | |
| id: release-tag | |
| run: | | |
| tag="${{ inputs.tag }}" | |
| if [[ ! "$tag" =~ ^v0\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Refusing to publish tag '$tag'. Expected exact v0.MINOR.PATCH semver." | |
| exit 1 | |
| fi | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "version=${tag#v}" >> "$GITHUB_OUTPUT" | |
| release-metadata: | |
| name: Validate release metadata | |
| needs: release-tag | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ needs.release-tag.outputs.tag }} | |
| - name: Match package versions to release tag | |
| env: | |
| RELEASE_VERSION: ${{ needs.release-tag.outputs.version }} | |
| run: | | |
| python - <<'PY' | |
| import os | |
| import tomllib | |
| from pathlib import Path | |
| expected = os.environ["RELEASE_VERSION"] | |
| with Path("pyproject.toml").open("rb") as file: | |
| root = tomllib.load(file)["project"] | |
| cli_dependency = next( | |
| item for item in root["dependencies"] if item.startswith("sqlclean-cli==") | |
| ).partition("==")[2] | |
| with Path("packages/sqlclean-cli/pyproject.toml").open("rb") as file: | |
| cli_package_version = tomllib.load(file)["project"]["version"] | |
| with Path("Cargo.toml").open("rb") as file: | |
| workspace_version = tomllib.load(file)["workspace"]["package"]["version"] | |
| manifests = [ | |
| ("root project", root["version"]), | |
| ("root CLI dependency", cli_dependency), | |
| ("CLI package", cli_package_version), | |
| ("Cargo workspace", workspace_version), | |
| ] | |
| mismatches = [f"{label}={version}" for label, version in manifests if version != expected] | |
| if mismatches: | |
| raise SystemExit( | |
| f"Release tag version {expected} does not match: {', '.join(mismatches)}" | |
| ) | |
| PY | |
| wheels: | |
| name: Build wheel (${{ matrix.platform.name }}) | |
| needs: [release-tag, release-metadata] | |
| runs-on: ${{ matrix.platform.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: | |
| - name: linux-x86_64 | |
| runner: ubuntu-latest | |
| target: x86_64 | |
| - name: linux-aarch64 | |
| runner: ubuntu-24.04-arm | |
| target: aarch64 | |
| - name: macos-x86_64 | |
| runner: macos-latest | |
| target: x86_64 | |
| - name: macos-arm64 | |
| runner: macos-latest | |
| target: aarch64 | |
| - name: windows-x86_64 | |
| runner: windows-latest | |
| target: x86_64 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ needs.release-tag.outputs.tag }} | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: 1.95.0 | |
| # sqlclean-cli ships one standalone Rust executable and links no libpython, | |
| # so maturin tags it py3-none-<platform>. The tag is asserted before release. | |
| - name: Build native CLI wheel | |
| uses: PyO3/maturin-action@v1 | |
| with: | |
| command: build | |
| args: --release --out ../../dist | |
| target: ${{ matrix.platform.target }} | |
| manylinux: auto | |
| working-directory: packages/sqlclean-cli | |
| - name: Assert native CLI wheel is interpreter-agnostic | |
| shell: bash | |
| run: bash .github/scripts/assert_cli_wheel_tags.sh dist | |
| - uses: actions/upload-artifact@v5 | |
| with: | |
| name: wheel-${{ matrix.platform.name }} | |
| path: dist | |
| sdist: | |
| name: Build sdists and Python wheel | |
| needs: [release-tag, release-metadata] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ needs.release-tag.outputs.tag }} | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: 1.95.0 | |
| - uses: astral-sh/setup-uv@v6 | |
| with: | |
| version: "0.12.9" | |
| # The sqlclean package is pure Python, so one wheel serves every platform. | |
| - name: Build Python package sdist and wheel | |
| run: uv build --sdist --wheel --out-dir dist | |
| - name: Build native CLI sdist | |
| uses: PyO3/maturin-action@v1 | |
| with: | |
| command: sdist | |
| args: --out ../../dist | |
| working-directory: packages/sqlclean-cli | |
| - uses: actions/upload-artifact@v5 | |
| with: | |
| name: sdist | |
| path: dist | |
| pypi: | |
| name: Publish to PyPI | |
| needs: | |
| - release-tag | |
| - wheels | |
| - sdist | |
| runs-on: ubuntu-latest | |
| environment: pypi | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ needs.release-tag.outputs.tag }} | |
| - uses: actions/download-artifact@v5 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - name: Assert native CLI wheels are interpreter-agnostic | |
| shell: bash | |
| run: bash .github/scripts/assert_cli_wheel_tags.sh dist | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: dist | |
| skip-existing: true |