@invarn/cibuild 2.8.7 → 2.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -55,6 +55,9 @@ const run = async (opts) => {
55
55
  if (opts.lock !== undefined)
56
56
  writeFileSync(join(project, 'Gemfile.lock'), opts.lock);
57
57
  writeFileSync(join(project, 'Gemfile'), opts.gemfile ?? "gem 'cocoapods'\n");
58
+ if (opts.rubyVersionFile !== undefined) {
59
+ writeFileSync(join(project, '.ruby-version'), opts.rubyVersionFile);
60
+ }
58
61
  const installed = (opts.installed ?? []).join(' ');
59
62
  executable(join(bin, 'gem'), `echo "gem $*" >> '${log}'
60
63
  if [ "$1" = "list" ]; then
@@ -67,11 +70,24 @@ fi`);
67
70
  executable(join(bin, 'bundle'), `echo "bundle $* (GEM_HOME=$GEM_HOME)" >> '${log}'`);
68
71
  executable(join(bin, 'pod'), `echo "pod $*" >> '${log}'`);
69
72
  executable(join(bin, 'ruby'), `echo "ruby $*" >> '${log}'; printf '2.6.10'`);
70
- if (opts.brewRuby) {
73
+ if (opts.brewRuby || opts.ruby33) {
74
+ const brewVersion = opts.brewRubyVersion ?? '3.4.1';
71
75
  const keg = join(root, 'homebrew-ruby');
72
- mkdirSync(join(keg, 'bin'), { recursive: true });
73
- executable(join(keg, 'bin', 'ruby'), `echo "brew-ruby $*" >> '${log}'; printf '3.4.1'`);
74
- executable(join(bin, 'brew'), `if [ "$*" = "--prefix --installed ruby" ]; then echo '${keg}'; exit 0; fi; exit 1`);
76
+ const keg33 = join(root, 'homebrew-ruby@3.3');
77
+ if (opts.brewRuby) {
78
+ mkdirSync(join(keg, 'bin'), { recursive: true });
79
+ executable(join(keg, 'bin', 'ruby'), `echo "brew-ruby $*" >> '${log}'; printf '${brewVersion}'`);
80
+ }
81
+ if (opts.ruby33) {
82
+ mkdirSync(join(keg33, 'bin'), { recursive: true });
83
+ executable(join(keg33, 'bin', 'ruby'), `echo "ruby33 $*" >> '${log}'; printf '3.3.10'`);
84
+ }
85
+ executable(join(bin, 'brew'), [
86
+ `if [ "$*" = "--prefix --installed ruby" ]; then ${opts.brewRuby ? `echo '${keg}'; exit 0` : 'exit 1'}; fi`,
87
+ `if [ "$*" = "list --versions ruby" ]; then ${opts.brewRuby ? `echo 'ruby ${brewVersion}'; exit 0` : 'exit 1'}; fi`,
88
+ `if [ "$*" = "--prefix --installed ruby@3.3" ]; then ${opts.ruby33 ? `echo '${keg33}'; exit 0` : 'exit 1'}; fi`,
89
+ 'exit 1',
90
+ ].join('\n'));
75
91
  }
76
92
  const script = (await new CocoapodsInstallStepExecutor().execute({ source_root_path: project }, {}, testConfig)).script;
77
93
  const scriptPath = join(root, 'step.sh');
@@ -134,12 +150,133 @@ describe('cocoapods-install runs the bundler Gemfile.lock names', () => {
134
150
  expect(output).toContain('BUNDLED WITH');
135
151
  expect(output).toMatch(/EXIT [1-9]/);
136
152
  });
137
- // Homebrew's ruby is keg-only, so a guest whose CocoaPods and fastlane came
138
- // from Homebrew has it installed and still resolves `ruby` to the system 2.6.
139
- test('prefers an installed Homebrew Ruby over system Ruby', async () => {
140
- const { calls } = await run({ lock: LOCK_WITH_BUNDLER, brewRuby: true });
141
- expect(calls.some((c) => c.startsWith('brew-ruby'))).toBe(true);
142
- expect(calls.some((c) => c.startsWith('ruby '))).toBe(false);
153
+ });
154
+ // Issue 08 preferred Homebrew's Ruby whenever it was installed. On the mac
155
+ // image that is Ruby 4, and an old lockfile's gems do not load there: rake
156
+ // 13.0.6 requires `ostruct`, which stopped being a default gem in Ruby 4.0,
157
+ // so a native-extension build died inside rake. The lockfile decides instead:
158
+ // its `RUBY VERSION`, then `.ruby-version`, and system Ruby when neither names
159
+ // one. Homebrew's Ruby only when the named Ruby is 3 or newer.
160
+ describe('cocoapods-install runs the Ruby the project names', () => {
161
+ const usedBrew = (calls) => calls.some((c) => c.startsWith('brew-ruby'));
162
+ const usedSystem = (calls) => calls.some((c) => c.startsWith('ruby '));
163
+ const lockWithRuby = (v) => LOCK_WITH_BUNDLER.replace('BUNDLED WITH', `RUBY VERSION\n ruby ${v}\n\nBUNDLED WITH`);
164
+ test('a lock that names no Ruby runs system Ruby, with the locked bundler', async () => {
165
+ const { calls, output, gemHome } = await run({ lock: LOCK_WITH_BUNDLER, brewRuby: true });
166
+ expect(usedSystem(calls)).toBe(true);
167
+ expect(usedBrew(calls)).toBe(false);
168
+ expect(calls).toContain('gem install bundler -v 2.3.21 --no-document');
169
+ expect(calls.find((c) => c.startsWith('bundle _2.3.21_ install'))).toContain(`GEM_HOME=${gemHome}`);
170
+ expect(output).toMatch(/^Ruby: .*\(2\.6\.10\), GEM_HOME: .* — system: lockfile names no Ruby, and no Ruby 3\.3 is installed$/m);
171
+ });
172
+ test('a lock whose RUBY VERSION is 3 or newer runs Homebrew Ruby', async () => {
173
+ const { calls, output } = await run({ lock: lockWithRuby('3.3.4p94'), brewRuby: true });
174
+ expect(usedBrew(calls)).toBe(true);
175
+ expect(usedSystem(calls)).toBe(false);
176
+ expect(output).toMatch(/^Ruby: .*homebrew-ruby\/bin\/ruby \(3\.4\.1\), .* — from Gemfile\.lock RUBY VERSION 3\.3\.4$/m);
177
+ });
178
+ test('a lock whose RUBY VERSION is 2.x runs system Ruby', async () => {
179
+ const { calls, output } = await run({ lock: lockWithRuby('2.7.2p137'), brewRuby: true });
180
+ expect(usedBrew(calls)).toBe(false);
181
+ expect(output).toContain('— from Gemfile.lock RUBY VERSION 2.7.2');
182
+ });
183
+ test('the lock outranks .ruby-version', async () => {
184
+ const { calls, output } = await run({
185
+ lock: lockWithRuby('3.3.4p94'),
186
+ rubyVersionFile: '2.7.6\n',
187
+ brewRuby: true,
188
+ });
189
+ expect(usedBrew(calls)).toBe(true);
190
+ expect(output).toContain('— from Gemfile.lock RUBY VERSION 3.3.4');
191
+ });
192
+ test('.ruby-version of 3 or newer runs Homebrew Ruby when the lock names none', async () => {
193
+ const { calls, output } = await run({ lock: LOCK_WITH_BUNDLER, rubyVersionFile: 'ruby-3.2.2\n', brewRuby: true });
194
+ expect(usedBrew(calls)).toBe(true);
195
+ expect(output).toContain('— from .ruby-version 3.2.2');
196
+ });
197
+ test('.ruby-version of 2.7 runs system Ruby, and says so', async () => {
198
+ const { calls, output } = await run({ lock: LOCK_WITH_BUNDLER, rubyVersionFile: '2.7.6\n', brewRuby: true });
199
+ expect(usedBrew(calls)).toBe(false);
200
+ expect(usedSystem(calls)).toBe(true);
201
+ expect(output).toContain('— from .ruby-version 2.7.6');
202
+ });
203
+ test('a .ruby-version that names no version is ignored', async () => {
204
+ const { calls, output } = await run({ lock: LOCK_WITH_BUNDLER, rubyVersionFile: 'system\n', brewRuby: true });
205
+ expect(usedBrew(calls)).toBe(false);
206
+ expect(output).toContain('— system: lockfile names no Ruby');
207
+ });
208
+ test('Ruby 3 named, no Homebrew Ruby installed: system Ruby, and says so', async () => {
209
+ const { calls, output } = await run({ lock: lockWithRuby('3.3.4p94') });
210
+ expect(usedSystem(calls)).toBe(true);
211
+ expect(output).toContain('— from Gemfile.lock RUBY VERSION 3.3.4, but no Homebrew Ruby is installed');
212
+ });
213
+ test('a project without cocoapods in its Gemfile never picks a Ruby', async () => {
214
+ const { calls } = await run({ gemfile: "gem 'fastlane'\n", rubyVersionFile: '3.3.0\n', brewRuby: true });
215
+ expect(calls).toContain('pod install');
216
+ expect(usedBrew(calls)).toBe(false);
217
+ expect(usedSystem(calls)).toBe(false);
218
+ });
219
+ });
220
+ // With the lock naming no Ruby, the step chose system Ruby 2.6 as above, and the build still died:
221
+ // the Xcode 26.4 SDK's Ruby 2.6 headers have no `ruby/config.h`, so no native extension (json, ffi)
222
+ // compiles. Homebrew's Ruby is 4, where the lock's rake 13.0.6 cannot load. So a Ruby 3.3 runs when
223
+ // the lock names no Ruby or one below 3; a named 3.x runs 3.3 unless Homebrew's matches it better; a
224
+ // named 4.x runs Homebrew's. A machine without 3.3 behaves as before.
225
+ describe('cocoapods-install runs Ruby 3.3 where system Ruby cannot build native gems', () => {
226
+ const used33 = (calls) => calls.some((c) => c.startsWith('ruby33'));
227
+ const usedBrew = (calls) => calls.some((c) => c.startsWith('brew-ruby'));
228
+ const usedSystem = (calls) => calls.some((c) => c.startsWith('ruby '));
229
+ const lockWithRuby = (v) => LOCK_WITH_BUNDLER.replace('BUNDLED WITH', `RUBY VERSION\n ruby ${v}\n\nBUNDLED WITH`);
230
+ const image = { brewRuby: true, brewRubyVersion: '4.0.2', ruby33: true };
231
+ test('a lock that names no Ruby runs 3.3, with the locked bundler', async () => {
232
+ const { calls, output, gemHome } = await run({ lock: LOCK_WITH_BUNDLER, ...image });
233
+ expect(used33(calls)).toBe(true);
234
+ expect(usedSystem(calls)).toBe(false);
235
+ expect(usedBrew(calls)).toBe(false);
236
+ expect(calls).toContain('gem install bundler -v 2.3.21 --no-document');
237
+ expect(calls.find((c) => c.startsWith('bundle _2.3.21_ install'))).toContain(`GEM_HOME=${gemHome}`);
238
+ expect(output).toMatch(/^Ruby: .*homebrew-ruby@3\.3\/bin\/ruby \(3\.3\.10\), GEM_HOME: .* — Ruby 3\.3: lockfile names no Ruby, and system Ruby 2\.6 cannot build native gems$/m);
239
+ });
240
+ test('a lock whose RUBY VERSION is 2.x runs 3.3', async () => {
241
+ const { calls, output } = await run({ lock: lockWithRuby('2.7.2p137'), ...image });
242
+ expect(used33(calls)).toBe(true);
243
+ expect(output).toContain('— from Gemfile.lock RUBY VERSION 2.7.2, run on Ruby 3.3: system Ruby 2.6 cannot build native gems');
244
+ });
245
+ test('a 2.x .ruby-version runs 3.3', async () => {
246
+ const { calls } = await run({ lock: LOCK_WITH_BUNDLER, rubyVersionFile: '2.7.6\n', ...image });
247
+ expect(used33(calls)).toBe(true);
248
+ });
249
+ test('a named 3.x that Homebrew does not match runs 3.3', async () => {
250
+ const { calls, output } = await run({ lock: lockWithRuby('3.2.2'), ...image });
251
+ expect(used33(calls)).toBe(true);
252
+ expect(usedBrew(calls)).toBe(false);
253
+ expect(output).toContain('— from Gemfile.lock RUBY VERSION 3.2.2, run on Ruby 3.3');
254
+ });
255
+ test('a named 3.3 runs 3.3 and needs no aside', async () => {
256
+ const { calls, output } = await run({ lock: lockWithRuby('3.3.4p94'), ...image });
257
+ expect(used33(calls)).toBe(true);
258
+ expect(output).toMatch(/— from Gemfile\.lock RUBY VERSION 3\.3\.4$/m);
259
+ });
260
+ test('a named 3.x that Homebrew matches runs Homebrew Ruby', async () => {
261
+ const { calls, output } = await run({ lock: lockWithRuby('3.4.1'), brewRuby: true, brewRubyVersion: '3.4.7', ruby33: true });
262
+ expect(usedBrew(calls)).toBe(true);
263
+ expect(used33(calls)).toBe(false);
264
+ expect(output).toMatch(/— from Gemfile\.lock RUBY VERSION 3\.4\.1$/m);
265
+ });
266
+ test('a named 4.x runs Homebrew Ruby', async () => {
267
+ const { calls } = await run({ lock: lockWithRuby('4.0.1'), ...image });
268
+ expect(usedBrew(calls)).toBe(true);
269
+ expect(used33(calls)).toBe(false);
270
+ });
271
+ test('without 3.3, a lock that names no Ruby runs system Ruby, and says 3.3 is missing', async () => {
272
+ const { calls, output } = await run({ lock: LOCK_WITH_BUNDLER, brewRuby: true, brewRubyVersion: '4.0.2' });
273
+ expect(usedSystem(calls)).toBe(true);
274
+ expect(output).toContain('— system: lockfile names no Ruby, and no Ruby 3.3 is installed');
275
+ });
276
+ test('without 3.3, a 2.x lock runs system Ruby, and says 3.3 is missing', async () => {
277
+ const { calls, output } = await run({ lock: lockWithRuby('2.7.2p137'), brewRuby: true });
278
+ expect(usedSystem(calls)).toBe(true);
279
+ expect(output).toContain('— from Gemfile.lock RUBY VERSION 2.7.2, and no Ruby 3.3 is installed');
143
280
  });
144
281
  });
145
282
  //# sourceMappingURL=cocoapods-locked-bundler.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ios-deps.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ios-deps.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAc,MAAM,wBAAwB,CAAC;AAMhF,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,gBAAgB;IAChE,yBAAyB,CACvB,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAUpB,OAAO,CACX,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CAoJpB;AAMD,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,gBAAgB;IACxD,yBAAyB,CACvB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAUpB,OAAO,CACX,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CAyDpB"}
1
+ {"version":3,"file":"ios-deps.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ios-deps.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAc,MAAM,wBAAwB,CAAC;AAMhF,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,gBAAgB;IAChE,yBAAyB,CACvB,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAUpB,OAAO,CACX,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CA+MpB;AAMD,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,gBAAgB;IACxD,yBAAyB,CACvB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAUpB,OAAO,CACX,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CAyDpB"}
@@ -83,9 +83,18 @@ export class CocoapodsInstallStepExecutor extends BaseStepExecutor {
83
83
  //
84
84
  // Three moves, each conditional, so a machine missing a piece keeps the
85
85
  // old behaviour rather than failing on it:
86
- // - prefer an installed Homebrew Ruby. It is keg-only, so it is not on
87
- // PATH even where it is installed (Homebrew's cocoapods and fastlane
88
- // formulae depend on it), and the system 2.6 wins by default;
86
+ // - run a Ruby that fits the one the project names: Gemfile.lock's
87
+ // `RUBY VERSION`, then `.ruby-version`. Homebrew's Ruby is 4 on the mac
88
+ // image, and an old lockfile's gems do not load there — rake 13.0.6
89
+ // requires `ostruct`, no longer a default gem — so "newest installed"
90
+ // is the wrong default. System Ruby 2.6 is no answer either: the Xcode
91
+ // 26.4 SDK's Ruby 2.6 headers have no `ruby/config.h`, so no native
92
+ // extension (json, ffi) compiles under it. So a Ruby named below 3, or
93
+ // none, runs a Homebrew `ruby@3.3`; a named 3.x runs 3.3 unless
94
+ // Homebrew's `ruby` has its major.minor; a named 4.x runs Homebrew's.
95
+ // Both are keg-only, so neither is on PATH where it is installed. With
96
+ // no 3.3 on the machine, below 3 stays on system Ruby and 3+ runs
97
+ // Homebrew's, as before. The `Ruby:` line says which, and why;
89
98
  // - point GEM_HOME at a writable directory outside the checkout, so both
90
99
  // `gem install bundler` and `bundle install` can write without sudo,
91
100
  // and put its bin directory first;
@@ -93,10 +102,60 @@ export class CocoapodsInstallStepExecutor extends BaseStepExecutor {
93
102
  // `bundle _<version>_`, which is the form RubyGems accepts.
94
103
  commands.push('BUNDLE_CMD="bundle"');
95
104
  commands.push('if [ "$USE_BUNDLE_EXEC" = "true" ]; then');
105
+ commands.push(' WANTED_RUBY=""');
106
+ commands.push(' WANTED_FROM=""');
107
+ commands.push(' if [ -f "Gemfile.lock" ]; then');
108
+ commands.push(' WANTED_RUBY="$(awk \'/^RUBY VERSION/ { getline; sub(/^[[:space:]]*ruby[[:space:]]+/, ""); sub(/p[0-9]+.*$/, ""); gsub(/[[:space:]]/, ""); print; exit }\' Gemfile.lock)"');
109
+ commands.push(' [ -n "$WANTED_RUBY" ] && WANTED_FROM="Gemfile.lock RUBY VERSION"');
110
+ commands.push(' fi');
111
+ commands.push(' if [ -z "$WANTED_RUBY" ] && [ -f ".ruby-version" ]; then');
112
+ commands.push(' WANTED_RUBY="$(head -n 1 .ruby-version | tr -d \'[:space:]\')"');
113
+ commands.push(' WANTED_RUBY="${WANTED_RUBY#ruby-}"');
114
+ commands.push(' WANTED_FROM=".ruby-version"');
115
+ commands.push(' fi');
116
+ commands.push(' case "${WANTED_RUBY%%.*}" in');
117
+ commands.push(' \'\'|*[!0-9]*) WANTED_RUBY="" ;;');
118
+ commands.push(' esac');
119
+ commands.push(' # The Rubies this machine has: a Homebrew `ruby@3.3` keg, and Homebrew\'s');
120
+ commands.push(' # `ruby` with its major.minor. Both keg-only, so neither is on PATH.');
121
+ commands.push(' RUBY33=""');
122
+ commands.push(' BREW_RUBY=""');
123
+ commands.push(' BREW_RUBY_MM=""');
96
124
  commands.push(' if command -v brew &>/dev/null; then');
125
+ commands.push(' RUBY33="$(brew --prefix --installed ruby@3.3 2>/dev/null || true)"');
126
+ commands.push(' if [ -n "$RUBY33" ] && [ ! -x "$RUBY33/bin/ruby" ]; then RUBY33=""; fi');
97
127
  commands.push(' BREW_RUBY="$(brew --prefix --installed ruby 2>/dev/null || true)"');
98
128
  commands.push(' if [ -n "$BREW_RUBY" ] && [ -x "$BREW_RUBY/bin/ruby" ]; then');
129
+ commands.push(' BREW_RUBY_MM="$(brew list --versions ruby 2>/dev/null | awk \'{ split($2, v, "."); print v[1] "." v[2]; exit }\')"');
130
+ commands.push(' else');
131
+ commands.push(' BREW_RUBY=""');
132
+ commands.push(' fi');
133
+ commands.push(' fi');
134
+ commands.push(' WANTED_MAJOR="${WANTED_RUBY%%.*}"');
135
+ commands.push(' WANTED_MM="$(printf \'%s\' "$WANTED_RUBY" | awk -F. \'{ print $1 "." $2 }\')"');
136
+ commands.push(' if [ -z "$WANTED_RUBY" ] || [ "$WANTED_MAJOR" -lt 3 ]; then');
137
+ commands.push(' if [ -z "$WANTED_RUBY" ]; then');
138
+ commands.push(' if [ -n "$RUBY33" ]; then');
139
+ commands.push(' export PATH="$RUBY33/bin:$PATH"');
140
+ commands.push(' RUBY_REASON="Ruby 3.3: lockfile names no Ruby, and system Ruby 2.6 cannot build native gems"');
141
+ commands.push(' else');
142
+ commands.push(' RUBY_REASON="system: lockfile names no Ruby, and no Ruby 3.3 is installed"');
143
+ commands.push(' fi');
144
+ commands.push(' elif [ -n "$RUBY33" ]; then');
145
+ commands.push(' export PATH="$RUBY33/bin:$PATH"');
146
+ commands.push(' RUBY_REASON="from $WANTED_FROM $WANTED_RUBY, run on Ruby 3.3: system Ruby 2.6 cannot build native gems"');
147
+ commands.push(' else');
148
+ commands.push(' RUBY_REASON="from $WANTED_FROM $WANTED_RUBY, and no Ruby 3.3 is installed"');
149
+ commands.push(' fi');
150
+ commands.push(' else');
151
+ commands.push(' RUBY_REASON="from $WANTED_FROM $WANTED_RUBY"');
152
+ commands.push(' if [ "$WANTED_MAJOR" -eq 3 ] && [ -n "$RUBY33" ] && [ "$BREW_RUBY_MM" != "$WANTED_MM" ]; then');
153
+ commands.push(' export PATH="$RUBY33/bin:$PATH"');
154
+ commands.push(' [ "$WANTED_MM" != "3.3" ] && RUBY_REASON="$RUBY_REASON, run on Ruby 3.3"');
155
+ commands.push(' elif [ -n "$BREW_RUBY" ]; then');
99
156
  commands.push(' export PATH="$BREW_RUBY/bin:$PATH"');
157
+ commands.push(' else');
158
+ commands.push(' RUBY_REASON="$RUBY_REASON, but no Homebrew Ruby is installed"');
100
159
  commands.push(' fi');
101
160
  commands.push(' fi');
102
161
  commands.push(' if ! command -v bundle &>/dev/null && ! command -v gem &>/dev/null; then');
@@ -109,7 +168,7 @@ export class CocoapodsInstallStepExecutor extends BaseStepExecutor {
109
168
  commands.push(' mkdir -p "$GEM_HOME"');
110
169
  commands.push(' export PATH="$GEM_HOME/bin:$PATH"');
111
170
  commands.push(' RUBY_VERSION_USED="$(ruby -e \'print RUBY_VERSION\' 2>/dev/null || echo unknown)"');
112
- commands.push(' echo "Ruby: $(command -v ruby || echo none) ($RUBY_VERSION_USED), GEM_HOME: $GEM_HOME"');
171
+ commands.push(' echo "Ruby: $(command -v ruby || echo none) ($RUBY_VERSION_USED), GEM_HOME: $GEM_HOME — $RUBY_REASON"');
113
172
  commands.push(' LOCKED_BUNDLER=""');
114
173
  commands.push(' if [ -f "Gemfile.lock" ]; then');
115
174
  commands.push(' LOCKED_BUNDLER="$(awk \'/^BUNDLED WITH/ { getline; gsub(/[[:space:]]/, ""); print; exit }\' Gemfile.lock)"');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.8.7",
3
+ "version": "2.8.9",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",