diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b819bd2..fc3c3104 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,8 @@ on: push: branches: - main + tags: + - 'v*' pull_request: schedule: # Nightly run; execute daily at 06:37 AM UTC on main (default branch). diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 00000000..a96f97fa --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,126 @@ +name: python + +on: + push: + branches: + - main + tags: + - 'v*' + pull_request: + workflow_dispatch: + inputs: + python_environment: + default: 'pypi' + description: 'The GitHub environment to use for publishing, as well as the name + of the Python package index to publish to. Value must match both the name of a + GitHub environment and the name of a [[tool.uv.index]] entry in + ts_python/pyproject.toml.' + required: true + type: choice + options: + - 'pypi' + - 'testpypi' + +permissions: + contents: read + +env: + # Cache-busting key -- change it if the build changes in a way that invalidates old + # cached state. + cache_key: python-ci + # Is this a tagged release build? + is_tag_push: ${{ startsWith(github.ref, 'refs/tags/') }} + # The GitHub environment to use for the "publish" job. Use the workflow_dispatch input + # if present, 'pypi' if this is a tagged release build; otherwise, fall back to + # 'testpypi'. + python_environment: &python_environment ${{ case(inputs.python_environment != '', inputs.python_environment, startsWith(github.ref, 'refs/tags/'), 'pypi', 'testpypi') }} + # The Python package index to publish to. Identical to "python_environment", separated + # for clarity. + python_index: *python_environment + # The Python ABI to build wheels for. Serves as a "minimum supported CPython version". + python_version: 3.12 + # The Rust toolchain version to build the wheels with. Should be latest supported + # version (MSRV + 1). + rust_toolchain: 1.94.0 + +jobs: + build_test: + name: test (${{ matrix.platform.os }}, ${{ matrix.platform.target }}) + runs-on: ${{ matrix.platform.runner }} + strategy: + matrix: + platform: + - os: linux + runner: linux-arm64-16cpu + target: aarch64 + - os: linux + runner: linux-x86_64-16cpu + target: x86_64 + - os: macOS + runner: macos-26 + target: aarch64 + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set up Rust cache + id: cache-cargo + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ~/.rustup/toolchains + target/ + key: ${{ matrix.platform.os }}-python-${{ env.cache_key }}-${{ env.rust_toolchain }}-${{ matrix.platform.target }}-${{ hashFiles('**/Cargo.lock') }} + - name: Install python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ env.python_version }} + - name: Build wheels + uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 + with: + working-directory: ts_python + rust-toolchain: ${{ env.rust_toolchain }} + target: ${{ matrix.platform.target }} + args: --release --out dist + sccache: ${{ !env.is_tag_push }} + manylinux: auto + - name: Upload wheels + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: wheels-${{ matrix.platform.os }}-${{ matrix.platform.target }} + path: ts_python/dist + + publish: + runs-on: ubuntu-latest + needs: build_test + environment: *python_environment + permissions: + # Use to sign the release artifacts + id-token: write + # Used to upload release artifacts + contents: write + # Used to generate artifact attestation + attestations: write + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Download built wheels + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: ts_python + - name: Generate artifact attestation + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 + with: + subject-path: 'ts_python/wheels-*/*' + - name: Install uv + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 + with: + working-directory: ts_python + - name: (Dry Run) Publish to ${{ env.python_index }} + run: uv publish --dry-run --directory ts_python --index ${{ env.python_index }} 'wheels-*/*' + - name: Publish to ${{ env.python_index }} + if: ${{ env.is_tag_push || github.event_name == 'workflow_dispatch' }} + run: uv publish --directory ts_python --index ${{ env.python_index }} 'wheels-*/*' diff --git a/ts_python/pyproject.toml b/ts_python/pyproject.toml index 9f84d24f..1fa01790 100644 --- a/ts_python/pyproject.toml +++ b/ts_python/pyproject.toml @@ -36,3 +36,15 @@ build-backend = "maturin" [tool.maturin] python-source = "python" module-name = "tailscale._internal" + +[[tool.uv.index]] +name = "pypi" +url = "https://pypi.org/simple/" +publish-url = "https://pypi.org/legacy/" +explicit = true + +[[tool.uv.index]] +name = "testpypi" +url = "https://test.pypi.org/simple/" +publish-url = "https://test.pypi.org/legacy/" +explicit = true \ No newline at end of file