From b10a462223bedf71242104677984ba9dec5b8777 Mon Sep 17 00:00:00 2001 From: doronz88 Date: Fri, 7 Aug 2026 20:43:07 +0300 Subject: [PATCH] bugfix: Publish to PyPI via Trusted Publishing The v0.3.0 release built fine but `twine upload` was rejected with `403 Forbidden`: the workflow authenticates with the `PYPI_USERNAME` / `PYPI_PASSWORD` secrets stored in 2024, and those credentials no longer work. Switch to Trusted Publishing, so GitHub mints a short-lived OIDC credential for this workflow and there is no long-lived secret to expire or leak. Requires registering the publisher once on PyPI (Manage project -> Publishing) with owner `doronz88`, repository `DeveloperDiskImage`, workflow `python-publish.yml` and no environment. Also add a `workflow_dispatch` trigger taking a tag, so a release whose publish run failed can be retried without cutting a new version, and fetch the full history since setuptools_scm derives the version from tags. --- .github/workflows/python-publish.yml | 39 +++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 1d7c1f6..a11c13c 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -1,31 +1,46 @@ -# This workflows will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries +# Uploads a Python package to PyPI when a release is created. +# +# Authentication uses PyPI Trusted Publishing (OpenID Connect) rather than a stored API token: +# GitHub mints a short-lived credential for this workflow, so there is no long-lived secret to +# leak or to silently expire. The trusted publisher must be registered once on PyPI, under +# Manage project -> Publishing, matching owner/repository/workflow below. +# https://docs.pypi.org/trusted-publishers/ name: Upload Python Package on: release: types: [created] + # Allows re-publishing a tag whose release-triggered run failed, without cutting a new version. + workflow_dispatch: + inputs: + ref: + description: 'Tag to build and publish (e.g. v0.3.0)' + required: true jobs: deploy: runs-on: ubuntu-latest + permissions: + # Required for Trusted Publishing; the job needs no repository secrets at all. + id-token: write + steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + # setuptools_scm derives the version from tags, so the full history must be present. + fetch-depth: 0 + ref: ${{ inputs.ref || github.ref }} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - - name: Install dependencies + - name: Build run: | python -m pip install --upgrade pip - pip install -U build setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | + pip install -U build python -m build - twine upload dist/* \ No newline at end of file + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1