From 43678792e18198fd5a2a1f9e6bf4f47e60a67a35 Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Sun, 18 Oct 2026 23:44:54 +0200 Subject: [PATCH 1/2] start new dev branch; add audit file --- .audit/oberstet_fix_1958.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .audit/oberstet_fix_1958.md diff --git a/.audit/oberstet_fix_1958.md b/.audit/oberstet_fix_1958.md new file mode 100644 index 000000000..5502c88b4 --- /dev/null +++ b/.audit/oberstet_fix_1958.md @@ -0,0 +1,8 @@ +- [ ] I did **not** use any AI-assistance tools to help create this pull request. +- [x] I **did** use AI-assistance tools to *help* create this pull request. +- [x] I have read, understood and followed the project's AI_POLICY.md when creating code, documentation etc. for this pull request. + +Submitted by: @oberstet +Date: 2026-10-18 +Related issue(s): #1958 +Branch: oberstet:fix_1958 From 97e2ebc982ab02e2aaa1ad1f0e11b5b5a61578aa Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Sun, 18 Oct 2026 23:47:14 +0200 Subject: [PATCH 2/2] Publish to PyPI via Trusted Publishing (OIDC) with PEP 740 attestations (#1958) The release-stable job uploaded with twine and secrets.PYPI_API_TOKEN. The account-wide PyPI tokens were deleted on 2026-09-29, so the v26.10.1 upload failed with "403 Invalid or non-existent authentication information" on the first file (nothing reached PyPI). Replace the twine step with pypa/gh-action-pypi-publish@release/v1, the same step zlmdb uses (packages-dir dist/, verify-metadata, print-hash, attestations). The job already has environment pypi and id-token: write, the Trusted Publisher is registered on PyPI (crossbario/autobahn-python, release.yml, environment pypi), and check-release-fileset already strips dist/ to *.whl + *.tar.gz. The twine/packaging installs from git master in the publish job are gone with it. Expected CI: green. PR CI does not run release-stable; the change is exercised by the v26.10.1 release run after landing (release.yml runs from master via workflow_run). Note: This work was completed with AI assistance (Claude Code). --- .github/workflows/release.yml | 31 +++++++++++++------------------ docs/changelog.rst | 1 + 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a7a33f8b4..da019caa6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2733,25 +2733,20 @@ jobs: echo "======================================================================" fi - - name: Publish to PyPI using bleeding-edge twine + - name: Publish to PyPI (OIDC trusted publishing) if: steps.pypi_check.outputs.exists == 'false' - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - echo "==> Publishing to PyPI using twine from master..." - # Install bleeding-edge packaging and twine for PEP 639 support - # Use --break-system-packages for consistency (safe in CI) - python3 -m pip install --break-system-packages git+https://github.com/pypa/packaging.git - python3 -m pip install --break-system-packages git+https://github.com/pypa/twine.git - - echo "Upload environment:" - echo "twine: $(twine --version)" - echo "packaging: $(python3 -m pip show packaging | grep '^Version:')" - echo "" - - # Upload to PyPI - twine upload dist/*.whl dist/*.tar.gz --verbose + uses: pypa/gh-action-pypi-publish@release/v1 + with: + # Tokenless OIDC trusted publishing (no PYPI_API_TOKEN); also generates + # and uploads PEP 740 attestations. By this point the "Validate and + # clean release fileset for PyPI" step (keep-metadata: false) has + # stripped dist/ down to only .whl + .tar.gz, so the whole dir is + # publishable. Matches zlmdb / crossbar / cfxdb / wamp-xbr / txaio. See #1958. + packages-dir: dist/ + verify-metadata: true + skip-existing: false + print-hash: true + attestations: true - name: Trigger RTD build env: diff --git a/docs/changelog.rst b/docs/changelog.rst index 83f21fa40..7891e4b19 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -36,6 +36,7 @@ Changelog * Remove dead code reported by ``ty`` (an unused ``_unique_list`` helper in both ``component.py`` modules, and an unreachable response-body block in the WebSocket server opening handshake) instead of adding it to the ignore list (#1938) * Adopt the WAMP fleet's shared developer workflow recipes from wamp-cicd (``just where``, ``what``, ``new-branch``, ``land``, ...); the release upload recipe ``publish`` is renamed ``publish-release`` (#1943) * Apply the fleet's shared ``python-package`` and ``way-a`` aspects (repository files kept in sync from wamp-cicd, with generated ``aspects.toml``), and bump ``.cicd`` accordingly (#1960, #1972, #1975, #1977, #1979, #1981) +* Publish to PyPI through Trusted Publishing (OIDC) with ``pypa/gh-action-pypi-publish``, as the other WAMP Python packages do, instead of ``twine upload`` with a ``PYPI_API_TOKEN`` secret. Every file on PyPI now carries a PEP 740 publish attestation (provenance), starting with 26.10.1 (#1958) * Add an ``import-smoke-lowest`` CI job (``just test-imports-lowest``) that runs the import smoke test on CPython 3.11 with every direct dependency resolved to the lowest version ``pyproject.toml`` allows (``uv --resolution lowest-direct``), so stale version floors are caught. The import smoke test now also covers the Twisted and asyncio bindings, each module imported in a fresh interpreter (#1955) **asyncio**