Repository navigation
chore: upgrade to Elixir 1.19.5 / OTP 28.5.0.5 across CI, Docker, and local env - #34
Merged
Merged
Conversation
… local env Versions had drifted apart across the three surfaces: .tool-versions ran OTP 28.0.2, CI ran OTP 27, and the production Dockerfile ran OTP 27.3.4.9. Align all of them on Elixir 1.19.5 / OTP 28.5.0.5. Elixir 1.19 officially supports OTP 28.1+. Running 1.19.5 on the previously pinned 28.0.2 emits "Regexes will be re-compiled from source at runtime, which will cause degraded performance" because of the new OTP 28 regex representation, so the .tool-versions bump off 28.0.2 is required rather than cosmetic. Alpine moves 3.21.6 -> 3.23.5. Alpine 3.21 reaches EOL in Nov 2026; 3.23 is supported to Nov 2027. The image stays Alpine-based. CI pins OTP as "28.5" rather than a bare "28" so the Dialyzer PLT cache key, which is derived from setup-beam's resolved otp-version output, stays stable across runner image updates. No application code changes were needed. Checked against the 1.19 hard deprecations: no struct-update syntax without a preceding pattern match, no regexes as defstruct defaults, no comma-separated `mix do`, no :preferred_cli_env/:preferred_cli_target in mix.exs, no Logger :backends config, and the sole File.cp call is the 2-arity form. mix.lock is unchanged -- no dependency needed updating for 1.19. Verified locally on Elixir 1.19.5 / OTP 28.5.0.5: mix compile --warnings-as-errors --all-warnings 0 app-code warnings mix format --check-formatted pass mix credo --strict no issues mix sobelow --config pass mix dialyzer pass mix test 1159 tests, 0 failures The docker build was not verified locally -- this machine's Docker daemon cannot currently reach the registry. CI's docker-build job covers it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Aligns CI, the Docker builds, and the local toolchain on Elixir 1.19.5 / Erlang-OTP 28.5.0.5. The production image stays Alpine-based.
Why
The three surfaces had drifted apart:
.tool-versions.github/workflows/ci.yml"27""28.5"Dockerfile(prod)Dockerfile.develixir:1.18-otp-28-alpineelixir:1.19.5-otp-28-alpinedev-build.ymlneeds no change — it builds throughDockerfileand inherits the bump.docker-compose.*.ymlonly pin postgres/caddy/minio.Version choices
OTP 28.5.0.5 — newest patch of the 28 line. OTP has no formal LTS, so newest-patch-of-the-line is the stable choice.
The bump off 28.0.2 is required, not cosmetic: Elixir 1.19 officially supports OTP 28.1+, and running 1.19.5 on 28.0.2 emits
because of the new OTP 28 regex representation. Gone on 28.5.0.5.
Alpine 3.23.5 — Alpine has no LTS either; each release gets ~2 years. The current 3.21 pin reaches EOL Nov 2026, so this moves to 3.23 (supported to ~Nov 2027) rather than taking 3.21.7 or jumping to the newest 3.24.1.
CI pins OTP as
"28.5", not a bare"28". The Dialyzer PLT cache key is derived fromsetup-beam's resolvedotp-versionoutput, so a loose pin silently invalidates the PLT cache whenever the runner image's resolution changes.Breaking-change review
Checked the Elixir 1.19 hard deprecations against this codebase — no application code changes were needed:
%URI{uri | path: ...}) now requires the variable to pattern-match on the struct first — no occurrences inlib/ortest/.defstructfield defaults (new OTP 28 regex representation) — no~rin anydefstruct.mix do foo, bar— not used.:preferred_cli_env/:preferred_cli_targetindef project— not present.:backendsconfig — not present.on_undefined_variable: :warn,Kernel.ParallelCompilerreturn_diagnostics,mix compile.protocols— not used.File.cp/3callback form — the only call site (lib/kith/storage/local.ex:18) is the 2-arity form.mix.lockis unchanged — no dependency needed updating for 1.19.Verification
Run locally on Elixir 1.19.5 / OTP 28.5.0.5:
mix compile --warnings-as-errors --all-warningstesla, one registry module)mix format --check-formattedmix credo --strictmix sobelow --configmainmix dialyzer.dialyzer_ignore.exsskipsmix testdocker buildAnd on CI (run) — all checks green:
testdialyzerdocker-buildkith:ci versionruns, container UID is 1000The Docker build could not be run on the authoring machine: its Docker daemon cannot currently reach the registry (even a 13 KB
hello-worldpull times out, while hostcurltoauth.docker.ioreturns 200 in 0.27s). That is a local Docker Desktop networking fault, not a Dockerfile problem — CI'sdocker-buildjob builds the image cleanly and passes both of its runtime assertions.Out of scope
mix hex.auditreports 4 advisories againstplug 1.19.1, one HIGH (CVE-2026-54892, quadratic-time nested param decoding). These are pre-existing onmainand unrelated to this bump —mix.lockis untouched here. Worth a separate PR.