Skip to content

Fix red master: keep the tests' Bundler runs out of OCRAN's own lockfile - #55

Merged
Largo merged 4 commits into
masterfrom
fix/windows-bundle-pollution
Aug 10, 2026
Merged

Fix red master: keep the tests' Bundler runs out of OCRAN's own lockfile#55
Largo merged 4 commits into
masterfrom
fix/windows-bundle-pollution

Conversation

@Largo

@Largo Largo commented Aug 10, 2026

Copy link
Copy Markdown
Owner

master is red on Windows only, in the step Build zlib fixture for portability test:

You have deleted from the Gemfile:
* mylocal
... the lockfile can't be updated because frozen mode is set

Root cause

bundle exec exports BUNDLE_LOCKFILE holding the absolute path of the lockfile it used. The test suite runs under bundle exec rake test, so every child process it spawns inherits BUNDLE_LOCKFILE=<repo>/Gemfile.lock.

bundle_exec_env (added in #54) runs bundle exec ruby -e ... with BUNDLE_GEMFILE pointed at a fixture Gemfile — for test_bundle_exec_own_bundle_is_not_warned_about, test/fixtures/localgem/Gemfile, copied to a tmpdir. Bundler believes BUNDLE_LOCKFILE over the Gemfile it was handed, so it resolved the fixture and wrote the result — PATH remote: mylocal and nothing else — into OCRAN's own Gemfile.lock, not the fixture's.

Every platform did this. Only Windows noticed: its post-test zlib step runs bundle exec ruby ..., and ruby/setup-ruby has put deployment: true in .bundle/config, so Bundler refuses the rewritten lockfile. Linux and macOS run that step under plain ruby and stayed green while carrying the same damage.

(The repo-local deployment: true never applied to the offending call itself: with BUNDLE_GEMFILE in a tmpdir, .bundle/config is out of Bundler's root, so nothing stopped the write.)

Fix

  • bundle_exec_env clears BUNDLE_LOCKFILE, which puts the lockfile back where Bundler would put it unaided — next to the Gemfile, i.e. inside the temporary copy that is deleted with the rest of the fixture. The tests still run real Bundler against real fixture Gemfiles; nothing is weakened.
  • Every such Bundler run is followed by an assertion that OCRAN's lockfile still has its pre-run content, so the next variant of this names itself instead of surfacing three steps later.
  • CI fails right after the test step if the run modified a tracked file (vendor/ and .bundle/ excluded — both are checked in but rewritten by bundle install and setup-ruby before any test runs).
  • branches: ['*'] never matched fix/... or feat/...: a single star stops at a slash. Every branch here was merged untested, which is how the last two merges reached master red. Now '**', plus workflow_dispatch.

Verification

Windows on this branch, run https://github.com/Largo/ocran/actions/runs/31359567122run-tests-windows 3.3 / 3.4 / 4.0 and all three test-windows-portability jobs green. Linux and macOS jobs were still waiting for runners at the time of writing; locally, bundle exec rake test leaves the tree clean and shows only this box's known failures.

🤖 Generated with Claude Code

Largo and others added 4 commits August 10, 2026 00:27
`bundle exec` exports BUNDLE_LOCKFILE with the absolute path of the
lockfile it used, and the suite itself runs under `bundle exec rake
test`, so every child it spawns inherits OCRAN's own Gemfile.lock by
name. Bundler believes that variable over the Gemfile it is handed:
bundle_exec_env, resolving a fixture Gemfile to find out what `bundle
exec` sets, wrote the fixture's dependencies into OCRAN's lockfile
instead of the fixture's own.

Nothing in the test run noticed. What noticed was the next step in the
same CI job that ran `bundle exec` - on Windows, the zlib portability
build - which died in frozen mode over a lockfile that had `mylocal` in
it and none of OCRAN's development gems. Linux and macOS run that step
under plain `ruby` and so stayed green while carrying the same damaged
lockfile.

Clearing BUNDLE_LOCKFILE puts the lockfile back where Bundler would put
it on its own, next to the Gemfile - for a fixture, the temporary
directory it was copied into, which is removed with the rest of it.
The lockfile is compared against its pre-run content after every such
Bundler run, so the next variant of this names itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A test that lets Bundler write into the working tree leaves the suite
green and breaks a later step with an error that names neither the test
nor the fact that a test was responsible - the Windows jobs reported a
frozen-mode Bundler failure in a build step minutes after the run that
caused it.

Checking the tree right after the tests puts the failure where the cause
is. Tracked files only: bundle install populates vendor/bundle, and the
builds leave stubs and packed executables behind.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`branches: ['*']` does not match `fix/...` or `feat/...`: a single star
stops at a slash. Every branch this project uses was therefore merged
untested, and master was the first place the tests ever ran on it - the
last two merges both turned it red.

workflow_dispatch as well, so a run can be asked for without a push.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
vendor/ and .bundle/config are under version control here, and CI writes
to both before a test runs: ruby/setup-ruby sets `deployment: true` in
the config, and `bundle install` rewrites the vendored gems, whose
shebangs and line endings differ per platform. On Windows that is some
four thousand modified files, none of them anything a test did.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Largo
Largo merged commit d18d926 into master Aug 10, 2026
7 of 17 checks passed
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