Skip to content

Add a blend dependency-version test matrix and CI dependency audits - #48

Merged
petermueller merged 7 commits into
mainfrom
pkm/blend-dep-matrix
Jul 27, 2026
Merged

Add a blend dependency-version test matrix and CI dependency audits#48
petermueller merged 7 commits into
mainfrom
pkm/blend-dep-matrix

Conversation

@petermueller

@petermueller petermueller commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds blend (~> 0.5) so the suite can run against the dependency versions mix.exs claims to support, not just the frozen main lock: BLEND=<name> mix test.unit (or any mix task).

Blend Pins Covers
oldest waffle 1.1.0, goth 1.1.0, gcs 0.34.0, mime 1.2.0 every declared floor; real bucket/0 fallback (waffle < 1.1.7 has no bucket/1)
goth_1_2 goth 1.2.0 pre-1.3 goth; the only config that compiles GothTokenFetcher
waffle_1_1_10 waffle 1.1.10 newest waffle (lock: 1.1.8)
gcs_0_46 google_api_storage 0.46.1 newest storage client (lock: 0.37.0)
mime_2 mime ~> 2.0 the or ~> 2.0 half of the mime requirement

Old-goth blends are unit-only: test_helper excludes :integration (the harness needs the Goth >= 1.3 API) and the two :goth_config_swap signing tests (goth < 1.3 freezes boot config). Those exclusion blocks, the config/dev.exs + config/test.exs placeholder-identity blocks, and the test-support fetcher gate all carry delete-me comments keyed to the future goth bump — removing a blend is deleting its entry, mix blend.get, done.

Config is split into the conventional per-env files (import_config "#{config_env()}.exs") so no test/dev shim can reach a release build.

Dependencies

CI

  • Unit job: Elixir/OTP matrix from 1.15 through 1.20, each on the newest OTP that version supports, plus one entry per blend on the newest pair. Blend runs need no blend package in CI — the committed premix.exs and a BLEND env var is enough — and cache blend/<name>/deps keyed on the blend's own lockfile.
  • New secret-free audit job: mix audit plus a blend drift check (mix blend.get must be a no-op against the committed lockfiles).
  • Integration job and the formatting check move to the newest pair.

Testing

  • 6 configs (5 blends + main lock) x with/without creds: mix test.unit green
  • Full integration suite against real GCS: green on the main lock and the three network-capable blends
  • mix audit, mix format --check-formatted, and the drift check green on Elixir 1.20.2 / OTP 29

blend (~> 0.5) generates per-blend lockfiles under blend/ so the suite can
run against the dependency versions mix.exs claims to support, not just the
frozen main lock: BLEND=<name> mix test.unit (or any mix task).

Blends (see blend.exs): oldest (every direct dep at its declared floor,
including waffle 1.1.0 which predates the bucket/1 callback), goth_1_2 (last
pre-1.3 goth; the only config that compiles GothTokenFetcher), waffle_1_1_10,
gcs_0_46, and mime_2 (resolvable because google_gax 0.4.0 has no mime dep).

Supporting changes:
- config/ split into the conventional per-env files; dev.exs and test.exs
  give credential-less runs a placeholder goth identity, because goth < 1.3
  parses :json eagerly at app boot (before test_helper can run) and crashes
  on an unset GCP_CREDENTIALS.
- test_helper excludes :integration and the new :goth_config_swap tag on
  old-goth runs (goth < 1.3 freezes boot config, so the signing tests'
  identity swap is impossible; integration needs the >= 1.3 API). Both
  exclusion blocks are commented for deletion at the goth version bump.
- The test-support GothTokenFetcher is gated on goth >= 1.3, since
  Goth.fetch!/1 doesn't exist below it.
- tesla becomes a direct dependency pinned to 1.18.2: newer tesla is
  incompatible with google_gax's compiled-in middleware stack. The pin
  raises the Elixir floor to ~> 1.15 and moves the hackney, finch, mint and
  hpax subtrees forward in the lock.
- mix_audit is added and a mix audit alias runs the hex.audit and deps.audit
  dependency checks, honoring the ignore list in mix.exs.

All five blends plus the default lock pass mix test.unit with and without
credentials; the full integration suite passes on the default lock and the
three network-capable blends.
The unit job gains an Elixir/OTP matrix from 1.15 (the floor in mix.exs)
through 1.20, each paired with the newest OTP that version supports, plus
one entry per blend on the newest pair — language compat is the version
entries' job, dependency compat is the blends'. Blend runs need no blend
package in CI: the committed premix.exs plus a BLEND env var is enough.
They cache blend/<name>/deps keyed on the blend's own lockfile, and the
cache keys drop the '**/mix.lock' glob so blend lock changes stop busting
main-lock caches.

New secret-free audit job runs mix audit (the hex.audit and deps.audit
checks) and a blend drift check: mix blend.get must be a no-op against the
committed lockfiles, so dependency changes that invalidate a blend fail
loudly instead of silently testing a stale resolution.

The integration job and the formatting check move to the newest pair.
@petermueller
petermueller force-pushed the pkm/blend-dep-matrix branch from dca6e83 to 71d62f2 Compare July 26, 2026 03:25
@petermueller petermueller changed the title Blend dependency-version test matrix, tesla 1.18.2 peg (CVE-2026-48594), and dependency audits in CI Add a blend dependency-version test matrix and CI dependency audits Jul 26, 2026
…t blend

waffle <= 1.1.9's generated delete/1 trips Elixir 1.20's type-checker
warnings, which fail the unit job's --warnings-as-errors compile (the
blend jobs that resolved waffle 1.1.10 already passed). Bump the main
lock to waffle 1.1.10, and move the oldest blend — which pins waffle
1.1.0 deliberately — to the 1.15/OTP 26 floor pair, where no type
warnings exist and which is the pairing floor-dep consumers actually
run.
The tesla 1.18.2 exact pin forced by google_gax is transitive poison —
it blocks consumers' own tesla usage from taking 1.18.3+ security
fixes, and the archived upstream makes it permanent. Split the rewrite:
phase 1 (Req transport, feature parity, library-owned types) gates 0.3;
phase 2 (resumable, signBlob, v4, dual-target suite) targets 0.4.
Transport default is Req, aligned with waffle core's direction (the
Waffle.HTTPClient behaviour on master and the Req adapter in waffle
PR #156).
A library's config files are never evaluated by consumers (see the
Config module docs), so shipping config/config.exs was dead weight —
and since the per-env split it references files that weren't in the
tarball anyway. Verified with mix hex.build.
Common Changelog says to exclude maintenance changes that aren't
interesting to consumers of the distributed package: the blend matrix,
mix audit, the Mix.Config->Config switch, and the test-suite overhaul
all fall under that. Dependency changes consumers can observe (tesla
pin, mime, google_api_storage, jose, the Elixir floor) stay.
Identical findings on this lockfile (the same 5 tesla + 4 hackney
advisories from both tools), and hex.audit additionally checks
retirements and honors ignore_advisories natively. The audit alias
becomes just hex.audit.
@petermueller
petermueller merged commit e00b5bf into main Jul 27, 2026
13 checks passed
@petermueller
petermueller deleted the pkm/blend-dep-matrix branch July 27, 2026 01:42
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