From 321cd44f13444d2809eadee94a025a965f27a671 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Tue, 31 Oct 2023 21:36:26 -0400 Subject: [PATCH] Use separate jobs for building and publishing test releases. (#12671) This follows the principle of least privilege. Our `poetry build` step doesn't need, and shouldn't get, access to our GitHub OIDC capability. This is the same structure as I used in the already-merged PR for refactoring the regular PyPI release workflow: #12578. --- .github/workflows/_release.yml | 2 +- .github/workflows/_test_release.yml | 81 ++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml index 88144dbeaa2..237b998ee3a 100644 --- a/.github/workflows/_release.yml +++ b/.github/workflows/_release.yml @@ -58,7 +58,7 @@ jobs: shell: bash working-directory: ${{ inputs.working-directory }} run: | - echo pkg-name="$(poetry version | cut -d' ' -f 1)" >> $GITHUB_OUTPUT + echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT echo version="$(poetry version --short)" >> $GITHUB_OUTPUT test-pypi-publish: diff --git a/.github/workflows/_test_release.yml b/.github/workflows/_test_release.yml index febe929b618..0fc25a75164 100644 --- a/.github/workflows/_test_release.yml +++ b/.github/workflows/_test_release.yml @@ -10,9 +10,60 @@ on: env: POETRY_VERSION: "1.6.1" + PYTHON_VERSION: "3.10" jobs: - publish_to_test_pypi: + build: + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + + outputs: + pkg-name: ${{ steps.check-version.outputs.pkg-name }} + version: ${{ steps.check-version.outputs.version }} + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ env.PYTHON_VERSION }} + poetry-version: ${{ env.POETRY_VERSION }} + working-directory: ${{ inputs.working-directory }} + cache-key: release + + # We want to keep this build stage *separate* from the release stage, + # so that there's no sharing of permissions between them. + # The release stage has trusted publishing and GitHub repo contents write access, + # and we want to keep the scope of that access limited just to the release job. + # Otherwise, a malicious `build` step (e.g. via a compromised dependency) + # could get access to our GitHub or PyPI credentials. + # + # Per the trusted publishing GitHub Action: + # > It is strongly advised to separate jobs for building [...] + # > from the publish job. + # https://github.com/pypa/gh-action-pypi-publish#non-goals + - name: Build project for distribution + run: poetry build + working-directory: ${{ inputs.working-directory }} + + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: test-dist + path: ${{ inputs.working-directory }}/dist/ + + - name: Check Version + id: check-version + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT + echo version="$(poetry version --short)" >> $GITHUB_OUTPUT + + publish: + needs: + - build runs-on: ubuntu-latest permissions: # This permission is used for trusted publishing: @@ -21,30 +72,24 @@ jobs: # Trusted publishing has to also be configured on PyPI for each package: # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ id-token: write - defaults: - run: - working-directory: ${{ inputs.working-directory }} + steps: - uses: actions/checkout@v4 - - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} - uses: "./.github/actions/poetry_setup" + - uses: actions/download-artifact@v3 with: - python-version: "3.10" - poetry-version: ${{ env.POETRY_VERSION }} - working-directory: ${{ inputs.working-directory }} - cache-key: release + name: test-dist + path: ${{ inputs.working-directory }}/dist/ - - name: Build project for distribution - run: poetry build - - name: Check Version - id: check-version - run: | - echo version=$(poetry version --short) >> $GITHUB_OUTPUT - - name: Publish package to TestPyPI + - name: Publish to test PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - repository-url: https://test.pypi.org/legacy/ packages-dir: ${{ inputs.working-directory }}/dist/ verbose: true print-hash: true + repository-url: https://test.pypi.org/legacy/ + + # We overwrite any existing distributions with the same name and version. + # This is *only for CI use* and is *extremely dangerous* otherwise! + # https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates + skip-existing: true