update test matrix to include newer major and minor versions#1166
update test matrix to include newer major and minor versions#1166Ch4s3 wants to merge 5 commits into
Conversation
|
@Ch4s3 Looks like there is a failing test even after retrying. Can you investigate? |
I sure can. This is the exact sort of thing I thought running against the latest versions might uncover. |
|
Interesting, this is a fixture issue. The data is wrong and new versions of mix now catch it. I'll have a fix later. |
ecto_3_3_2/mix.exs declared version "3.3.1" instead of "3.3.2", causing Mix 1.20 to raise a nomatchvsn error when updating ecto_sql (which pulls in ecto ~> 3.3.2). Also fix the copy-paste module name in ecto_sql_3_3_3.
Elixir 1.20 removed the `recently_fetched?` guard from
Mix.Dep.Loader.validate_app. Previously, when a dep was just fetched,
validate_app would short-circuit to :compile status instead of reading
the (potentially stale) .app file from the build directory.
Without that guard, when a dep like ecto is updated from 3.3.1 → 3.3.2
during `deps.update ecto_sql`, Mix reads the old compiled ecto.app
(version 3.3.1) and marks ecto as {:ok, "3.3.1"}. When ecto_sql 3.3.3
then requires ecto ~> 3.3.2, req_mismatch triggers :divergedreq — a
false positive since ecto is already being updated to 3.3.2.
Fix: delete the stale .app file from the build directory in
Hex.SCM.update/1 after extracting the new tarball. This causes
validate_app to see {:noappfile, ...} (not {:ok, "3.3.1"}), so
req_mismatch is not triggered.
The existing ":divergedreq" integration test only fails on Elixir >= 1.20 (older versions mask the bug via Mix.Dep.Loader's recently_fetched? guard), so it cannot guard the fix when the suite runs on 1.19 and earlier. This test asserts the concrete behavior of the fix directly: after a transitive dependency is updated (ecto 3.3.1 -> 3.3.2), its stale compiled .app file must be gone. It fails without the SCM fix on every Elixir version and passes with it. Verified: - 1.19.5 without fix: existing test passes (masked), this test fails - 1.19.5 with fix: both pass - 1.20.0-rc.5 without fix: both fail - 1.20.0-rc.5 with fix: both pass
| if build = opts[:build] do | ||
| Path.join([build, "ebin", "#{name}.app"]) |> File.rm() | ||
| end |
There was a problem hiding this comment.
@ericmj you probably understand mix way better than I do. Can you think of an approach that doesn't require a call to File.rm/0?
There was a problem hiding this comment.
This looks like an Elixir bug to me. Opened a PR with a proposed fix here: elixir-lang/elixir#15406
There was a problem hiding this comment.
That's even better. I can point this to the next rc, main, or the eventual 1.20 when that's ready.
Covers the full chain seen in hexpm/hex#1166: a fetchable dep's stale .app is read by `validate_app`, produces an `{:ok, vsn}` that matches the top-level requirement, then a transitive parent with a stricter requirement causes the converger's `req_mismatch` to mark the dep as `:divergedreq` — even though the only thing actually wrong is that `_build` hasn't been recompiled yet. With the loader bypass, `validate_app` returns `:compile` for a fetchable dep whose SCM manifest's stored lock differs from `opts[:lock]`, so the dep never enters the converger with `{:ok, _}` and `req_mismatch` doesn't fire. The previous test exercised the loader short-circuit in isolation; this one exercises the same path through the full converge step and asserts `Mix.Dep.diverged?/1` returns false.
I'm not sure if it's desirable to test against the latest RC of elixir like this, but I've seen other ecosystems do something like this and in any case it might be good to move the main versions up to the latest Elixir 1.19 and OTP28.5.