diff --git a/README.md b/README.md index bd6f5a4..5ee06cb 100644 --- a/README.md +++ b/README.md @@ -62,20 +62,25 @@ The secret used in `${{ secrets.PYPI_API_TOKEN }}` needs to be created on the settings page of your project on GitHub. See [Creating & using secrets]. -### Publishing with OpenID Connect +### Trusted publishing > **IMPORTANT**: This functionality is in beta, and will not work for you -> unless you're a member of the PyPI OIDC beta testers' group. For more -> information, see [warehouse#12965]. +> unless you're a member of the PyPI trusted publishing beta testers' group. +> For more information, see [warehouse#12965]. -This action supports PyPI's [OpenID Connect publishing] +> **NOTE**: Trusted publishing is sometimes referred to by its +> underlying technology -- OpenID Connect, or OIDC for short. +> If you see references to "OIDC publishing" in the context of PyPI, +> this is what they're referring to. + +This action supports PyPI's [trusted publishing] implementation, which allows authentication to PyPI without a manually configured API token or username/password combination. To perform -[OIDC publishing][OpenID Connect Publishing] with this action, your project's -OIDC publisher must already be configured on PyPI. +[trusted publishing] with this action, your project's +publisher must already be configured on PyPI. -To enter the OIDC flow, configure this action's job with the `id-token: write` -permission and **without** an explicit username or password: +To enter the trusted publishing flow, configure this action's job with the +`id-token: write` permission and **without** an explicit username or password: ```yaml jobs: @@ -83,7 +88,7 @@ jobs: name: Upload release to PyPI runs-on: ubuntu-latest permissions: - id-token: write # IMPORTANT: this permission is mandatory for OIDC publishing + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: # retrieve your distributions here @@ -91,7 +96,7 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 ``` -Other indices that support OIDC publishing can also be used, like TestPyPI: +Other indices that support trusted publishing can also be used, like TestPyPI: ```yaml - name: Publish package distributions to TestPyPI @@ -268,4 +273,4 @@ https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direc https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md [warehouse#12965]: https://github.com/pypi/warehouse/issues/12965 -[OpenID Connect Publishing]: https://pypi.org/help/#openid-connect +[trusted publishing]: https://docs.pypi.org/trusted-publishers/ diff --git a/oidc-exchange.py b/oidc-exchange.py index 52bee14..07579d0 100644 --- a/oidc-exchange.py +++ b/oidc-exchange.py @@ -13,7 +13,7 @@ _GITHUB_STEP_SUMMARY = Path(os.getenv("GITHUB_STEP_SUMMARY")) # The top-level error message that gets rendered. # This message wraps one of the other templates/messages defined below. _ERROR_SUMMARY_MESSAGE = """ -Trusted publisher (OIDC) exchange failure: +Trusted publishing exchange failure: {message} @@ -24,11 +24,14 @@ publishing, then you should double-check your secret configuration and variable names. Read more about trusted publishers at https://docs.pypi.org/trusted-publishers/ + +Read more about how this action uses trusted publishers at +https://github.com/marketplace/actions/pypi-publish#trusted-publishing """ # Rendered if OIDC identity token retrieval fails for any reason. _TOKEN_RETRIEVAL_FAILED_MESSAGE = """ -OIDC token retrieval failed: {identity_error} +OpenID Connect token retrieval failed: {identity_error} This generally indicates a workflow configuration error, such as insufficient permissions. Make sure that your workflow has `id-token: write` configured @@ -71,7 +74,7 @@ def die(msg: str) -> NoReturn: with _GITHUB_STEP_SUMMARY.open("a", encoding="utf-8") as io: print(_ERROR_SUMMARY_MESSAGE.format(message=msg), file=io) - print(f"::error::OIDC exchange failure: {msg}", file=sys.stderr) + print(f"::error::Trusted publishing exchange failure: {msg}", file=sys.stderr) sys.exit(1) @@ -94,12 +97,14 @@ def assert_successful_audience_call(resp: requests.Response, domain: str): case HTTPStatus.FORBIDDEN: # This index supports OIDC, but forbids the client from using # it (either because it's disabled, limited to a beta group, etc.) - die(f"audience retrieval failed: repository at {domain} has OIDC disabled") + die( + f"audience retrieval failed: repository at {domain} has trusted publishing disabled", + ) case HTTPStatus.NOT_FOUND: # This index does not support OIDC. die( "audience retrieval failed: repository at " - f"{domain} does not indicate OIDC support", + f"{domain} does not indicate trusted publishing support", ) case other: status = HTTPStatus(other) @@ -124,7 +129,7 @@ assert_successful_audience_call(audience_resp, repository_domain) oidc_audience = audience_resp.json()["audience"] -debug(f"selected OIDC token exchange endpoint: {token_exchange_url}") +debug(f"selected trusted publishing exchange endpoint: {token_exchange_url}") try: oidc_token = id.detect_credential(audience=oidc_audience) diff --git a/twine-upload.sh b/twine-upload.sh index f38d429..bf48246 100755 --- a/twine-upload.sh +++ b/twine-upload.sh @@ -44,7 +44,7 @@ if [[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] ; then # No password supplied by the user implies that we're in the OIDC flow; # retrieve the OIDC credential and exchange it for a PyPI API token. echo \ - '::notice::Attempting to perform OIDC credential exchange' \ + '::notice::Attempting to perform trusted publishing exchange' \ 'to retrieve a temporary short-lived API token for authentication' \ "against ${INPUT_REPOSITORY_URL} due to __token__ username with no" \ 'supplied password field'