diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml index 7cd32ad..e9041f3 100644 --- a/.github/workflows/_release.yml +++ b/.github/workflows/_release.yml @@ -61,6 +61,9 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + # OIDC: mint a short-lived token for PyPI Trusted Publishing — no + # long-lived TEST_PYPI_TOKEN secret to leak, expire, or rotate. + id-token: write environment: name: testpypi url: https://test.pypi.org/project/${{ needs.build.outputs.pkg-name }}/ @@ -72,22 +75,18 @@ jobs: name: dist path: dist/ - # actions/setup-python@v6.2.0 - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 - with: - python-version: "3.x" - + # pypa/gh-action-pypi-publish@v1.14.0 — Trusted Publishing (OIDC). + # Requires a "pending/trusted publisher" registered on test.pypi.org: + # repo=oracle-samples/locus, workflow=_release.yml, environment=testpypi + # continue-on-error so a TestPyPI hiccup never blocks the prod publish; + # skip-existing tolerates re-runs over an already-uploaded version. - name: Publish to TestPyPI - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} - # continue-on-error so a missing/invalid TestPyPI token does not - # block the main PyPI publish; TestPyPI is best-effort smoke-test. continue-on-error: true - run: | - pip install twine - twine upload -r testpypi dist/* --verbose + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b + with: + repository-url: https://test.pypi.org/legacy/ + packages-dir: dist/ + skip-existing: true pre-release-checks: needs: