ericmj

ericmj

Elixir Core Team

Release: Release v2.6.0 · hexpm/hex · GitHub

Announcement: Hex v2.6 released | Hex

Backwards incompatible changes

  • Require --key in mix hex.organization auth ORGANIZATION. For development authenticate with mix hex.user auth, which gives access to all your organizations. For CI generate an organization key with mix hex.organization key ORGANIZATION generate and pass it with --key
  • Exchange the key given to mix hex.organization auth ORGANIZATION --key KEY for a short-lived token and store only the token. Hex uses the token for about 25 minutes and doesn’t refresh it, so in CI run the command right before fetching dependencies
  • Stop authenticating to organization repositories with keys that earlier Hex versions stored in ~/.hex/hex.config. Authenticate again with mix hex.user auth or mix hex.organization auth ORGANIZATION --key KEY. mix hex.repo add and mix hex.repo set refuse --auth-key for an organization repository
  • Stop authenticating to organization repositories with HEX_REPOS_KEY or a key set with mix hex.repo set hexpm --auth-key. Use mix hex.organization auth ORGANIZATION --key KEY instead. HEX_REPOS_KEY still authenticates to the hexpm repository and to mirrors set with HEX_TRUSTED_MIRROR
  • Fetch packages from organization repositories on hex.pm from the hexpm repository’s URL, https://repo.hex.pm by default, when a mirror is set with HEX_MIRROR, and through the mirror when it’s set with HEX_TRUSTED_MIRROR. Before, where they were fetched from depended on whether the organization was in ~/.hex/hex.config when the command started
  • Require OTP 24 or later. Hex 2.4.2 to 2.5.4 can’t unpack packages on OTP 22, so Hex 2.4.1 is the last release that works there. Hex 2.5.4 is the last release for OTP 23
  • Exclude files created by operating systems, editors and version control, such as .DS_Store, .git, *~, *.orig and *.bak, at any depth from packages built by mix hex.build and mix hex.publish, unless a :files entry names them without wildcards. Only .DS_Store was excluded before. The build and deps directories, the package tarball, the unpack directory and --output are always excluded, so files: ["*"] no longer packages an earlier build. A :files entry without wildcards only matches a file whose name has the same case on disk, including on case-insensitive file systems
  • Fail mix hex.build and mix hex.publish when a directory they read for the package’s files contains a file name that isn’t valid UTF-8, including when that file wouldn’t be packaged
  • Stop reading ~/.hex/hex.config files in the Elixir format that Hex versions before 0.5.0 wrote. When the file can’t be read, Hex fails with an error that says to remove it and run mix hex.user auth

Enhancements

  • Support Workload Identity, also known as Trusted Publishing, so a GitHub Actions job with the id-token: write permission can publish packages and fetch an organization’s packages without storing a key. When no HEX_API_KEY or other Hex credential is configured, mix hex.publish exchanges the job’s OIDC token for a short-lived token that can only publish the package. When there’s no token from mix hex.organization auth ORGANIZATION --key KEY and no mix hex.user auth session, fetching an organization’s packages exchanges the OIDC token for a short-lived token that can fetch them. Configure the workload identity on hex.pm first. For a public package, configure it on the package or on an organization that owns the package. For a package in an organization’s repository, configure it on the organization. An organization’s workload identity with the read role can fetch its packages, and one with the write role can also publish and create packages in its repository and publish the public packages it owns. Requires OTP 27 or later. Workload identities are in beta on hex.pm, and only packages and organizations in the beta can configure them
  • Add the workload_identity_audience config, overridden by HEX_WORKLOAD_IDENTITY_AUDIENCE. It sets the audience of the OIDC token that Workload Identity requests, hexpm by default. Hex doesn’t request a token when the API advertises a different audience, so an api_url other than hex.pm can’t obtain a token that other services trusting the job would accept
  • Build identical packages from identical project files in mix hex.build and mix hex.publish. The package no longer depends on whether it’s built on macOS or Linux, the file system, the order of files on disk, the umask, the Elixir and OTP versions or VM flags such as +fnl, so a package can be rebuilt from its source and its checksum compared. The build_env field of the package metadata records the Hex version that built the package, which is the version needed to rebuild it
  • Add the :executables package option to list the files that are executable in the package, for file systems that don’t store execute permissions, such as on Windows. Without it a file is executable when its owner execute permission is set on disk
  • Add the :secret_scan package option to suppress hex.pm’s leaked credential findings for files that deliberately contain secret-like values, such as secret_scan: [ignore: ["test/fixtures/**"]]. Earlier Hex versions leave the option out of the package
  • Ask once before fetching when an organization that the project’s dependencies come from requires two-factor authentication or SSO and the mix hex.user auth session doesn’t meet the requirement. mix deps.get and mix deps.update name the organizations and what they require, and on confirmation open hex.pm in the browser to complete it and continue with the organization’s packages. Declining continues without them. hex.pm doesn’t offer organization SSO yet
  • Add --policy and --policy-overrides options to mix hex.audit to audit locked dependencies against the active dependency policy. --policy applies the policy’s advisory severity threshold, retirement reasons and overrides, and fails only for findings the policy rejects. --policy-overrides only applies the policy’s overrides. Neither checks the cooldown. Findings the policy accepts are listed in their own sections and don’t fail the audit. Locked packages matched by a DENY override are listed under “Denied:” and fail the audit, and ignore_advisories and ignore_retirements don’t apply to them
  • Don’t warn in mix deps.get and mix deps.update about advisories and retirements of releases that an override in the active policy accepts
  • Support policy overrides that accept a specific advisory, retirement reason or the cooldown for a package in dependency resolution, while the policy’s other checks still apply. Overrides can have a comment. Advisory and retirement overrides also apply to mix hex.audit --policy and --policy-overrides, which print an override’s comment next to the finding it accepts. mix hex.policy show lists overrides with their comments. Overrides with an action this Hex version doesn’t know are ignored with a warning. Create them in the policy editor on hex.pm
  • Add the policy_enforce_lock config. When it’s enabled and a policy is active, mix deps.get and mix deps.update fail if a Hex package in mix.lock is rejected by the policy, using the same check as mix hex.audit --policy. Findings acknowledged with ignore_advisories or ignore_retirements pass, and a package matched by a DENY override fails until the policy changes. Configure it in the mix.exs :hex block, with the HEX_POLICY_ENFORCE_LOCK environment variable, or with mix hex.config
  • End the errors caused by the active dependency policy with how to run without it (HEX_POLICY= mix deps.get). This covers an invalid policy configuration, a policy that can’t be fetched or loaded, a resolution failure where the policy hid versions, and the policy_enforce_lock check, which also names HEX_POLICY_ENFORCE_LOCK to skip only that check
  • Add --format sarif and --output PATH options to mix hex.audit to render the audit result as a SARIF v2.1.0 document that can be uploaded to GitHub code scanning and other SARIF consumers. Each finding points at the dependency’s mix.lock entry, including when a package is locked from two repositories, and packages denied by the policy are reported under the HEX0006 rule. Findings acknowledged with ignore_advisories or ignore_retirements are left out, and so are findings the active policy accepts when run with --policy or --policy-overrides, so GitHub code scanning closes their alerts as fixed. Requires OTP 27 or later
  • Print warnings to standard error instead of standard output, so machine-readable output such as mix hex.outdated --json isn’t mixed with them. Warning-colored lines that are part of a command’s regular output, such as retirement notices in mix hex.info and the mix deps.get dependency listing, remain on standard output
  • Link packages from organization repositories to their own diffs on hex.pm in mix hex.outdated. Earlier versions linked them as public packages, which showed a public package with the same name or failed. Packages from other repositories are no longer linked
  • Stop listing unchanged dependencies after mix deps.get and mix deps.update resolve dependencies. Unchanged dependencies that are retired or have security advisories are still listed under “Unchanged:”
  • Fail with an error that names the package and where the requirement comes from when a requirement in mix.exs or mix.lock can never be satisfied, such as ~> 1.0 and >= 2.0.0. When a package release in the registry has such a requirement, warn and resolve with another release of the package
  • Speed up mix deps.get and mix deps.update and lower their memory use when fetching large packages. http_concurrency now limits how many packages are downloaded at a time, and registry files are fetched with four times that limit, 32 by default
  • Speed up resolving dependencies in mix deps.get and mix deps.update, especially in projects with many dependencies and when the registry hasn’t changed. The registry cache is now cache.bin in the Hex cache directory. The first run reads the cache.ets of earlier Hex versions and leaves it in place for them

Bug fixes

  • Refresh the mix hex.user auth session and retry the request when hex.pm rejects its access token, for example after it was revoked. When hex.pm rejects a short-lived Workload Identity token, exchange the OIDC token again. When it rejects a token from mix hex.organization auth ORGANIZATION --key KEY, use the session or Workload Identity instead. When the session can’t be refreshed, use a session that another command stored in the meantime before asking to authenticate again. Hex didn’t recognize hex.pm’s response to a rejected token, so requests failed until the token expired
  • Don’t send the hex.pm session from mix hex.user auth to repositories added with mix hex.repo add. Since Hex 2.5.0 Hex sent it to them, and requests to a repository that authenticates with ~/.netrc credentials failed with 401 because the credentials were no longer sent
  • Warn in mix hex.user deauth when the hex.pm session couldn’t be revoked
  • Keep the current session when mix hex.user auth is denied, times out or is interrupted. The stored credentials were removed before the new authentication started
  • Write ~/.hex/hex.config, which holds API keys and OAuth tokens, readable only by the current user, and restrict the ~/.hex directory to the current user. The file was written with the default permissions, which on most systems let other local users read it
  • Upload docs once in mix hex.publish when hex.pm asks for a two-factor authentication code. The docs were uploaded, and their upload progress printed, both before and after the code was entered
  • Only look up the authenticated user’s organizations in mix hex.publish when the owner prompt can be shown, that is when publishing a new public package without --yes. Publishing with a key that can’t read the user, such as a workload identity token, no longer prints an error
  • Resolve dependencies with requirements that chain more than two conditions with and, use two bounds in the same direction or == inside and, or combine two pessimistic ranges, such as >= 1.0.0 and >= 1.2.0 or ~> 1.0.0 and ~> 1.0. They crashed with FunctionClauseError or were rejected, though hex.pm accepts them
  • Stop writing any to mix.lock as the requirement of a dependency whose requirement allows every version, such as >= 0.0.0-0. mix deps.get failed to read it with Version.InvalidRequirementError
  • Only say (using cache instead) when a package or policy fails to fetch from the registry and a cached copy exists. Without a cached copy the message claimed a fallback that didn’t happen
  • Reject mix hex.publish --revert VERSION --dry-run instead of reverting the release. --dry-run was ignored by --revert, so the package or docs were deleted from the repository
  • Keep the existing dependency in deps when its new version fails to unpack or doesn’t match the checksums in the registry
  • Reuse cached registry and policy files in mix deps.get and mix deps.update when they haven’t changed in the repository. Since Hex 2.1.0 every registry file was downloaded in full on each run, even when it was already cached
  • Skip HTTPS certificate verification when the unsafe_https config or the HEX_UNSAFE_HTTPS environment variable is set. Since Hex 2.3.0 the setting had no effect and certificates were always verified
  • Print the package version in the error raised when resolved Hex packages give the same dependency different OTP application names. Since Hex 0.21.3 the error showed a literal {version} instead
  • Resolve dependencies after compiling in the same command, such as mix do compile + deps.get, on Elixir 1.15 and later. Since Hex 2.4.1 this raised UndefinedFunctionError for Hex.Stdlib.ensure_application!/1
  • Fail mix hex.audit when the registry entry for a locked package version can’t be fetched, and with --policy or --policy-overrides when the active policy can’t be fetched. Without a cached copy of the entry the audit reported “No retired or security advisory packages found” and exited with 0 without checking the package. With a cached copy it audited against the cache, which can miss advisories and policy changes made since. Set HEX_OFFLINE=1 to audit against the cache. mix deps.get and mix deps.update still use the cache when a fetch fails

Deprecations

  • Warn when the key given to mix hex.organization auth ORGANIZATION --key KEY is owned by a user account instead of the organization. hex.pm stops accepting user keys with repository permissions on 21 January 2027, whatever Hex version you run. Use mix hex.user auth for development and an organization key from mix hex.organization key ORGANIZATION generate for CI

Showing Posts 1 to 2

ChaseGilliam

ChaseGilliam

This is fantastic, congrats @ericmj!

arcanemachine

arcanemachine

The Hex team has been doing some great work lately! :folded_hands:

— All posts loaded —

Where Next? Top

Trending in News Top

josevalim
Hi everyone, I am sharing this announcement here in case some of you might be interested. Dear colleagues, IRIF (Paris) is opening a p...
New
ericmj
Release: Release v2.6.0 · hexpm/hex · GitHub Announcement: Hex v2.6 released | Hex Backwards incompatible changes Require --key in mix...
New

Other Trending Topics Top

mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews