diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5701273 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,160 @@ +name: release + +on: + push: + tags: + - "v*" + workflow_dispatch: + inputs: + version: + description: "Expected version (e.g. 0.9.2). Leave empty to only verify sdk/python == sdk/rust." + required: false + type: string + +permissions: + contents: read + +jobs: + version-consistency: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Determine expected version + id: expected + env: + INPUT_VERSION: ${{ github.event.inputs.version }} + run: | + set -euo pipefail + expected="" + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + expected="${GITHUB_REF_NAME#v}" + elif [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then + expected="${INPUT_VERSION:-}" + fi + echo "expected=${expected}" >> "$GITHUB_OUTPUT" + + - name: Check Python package version + id: python_version + run: | + set -euo pipefail + pyv="$(sed -n 's/^version *= *"\\(.*\\)".*/\\1/p' sdk/python/pyproject.toml | head -n1)" + if [[ -z "${pyv}" ]]; then + echo "::error::Could not parse version from sdk/python/pyproject.toml" + exit 1 + fi + echo "pyv=${pyv}" >> "$GITHUB_OUTPUT" + + - name: Check Rust crate version + id: rust_version + run: | + set -euo pipefail + rustv="$(sed -n 's/^version *= *"\\(.*\\)".*/\\1/p' sdk/rust/ogn-sdk/Cargo.toml | head -n1)" + if [[ -z "${rustv}" ]]; then + echo "::error::Could not parse version from sdk/rust/ogn-sdk/Cargo.toml" + exit 1 + fi + echo "rustv=${rustv}" >> "$GITHUB_OUTPUT" + + - name: Enforce versions + run: | + set -euo pipefail + expected="${{ steps.expected.outputs.expected }}" + pyv="${{ steps.python_version.outputs.pyv }}" + rustv="${{ steps.rust_version.outputs.rustv }}" + if [[ -n "${expected}" ]]; then + test "${pyv}" = "${expected}" || { echo "::error::sdk/python version (${pyv}) != expected (${expected})"; exit 1; } + test "${rustv}" = "${expected}" || { echo "::error::sdk/rust crate version (${rustv}) != expected (${expected})"; exit 1; } + else + test "${pyv}" = "${rustv}" || { echo "::error::sdk/python version (${pyv}) != sdk/rust crate version (${rustv})"; exit 1; } + fi + + python-build: + runs-on: ubuntu-latest + needs: version-consistency + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Build wheel + sdist + working-directory: sdk/python + run: | + set -euxo pipefail + python -m pip install --upgrade pip build twine + python -m build + twine check dist/* + + - uses: actions/upload-artifact@v4 + with: + name: pypi-dist + path: sdk/python/dist/* + + rust-package: + runs-on: ubuntu-latest + needs: version-consistency + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: dtolnay/rust-toolchain@stable + + - name: Cargo package + working-directory: sdk/rust/ogn-sdk + run: | + set -euxo pipefail + cargo package --no-verify + + publish-pypi: + runs-on: ubuntu-latest + needs: python-build + if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && secrets.PYPI_API_TOKEN != '' }} + permissions: + id-token: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Build wheel + sdist + working-directory: sdk/python + run: | + set -euxo pipefail + python -m pip install --upgrade pip build + python -m build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} + packages-dir: sdk/python/dist + + publish-crates: + runs-on: ubuntu-latest + needs: rust-package + if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && secrets.CRATES_IO_TOKEN != '' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: dtolnay/rust-toolchain@stable + + - name: Cargo publish ogn-sdk + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }} + working-directory: sdk/rust/ogn-sdk + run: | + set -euxo pipefail + cargo publish --no-verify