From 27b12c8a66051f26ce8aef57bd4d8736c2093e82 Mon Sep 17 00:00:00 2001 From: yuriyryabikov <22548029+kurok@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:27:51 +0100 Subject: [PATCH] ci(publish): use PYPI_USERNAME/PYPI_PASSWORD secrets instead of OIDC Fall back to token/password auth for the PyPI upload so a release can be cut without configuring a Trusted Publisher. Requires PYPI_PASSWORD to be a valid API token (PyPI no longer accepts plain passwords). Re-migrating to OIDC Trusted Publishing is preferred long-term. Signed-off-by: yuriyryabikov <22548029+kurok@users.noreply.github.com> --- .github/workflows/publish.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f4e1f1e..f1aa812 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -171,14 +171,18 @@ jobs: uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 with: subject-path: "dist/*" - # Publish via PyPI Trusted Publishing (OIDC) — no long-lived token needed. - # Requires a one-time setup on PyPI: add a Trusted Publisher for - # namecheap/fast_mail_parser, workflow "publish.yml" (no environment). - # See the PR description for the exact steps. After this is live the old - # PYPI_USERNAME / PYPI_PASSWORD secrets can be deleted. + # Publish using the legacy PYPI_USERNAME / PYPI_PASSWORD secrets (token or + # username/password) rather than OIDC Trusted Publishing. NOTE: PyPI no + # longer accepts plain username/password — this only succeeds if + # PYPI_USERNAME is "__token__" and PYPI_PASSWORD is a valid API token. + # Preferred long-term: re-enable OIDC Trusted Publishing (drop these + # secrets) by configuring a Trusted Publisher for namecheap/fast_mail_parser + # + publish.yml on PyPI. - name: Publish to PyPI if: ${{ github.event_name == 'release' && startsWith(github.ref, 'refs/tags/') }} uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: packages-dir: dist skip-existing: true + user: ${{ secrets.PYPI_USERNAME }} + password: ${{ secrets.PYPI_PASSWORD }}