From 7c90a07ec5632ddbf71b7ee680cd1f35124a8a1a Mon Sep 17 00:00:00 2001 From: Abdel Fane Date: Thu, 14 May 2026 18:43:32 -0600 Subject: [PATCH] ci: switch npm and PyPI publishes to Trusted Publishing (OIDC) The npm workflow was already requesting `--provenance` with `id-token: write` AND a long-lived `NODE_AUTH_TOKEN`. The Python workflow set `id-token: write` AND `password: PYPI_API_TOKEN`. The PyPI side has been silently emitting attestations: ignored on every run since 0a31816 (2026-02-07): The workflow was run with the 'attestations: true' input, but an explicit password was also set, disabling Trusted Publishing. As a result, the attestations input is ignored. Both registries now exclusively use OIDC Trusted Publishing: publish-npm.yml - Bump runner Node to 24 (TP requires modern npm). - Drop `NODE_AUTH_TOKEN: secrets.NPM_TOKEN`. `id-token: write` plus `registry-url: https://registry.npmjs.org` is sufficient for setup-node@v4 + npm 11+ to handle the OIDC handshake. publish.yml - Drop `password: secrets.PYPI_API_TOKEN` from all four publish jobs (cryptoserve-core, cryptoserve-client, cryptoserve-auto, cryptoserve). `id-token: write` plus `environment: pypi` is what pypa/gh-action-pypi-publish needs to enable attestations. - Harden the GitHub Release step so re-runs against an existing tag (which was the actual cause of the v1.4.3 publish-job failure) update assets via `gh release upload --clobber` instead of crashing the whole job. Pre-merge checklist (admin actions, then merge): 1. npmjs.com -> cryptoserve -> Settings -> Publishing access -> Trusted Publisher: org=ecolibria, repo=cryptoserve, workflow=publish-npm.yml, environment blank. 2. For each of cryptoserve, cryptoserve-core, cryptoserve-client, cryptoserve-auto on pypi.org -> Settings -> Publishing -> add Trusted Publisher: owner=ecolibria, repo=cryptoserve, workflow=publish.yml, environment=pypi. 3. After steps 1 + 2 are confirmed: merge this PR. Then delete NPM_TOKEN and PYPI_API_TOKEN from repo secrets. 4. Verify on the next release with `npm view cryptoserve dist.attestations --json` and `curl https://pypi.org/pypi/cryptoserve//json | jq '.urls[].has_sig'`. This PR keeps the workflow on `js-v*` and `v*` tag triggers; tag hygiene and the manual-publish hole that produced npm cryptoserve 0.3.4 without provenance are out of scope here. --- .github/workflows/publish-npm.yml | 4 +--- .github/workflows/publish.yml | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index e8de7d8..7c0afcd 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -36,10 +36,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' registry-url: 'https://registry.npmjs.org' - name: Publish working-directory: sdk/javascript run: npm publish --provenance --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2391247..59dde86 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -133,7 +133,6 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 with: - password: ${{ secrets.PYPI_API_TOKEN }} skip_existing: true publish-client: @@ -153,7 +152,6 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 with: - password: ${{ secrets.PYPI_API_TOKEN }} skip_existing: true publish-auto: @@ -173,7 +171,6 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 with: - password: ${{ secrets.PYPI_API_TOKEN }} skip_existing: true publish-main: @@ -193,7 +190,6 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 with: - password: ${{ secrets.PYPI_API_TOKEN }} skip_existing: true provenance: @@ -218,16 +214,23 @@ jobs: done > ../SHA256SUMS.txt cat ../SHA256SUMS.txt - - name: Create GitHub Release + - name: Create or update GitHub Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | TAG=${GITHUB_REF#refs/tags/} - gh release create "$TAG" \ - --title "CryptoServe SDK $TAG" \ - --generate-notes \ - SHA256SUMS.txt \ - all-dist/dist-cryptoserve-core/*.whl \ - all-dist/dist-cryptoserve-client/*.whl \ - all-dist/dist-cryptoserve-auto/*.whl \ + ASSETS=( + SHA256SUMS.txt + all-dist/dist-cryptoserve-core/*.whl + all-dist/dist-cryptoserve-client/*.whl + all-dist/dist-cryptoserve-auto/*.whl all-dist/dist-cryptoserve/*.whl + ) + if gh release view "$TAG" >/dev/null 2>&1; then + gh release upload "$TAG" "${ASSETS[@]}" --clobber + else + gh release create "$TAG" \ + --title "CryptoServe SDK $TAG" \ + --generate-notes \ + "${ASSETS[@]}" + fi