From 45c9567c2c4262a0c4a9677034dea375f181a9cd Mon Sep 17 00:00:00 2001 From: yangxk1 Date: Tue, 9 Jun 2026 21:57:13 +0800 Subject: [PATCH] fix(CI): replace pypa/gh-action-pypi-publish with inline twine upload The pypa/gh-action-pypi-publish action is blocked by Apache org's action allowlist policy. Replace it with inline shell steps that use PyPI's trusted publisher OIDC flow directly: mint a short-lived API token via the OIDC endpoint and upload with twine. The id-token: write permission is preserved so GitHub Actions still injects the OIDC credentials needed for the trusted publisher exchange. --- .github/workflows/python-wheel-workflow.yml | 61 ++++++++++++++++++--- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/.github/workflows/python-wheel-workflow.yml b/.github/workflows/python-wheel-workflow.yml index ad44f9c53..48b6ff862 100644 --- a/.github/workflows/python-wheel-workflow.yml +++ b/.github/workflows/python-wheel-workflow.yml @@ -273,11 +273,35 @@ jobs: run: | mkdir -p python/dist find dist -name "*" -type f -exec mv {} python/dist/ \; - - name: Publish to Test PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + - name: Set up Python + uses: actions/setup-python@v5 with: - repository-url: https://test.pypi.org/legacy/ - packages-dir: python/dist/ + python-version: "3.x" + + - name: Publish to Test PyPI + run: | + set -euo pipefail + pip install twine + + # Mint a short-lived API token via PyPI Trusted Publisher (OIDC) + OIDC_TOKEN=$(curl -sS \ + -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=testpypi" \ + | python3 -c "import sys, json; print(json.load(sys.stdin)['value'])") + + PYPI_TOKEN=$(curl -sS -X POST \ + https://test.pypi.org/_/oidc/mint-token \ + -H "Content-Type: application/json" \ + -d "{\"token\": \"${OIDC_TOKEN}\"}" \ + | python3 -c "import sys, json; print(json.load(sys.stdin)['token'])") + echo "::add-mask::${PYPI_TOKEN}" + + twine upload \ + --repository-url https://test.pypi.org/legacy/ \ + --username __token__ \ + --password "${PYPI_TOKEN}" \ + --skip-existing \ + python/dist/* upload_pypi: name: Publish (manual) @@ -297,7 +321,30 @@ jobs: run: | mkdir -p python/dist find dist -name "*" -type f -exec mv {} python/dist/ \; - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/2473ec6c6aa87f38946284d51289219fd0b87264 + - name: Set up Python + uses: actions/setup-python@v5 with: - packages-dir: python/dist/ \ No newline at end of file + python-version: "3.x" + + - name: Publish to PyPI + run: | + set -euo pipefail + pip install twine + + # Mint a short-lived API token via PyPI Trusted Publisher (OIDC) + OIDC_TOKEN=$(curl -sS \ + -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=pypi" \ + | python3 -c "import sys, json; print(json.load(sys.stdin)['value'])") + + PYPI_TOKEN=$(curl -sS -X POST \ + https://pypi.org/_/oidc/mint-token \ + -H "Content-Type: application/json" \ + -d "{\"token\": \"${OIDC_TOKEN}\"}" \ + | python3 -c "import sys, json; print(json.load(sys.stdin)['token'])") + echo "::add-mask::${PYPI_TOKEN}" + + twine upload \ + --username __token__ \ + --password "${PYPI_TOKEN}" \ + python/dist/*