Skip to content

Fetch organization packages with Workload Identity - #1266

Merged
ericmj merged 3 commits into
mainfrom
workload-identity-fetch
Oct 10, 2026
Merged

ericmj merged 3 commits into
mainfrom
workload-identity-fetch

Conversation

@ericmj

@ericmj ericmj commented Oct 9, 2026

Copy link
Copy Markdown
Member

In a GitHub Actions job with the id-token: write permission, fetching packages from an organization's repository now exchanges the job's OIDC token for a short-lived repository token when no organization key or authenticated user is configured. The exchange is in hex_core, hexpm/hex_core#238, vendored here at 6ded3af. The vendored copy needs updating once that's merged, since the squash changes the commit.

  • Tokens, and failed exchanges, are kept in Hex.State through the new hex_core callbacks, never in the Hex config.
  • Before the registry prefetch, the converger exchanges once per organization instead of asking "No authenticated user found. Do you want to authenticate now?", and prints "Authenticated to the acme organization with Workload Identity".
  • After a failed exchange a fetch runs without credentials, so .netrc credentials for a mirror still apply. A registry, policy or tarball fetch the repository refuses prints why the exchange failed and suggests mix hex.organization auth ORG --key KEY.
  • The CHANGELOG entry from Support Workload Identity in mix hex.publish #1253 and the mix hex.organization docs now cover fetching.

hexpm's Workload Identity docs say Mix and rebar3 don't request repository tokens (https://github.com/hexpm/hexpm/blob/a746876ae838334007a3f0a956745fe5bcaa8768/lib/hexpm_web/templates/docs/workload_identity.html.md?plain=1#L222), which needs updating when this is released.

ericmj added 3 commits October 9, 2026 21:58
In a GitHub Actions job with the id-token: write permission, fetching
packages from an organization's repository exchanges the job's OIDC
token for a short-lived repository token when no organization key or
authenticated user is configured. hex_core's repository auth resolution
does the exchange. Hex keeps the outcome, a token or why there is none,
in memory through the new callbacks, so it's never written to the Hex
config and a failed exchange isn't repeated for every package.

Before the registry prefetch, the converger exchanges once per
organization instead of asking to authenticate a user, and says when
the job authenticated with a workload identity. After a failed exchange
a fetch runs without credentials, so .netrc credentials for a mirror
still apply, and a fetch the repository refuses reports why the
exchange failed instead of printing a term or asking to run
mix hex.user auth.

Updates the vendored hex_core to 6ded3af.
Those versions reject a pinned variable on the left of <> in a match, so
the expected message is built before the assertion.
Name who exchanges the OIDC token instead of using the passive voice in
the mix hex.publish and mix hex.organization docs and the changelog
entry. The facts are unchanged.
@ericmj
ericmj marked this pull request as ready for review October 10, 2026 12:10
@ericmj
ericmj merged commit 4f5ade7 into main Oct 10, 2026
22 checks passed
@ericmj
ericmj deleted the workload-identity-fetch branch October 10, 2026 12:10
ericmj added a commit to hexpm/hexpm that referenced this pull request Oct 10, 2026
…d the Workload Identity docs (#2022)

* Reword the Workload Identity docs

Split sentences joined by semicolons, name who does what instead of
using the passive voice, use contractions, drop the bold lead-ins from
the empty-field list and replace phrasing like "publish-oriented",
"land the first release" and "put a gate in front of a publish" with
what it means. The facts are unchanged.

* Document that Mix fetches with organization workload identities

When Mix fetches packages from an organization's repository in a GitHub
Actions job with the id-token: write permission, and neither an
organization key nor an authenticated user is configured, it exchanges
the job's OIDC token for a repository token
(hexpm/hex#1266). Say so in the organization
section and remove the limitation saying it doesn't.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant