Skip to content

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
mainfrom
jdl/chore/elixir-language-upgrade-2026-sept
Open

chore(deps): Upgrade Elixir to 1.20.4, and upgrade some deps whose old versions are now incompatible.#3486
joshlarson wants to merge 19 commits into
mainfrom
jdl/chore/elixir-language-upgrade-2026-sept

Conversation

@joshlarson

@joshlarson joshlarson commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

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 robot in 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:

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_units and ex_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_component section below.

Unnecessary pattern-matched clauses

I wanted to highlight this example because it's pretty cool!

The DotcomWeb.ScheduleController.TripInfo module defines a private current_trip function, which handles empty and non-empty journey lists like so:

  defp current_trip([%Journey{} | _] = times, now) do
    do_current_trip(times, now)
  end

  defp current_trip([], _now), do: nil

However, current_trip is only called in two places (one, and two), both of which explicitly have a pattern-match preventing journeys from being an empty list:

  defp trip_id(...)
       when journeys != [] do
    current_trip(journeys, ...)
  end

So Elixir's new type checker detected that journeys can never be [], and that the empty-list-handling clause of current_trip/2 was unnecessary.

Pretty neat!

live_isolated_component

The flip-side of this is that the new type-checking gets a bit too excited about macros. live_isolated_component itself is defined as a macro, like so:

defmacro live_isolated_component(component, opts) do
  do_live_isolated_component(
    component,
    quote(do: if(is_map(unquote(opts)), do: [assigns: unquote(opts)], else: unquote(opts)))
  )
end

In the tests where we use it, we invoke live_isolated_component like so:

live_isolated_component(SearchResultsLive, create_assigns())

And create_assigns() is known at compile-time to be a %{map}.

So we end up with the macro expanding to something like

  do_live_isolated_component(
    component,
    if(is_map(%{map}), do: [assigns: %{map}], else: %{map}))
  )

And of course %{map} is a map, so we get a warning.

Copilot suggested the hack of wrapping the create_assigns() call in Function.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 in Function.identity/1, as well as my proposed cleanup ((also actually implemented by Copilot)) of moving the Function.identity/1 call to the definition of create_assigns/0)

How to test

We should somewhat thoroughly test this out in a deployed environment to make sure that everything still works.

… (all `Conn`'s have a `query_params` field)
…` clause (all `Journey`'s have a a `departure` field)
…earlier in the test to be one of several atoms, none of which is `""`)
@joshlarson joshlarson added the dev-blue Deploy to dev-blue label Sep 9, 2026
@joshlarson
joshlarson marked this pull request as ready for review September 9, 2026 21:38
@joshlarson
joshlarson requested a review from a team as a code owner September 9, 2026 21:38
@joshlarson
joshlarson requested a review from lvachon1 September 9, 2026 21:38
@joshlarson
joshlarson force-pushed the jdl/chore/elixir-language-upgrade-2026-sept branch from 3da5e84 to ca292be Compare September 10, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev-blue Deploy to dev-blue dev-green Deploy to dev-green

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant