diff --git a/docs/guides/integration/github.md b/docs/guides/integration/github.md index ede82fb7f7a..ede16f6c3f2 100644 --- a/docs/guides/integration/github.md +++ b/docs/guides/integration/github.md @@ -24,10 +24,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 ``` It is considered best practice to pin to a specific uv version, e.g., with: @@ -41,10 +41,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: # Install a specific version of uv. version: "0.12.1" @@ -63,10 +63,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: Set up Python run: uv python install @@ -90,15 +90,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: "Set up Python" - uses: actions/setup-python@v6 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 ``` Or, specify the `pyproject.toml` file to ignore the pin and use the latest version compatible with @@ -113,15 +113,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: "Set up Python" - uses: actions/setup-python@v6 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version-file: "pyproject.toml" - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 ``` ## Multiple Python versions @@ -143,10 +143,10 @@ jobs: - "3.12" steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install uv and set the Python version - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: python-version: ${{ matrix.python-version }} ``` @@ -167,7 +167,7 @@ jobs: env: UV_PYTHON: ${{ matrix.python-version }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 ``` ## Syncing and running @@ -184,10 +184,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: Install the project run: uv sync --locked --all-extras --dev @@ -212,7 +212,7 @@ persisting the cache: ```yaml title="example.yml" - name: Enable caching - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true ``` @@ -230,7 +230,7 @@ jobs: # ... setup up Python and uv ... - name: Restore uv cache - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: /tmp/.uv-cache key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} @@ -348,12 +348,18 @@ steps: uv can be used to build and publish your package to PyPI from GitHub Actions. We provide a standalone example alongside this guide in [astral-sh/trusted-publishing-examples](https://github.com/astral-sh/trusted-publishing-examples). -The workflow uses [trusted publishing](https://docs.pypi.org/trusted-publishers/), so no credentials +The workflow uses [Trusted Publishing](https://docs.pypi.org/trusted-publishers/), so no credentials need to be configured. In the example workflow, we use a script to test that the source distribution and the wheel are both functional and we didn't miss any files. This step is recommended, but optional. +!!! important + + This example workflow uses two separate jobs (`build` and `publish`) so that the publishing + step (which has access to a publishing credential via `id-token: write`) does not share its + permissions with the building step. This reduces the surface for supply chain attacks. + First, add a release workflow to your project: ```yaml title=".github/workflows/release.yml" @@ -366,27 +372,53 @@ on: - v* jobs: - run: + build: runs-on: ubuntu-latest - environment: - name: pypi permissions: - id-token: write contents: read steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - - name: Install Python 3.13 - run: uv python install 3.13 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + - name: Build run: uv build - # Check that basic features work and we didn't miss to include crucial files + + # Optional, but recommended: run smoke tests on distributions - name: Smoke test (wheel) run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py - name: Smoke test (source distribution) run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py + + - name: Upload distributions as artifacts + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: dist + path: dist/ + + publish: + runs-on: ubuntu-latest + environment: + name: pypi + permissions: + id-token: write + steps: + - name: Install uv + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + + - name: Download distributions artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: dist + path: dist/ - name: Publish run: uv publish ``` @@ -396,7 +428,7 @@ Then, create the environment defined in the workflow in the GitHub repository un ![GitHub settings dialog showing how to add the "pypi" environment under "Settings" -> "Environments"](../../assets/github-add-environment.png) -Add a [trusted publisher](https://docs.pypi.org/trusted-publishers/adding-a-publisher/) to your PyPI +Add a [Trusted Publisher](https://docs.pypi.org/trusted-publishers/adding-a-publisher/) to your PyPI project in the project settings under "Publishing". Ensure that all fields match with your GitHub configuration.