@invarn/cibuild 2.8.2 → 2.8.3

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.
@@ -351,4 +351,32 @@ describe("a build that reads the properties file directly", () => {
351
351
  expect(await keys()).toEqual(["api.key"]);
352
352
  });
353
353
  });
354
+ /**
355
+ * A scan that answers well on a small repository and thins out on a large one
356
+ * is the worse of the two failures, because the large one is the one someone
357
+ * is paid to build.
358
+ *
359
+ * Manifests and source shared a file budget at first, and source was walked
360
+ * first. Measured on a real application — 1743 source files, 47 manifests —
361
+ * the source walk spent the whole budget and the manifests were never opened,
362
+ * so every key referenced only as `${KEY}` in a manifest came back missing.
363
+ * Nine of that application's twenty declared keys were lost that way, and the
364
+ * scan reported the other eleven with no sign anything was wrong.
365
+ *
366
+ * This is the only test here that builds a tree big enough to exhaust a
367
+ * budget, because that is the only way to express the defect. It costs about
368
+ * half a second.
369
+ */
370
+ describe("a repository larger than the source budget", () => {
371
+ test("still reads its manifests", async () => {
372
+ projectApplyingTheSecretsPlugin();
373
+ write("app/src/main/AndroidManifest.xml", '<manifest android:value="${MANIFEST_ONLY_KEY}" />\n');
374
+ // Past SOURCE_FILE_CAP, spread over directories so no single readdir is
375
+ // unrepresentative.
376
+ for (let i = 0; i < 8100; i++) {
377
+ write(`app/src/main/java/p${i % 40}/F${i}.kt`, `val x${i} = 1\n`);
378
+ }
379
+ expect(await keys()).toContain("MANIFEST_ONLY_KEY");
380
+ }, 60_000);
381
+ });
354
382
  //# sourceMappingURL=a-properties-stand-in-declares-the-keys-the-build-reads.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"android-scanner.d.ts","sourceRoot":"","sources":["../../../src/commands/android-scanner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"android-scanner.d.ts","sourceRoot":"","sources":["../../../src/commands/android-scanner.ts"],"names":[],"mappings":"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"}
@@ -433,7 +433,23 @@ const MACHINE_LOCAL_KEYS = new Set(["sdk.dir", "ndk.dir", "cmake.dir"]);
433
433
  // runs on every scan of one.
434
434
  const SOURCE_EXTENSIONS = [".kt", ".kts", ".java"];
435
435
  const SOURCE_SKIP_DIRS = new Set(["build", "node_modules"]);
436
- const SOURCE_FILE_CAP = 1500;
436
+ /**
437
+ * **Manifests get their own budget, and a source walk cannot spend it.**
438
+ *
439
+ * They shared one at first, with source walked first, and on a real application
440
+ * that meant the manifests were never reached at all: 1743 source files against
441
+ * a 1500-file cap left nothing, and the keys referenced only as `${KEY}` in a
442
+ * manifest — which is most of them — came back missing. A scan that answers
443
+ * well on a small repository and silently thins out on a large one is the worse
444
+ * of the two failures, because the large one is the one someone is paid to
445
+ * build.
446
+ *
447
+ * There are few manifests and many source files — 47 against 1743 in that same
448
+ * application — so the two are not competing for a scarce resource, they were
449
+ * just sharing the wrong one.
450
+ */
451
+ const SOURCE_FILE_CAP = 8000;
452
+ const MANIFEST_FILE_CAP = 500;
437
453
  const SOURCE_DEPTH_CAP = 12;
438
454
  /** Source files under `dir`, up to the shared file budget. */
439
455
  function findSourceFiles(dir, budget, depth = 0) {
@@ -536,14 +552,17 @@ function collectPropertyKeys(gradleFiles) {
536
552
  }
537
553
  if (moduleDirs.size === 0)
538
554
  return [];
539
- const budget = { left: SOURCE_FILE_CAP };
555
+ const sourceBudget = { left: SOURCE_FILE_CAP };
556
+ const manifestBudget = { left: MANIFEST_FILE_CAP };
540
557
  for (const dir of outermost([...moduleDirs])) {
541
- for (const file of findSourceFiles(dir, budget)) {
542
- for (const name of extractBuildConfigFieldRefs(safeRead(file)))
558
+ // Manifests first. They are the likeliest place for a key and the cheapest
559
+ // to read, so if anything is ever going to run short it must not be these.
560
+ for (const manifest of findManifests(dir, manifestBudget)) {
561
+ for (const name of extractManifestXmlPlaceholders(safeRead(manifest)))
543
562
  keys.add(name);
544
563
  }
545
- for (const manifest of findManifests(dir, budget)) {
546
- for (const name of extractManifestXmlPlaceholders(safeRead(manifest)))
564
+ for (const file of findSourceFiles(dir, sourceBudget)) {
565
+ for (const name of extractBuildConfigFieldRefs(safeRead(file)))
547
566
  keys.add(name);
548
567
  }
549
568
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.8.2",
3
+ "version": "2.8.3",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",