chore(deps): Upgrade Elixir to 1.20.4, and upgrade some deps whose old versions are now incompatible. - #3486
Open
joshlarson wants to merge 19 commits into
Open
chore(deps): Upgrade Elixir to 1.20.4, and upgrade some deps whose old versions are now incompatible.#3486joshlarson wants to merge 19 commits into
joshlarson wants to merge 19 commits into
Conversation
…hose older versions don't compile
… (all `Conn`'s have a `query_params` field)
…` clause (all `Journey`'s have a a `departure` field)
…_ids_for_destination/2` clauses
…` is apparently already built-in)
…earlier in the test to be one of several atoms, none of which is `""`)
…step a type-check
joshlarson
force-pushed
the
jdl/chore/elixir-language-upgrade-2026-sept
branch
from
September 10, 2026 14:15
3da5e84 to
ca292be
Compare
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.
Scope
Asana Ticket: 🛠️ (2026/09) Upgrade Elixir and Erlang
Implementation
Note
🤖 While I did the original Elixir upgrade by hand, I used Copilot to clean up most of the resulting compile-time warnings. As usual, commits with
robotin the prefix (e.g.fix(warnings/robot)) were AI-generated. The others were human-generated.Elixir version 1.20 introduced some nifty new type checking and warnings, some of which we ran afoul of, generating warnings that I wanted to get cleaned up before issuing this PR. Those new type checks were:
requireslive_isolated_componentbelow.Commits 2-10 of this PR address ☝️ warnings within our codebase that I (well, Copilot) was actually able to clean up.
Commit 11 upgrades
ex_cldr_unitsandex_cldr_numbers, because those two libraries are run at compile-time, and the old versions had type issues that Elixir 1.20 warned about.Commits 12 and 13, well... see
live_isolated_componentsection below.Unnecessary pattern-matched clauses
I wanted to highlight this example because it's pretty cool!
The
DotcomWeb.ScheduleController.TripInfomodule defines a privatecurrent_tripfunction, which handles empty and non-empty journey lists like so:However,
current_tripis only called in two places (one, and two), both of which explicitly have a pattern-match preventingjourneysfrom being an empty list:So Elixir's new type checker detected that
journeyscan never be[], and that the empty-list-handling clause ofcurrent_trip/2was unnecessary.Pretty neat!
live_isolated_componentThe flip-side of this is that the new type-checking gets a bit too excited about macros.
live_isolated_componentitself is defined as a macro, like so:In the tests where we use it, we invoke
live_isolated_componentlike so:And
create_assigns()is known at compile-time to be a%{map}.So we end up with the macro expanding to something like
And of course
%{map}is a map, so we get a warning.Copilot suggested the hack of wrapping the
create_assigns()call inFunction.identity/1, so that Elixir would forget what its type was.(Arguably less important: The reason there are two commits was because I wanted to show the AI's first attempt, which was to wrap each
create_assigns()call inFunction.identity/1, as well as my proposed cleanup ((also actually implemented by Copilot)) of moving theFunction.identity/1call to the definition ofcreate_assigns/0)How to test
We should somewhat thoroughly test this out in a deployed environment to make sure that everything still works.