@invarn/cibuild 2.8.6 → 2.8.7

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.
@@ -124,6 +124,52 @@ describe("cibuild_gradle_memory_plan", () => {
124
124
  ]);
125
125
  });
126
126
  });
127
+ /** The plan, then the workers plan, as the step runs them. */
128
+ function workersPlan(memMib, maxWorkers) {
129
+ const script = `${GRADLE_MEMORY_FUNCTIONS}
130
+ cibuild_gradle_memory_plan "$1" gradle.properties "$2/gradle.properties" ""
131
+ cibuild_gradle_workers_plan "$3"
132
+ for a in "\${CIBUILD_GRADLE_MEMORY_ARGS[@]}"; do printf 'ARG %s\\n' "$a"; done
133
+ printf 'LINE %s\\n' "$CIBUILD_GRADLE_WORKERS_LINE"
134
+ printf 'SENTENCE %s\\n' "$CIBUILD_GRADLE_MEMORY_SENTENCE"`;
135
+ const out = execFileSync("bash", ["-c", script, "plan", memMib, join(dir, "no-user-home"), maxWorkers], {
136
+ cwd: dir,
137
+ encoding: "utf-8",
138
+ });
139
+ const lines = out.split("\n");
140
+ return {
141
+ args: lines.filter((l) => l.startsWith("ARG ")).map((l) => l.slice(4)),
142
+ line: (lines.find((l) => l.startsWith("LINE ")) ?? "").slice(5),
143
+ sentence: (lines.find((l) => l.startsWith("SENTENCE ")) ?? "").slice(9),
144
+ };
145
+ }
146
+ // ReFra was killed again with its heap capped: off-heap memory and parallel
147
+ // native compilers are past what a heap cap bounds. Its CI also sets
148
+ // org.gradle.workers.max=2, which the pipeline carries as max_workers.
149
+ describe("cibuild_gradle_workers_plan", () => {
150
+ test("ReFra: the worker count goes after the heap cap, and the sentence names it", () => {
151
+ copyFileSync(join(FIXTURES, "refra.gradle.properties"), join(dir, "gradle.properties"));
152
+ const p = workersPlan(TEN_GIB, "2");
153
+ expect(p.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx3840m -Dfile.encoding=UTF-8", "--max-workers=2"]);
154
+ expect(p.line).toBe("Gradle memory: running with --max-workers=2, as the pipeline asks (set on the command line, over any org.gradle.workers.max).");
155
+ expect(p.sentence).toMatch(/This build ran them capped: Gradle -Xmx3840m, .* Gradle ran with --max-workers=2\.$/);
156
+ });
157
+ test("heaps that fit still get the worker count", () => {
158
+ const p = workersPlan(TEN_GIB, "4");
159
+ expect(p.args).toEqual(["--max-workers=4"]);
160
+ });
161
+ test("nothing asked, nothing passed or printed", () => {
162
+ const p = workersPlan(TEN_GIB, "");
163
+ expect(p.args).toEqual([]);
164
+ expect(p.line).toBe("");
165
+ expect(p.sentence).not.toContain("max-workers");
166
+ });
167
+ test.each(["0", "02", "-1", "two", "2 --offline"])("%s is not a worker count, and says so", (value) => {
168
+ const p = workersPlan(TEN_GIB, value);
169
+ expect(p.args).toEqual([]);
170
+ expect(p.line).toBe(`Gradle memory: max_workers=${value} is not a positive whole number, so it is not passed and Gradle picks its own worker count.`);
171
+ });
172
+ });
127
173
  /** A directory standing in for PATH, with a fake `dmesg` that prints `oom`. */
128
174
  function fakeBin(oom) {
129
175
  const bin = join(dir, "bin");
@@ -173,6 +219,38 @@ describe("the Gradle steps", () => {
173
219
  const args = execFileSync("cat", [join(dir, "gradlew-args")], { encoding: "utf-8" }).trim().split("\n");
174
220
  expect(args).toEqual(["-Dorg.gradle.jvmargs=-Xmx256m -Dfile.encoding=UTF-8", "assembleDebug", "--stacktrace"]);
175
221
  });
222
+ test("the pipeline's max_workers reach Gradle after the heap arguments, before the task", async () => {
223
+ fakeGradlew("exit 0");
224
+ const step = await new GradleBuildStepExecutor().execute(
225
+ // YAML reads `max_workers: 2` as a number.
226
+ { gradle_task: "assembleDebug", gradle_options: "--stacktrace", jvmargs: "-Xmx256m", max_workers: 2 }, {}, testConfig);
227
+ const run = runStep(step.script, fakeBin(""));
228
+ expect(run.status).toBe(0);
229
+ expect(run.stdout).toContain("Gradle memory: running with --max-workers=2, as the pipeline asks");
230
+ const args = execFileSync("cat", [join(dir, "gradlew-args")], { encoding: "utf-8" }).trim().split("\n");
231
+ expect(args).toEqual(["-Dorg.gradle.jvmargs=-Xmx256m", "--max-workers=2", "assembleDebug", "--stacktrace"]);
232
+ });
233
+ test("a killed daemon's sentence names the worker count it ran with", async () => {
234
+ copyFileSync(join(FIXTURES, "refra.gradle.properties"), join(dir, "gradle.properties"));
235
+ fakeGradlew('echo "Gradle build daemon disappeared unexpectedly"\nexit 1');
236
+ const step = await new GradleBuildStepExecutor().execute({ gradle_task: "assembleDebug", max_workers: "2" }, {}, testConfig);
237
+ const run = runStep(step.script, fakeBin(OOM_LINE));
238
+ expect(run.status).toBe(1);
239
+ // The test machine's own memory decides whether a cap applied, so only the
240
+ // sentence's end is asserted.
241
+ expect(run.stdout).toMatch(/^The build machine has .*asked for 16\.0 GiB .* Gradle ran with --max-workers=2\.$/m);
242
+ });
243
+ test("every Gradle step passes max_workers to the plan", async () => {
244
+ const steps = [
245
+ await new GradleBuildStepExecutor().execute({ max_workers: 3 }, {}, testConfig),
246
+ await new AndroidLintStepExecutor().execute({ max_workers: 3 }, {}, testConfig),
247
+ await new AndroidUnitTestStepExecutor().execute({ max_workers: 3 }, {}, testConfig),
248
+ await new AndroidBuildForUITestingStepExecutor().execute({ max_workers: 3 }, {}, testConfig),
249
+ ];
250
+ for (const step of steps) {
251
+ expect(step.script).toContain("cibuild_gradle_memory_cap '' '3'");
252
+ }
253
+ });
176
254
  test("every Gradle step runs through the plan, and every one is valid bash", async () => {
177
255
  const steps = [
178
256
  await new GradleBuildStepExecutor().execute({}, {}, testConfig),
@@ -182,7 +260,7 @@ describe("the Gradle steps", () => {
182
260
  ];
183
261
  for (const step of steps) {
184
262
  const script = step.script;
185
- expect(script).toContain("cibuild_gradle_memory_cap ''");
263
+ expect(script).toContain("cibuild_gradle_memory_cap '' ''");
186
264
  execFileSync("bash", ["-n"], { input: script });
187
265
  }
188
266
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.8.6",
3
+ "version": "2.8.7",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",