@appforge-ci/admin-cli 0.3.8 → 0.3.10

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.
@@ -0,0 +1,10 @@
1
+ import type { Command } from "commander";
2
+ /**
3
+ * `appforge-admin warm-cache` — fills a regulated org's offline package cache, then proves it resolves offline. Two
4
+ * kinds of project: `--project` (a Flutter app: pub, from its pubspec.lock) or `--gradle` (an Android project: Gradle,
5
+ * from its wrapper and build files, into GRADLE_USER_HOME). Run ON the Mac, in your own terminal (the build user's
6
+ * commands prompt for sudo as needed). Regulated builds have no route to the package repositories, so this is how their
7
+ * dependencies get into the cache.
8
+ */
9
+ export declare function registerWarmCacheCommand(program: Command): void;
10
+ //# sourceMappingURL=warm-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-cache.d.ts","sourceRoot":"","sources":["../../src/commands/warm-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,QAqBxD"}
@@ -0,0 +1,31 @@
1
+ import { realWarmCacheDeps, realWarmGradleDeps, warmGradleCache, warmOrgCache } from "../lib/warm-cache.js";
2
+ /**
3
+ * `appforge-admin warm-cache` — fills a regulated org's offline package cache, then proves it resolves offline. Two
4
+ * kinds of project: `--project` (a Flutter app: pub, from its pubspec.lock) or `--gradle` (an Android project: Gradle,
5
+ * from its wrapper and build files, into GRADLE_USER_HOME). Run ON the Mac, in your own terminal (the build user's
6
+ * commands prompt for sudo as needed). Regulated builds have no route to the package repositories, so this is how their
7
+ * dependencies get into the cache.
8
+ */
9
+ export function registerWarmCacheCommand(program) {
10
+ program
11
+ .command("warm-cache")
12
+ .description("Fill a regulated org's offline cache from a project (pub for --project, Gradle for --gradle), then verify it resolves offline (run ON the Mac)")
13
+ .requiredOption("--org <orgId>", "the customer org whose regulated builds will use this cache")
14
+ .option("--project <dir>", "a Flutter app's directory (its pubspec.yaml and pubspec.lock)")
15
+ .option("--gradle <dir>", "an Android project's directory (its gradlew and Gradle build files)")
16
+ .option("--flutter-sdk <clone>", "with --project: which of the org's cached Flutter SDK clones to use (a directory name, or a path); default: the only one")
17
+ .action(async (opts) => {
18
+ if (Boolean(opts.project) === Boolean(opts.gradle))
19
+ throw new Error("pass exactly one of --project (pub) or --gradle (Gradle)");
20
+ if (opts.gradle) {
21
+ if (opts.flutterSdk)
22
+ throw new Error("--flutter-sdk applies to --project only");
23
+ const result = await warmGradleCache({ orgId: opts.org, projectDir: opts.gradle }, realWarmGradleDeps());
24
+ console.log(`\nDone: ${result.buildFiles} Gradle build file(s) staged; this org's Gradle cache (${result.gradleHome}) resolves offline.`);
25
+ return;
26
+ }
27
+ const result = await warmOrgCache({ orgId: opts.org, projectDir: opts.project, flutterSdk: opts.flutterSdk }, realWarmCacheDeps());
28
+ console.log(`\nDone: ${result.packages} hosted package(s) cached for this org, verified offline with ${result.clone}.`);
29
+ });
30
+ }
31
+ //# sourceMappingURL=warm-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-cache.js","sourceRoot":"","sources":["../../src/commands/warm-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE5G;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CACV,gJAAgJ,CACjJ;SACA,cAAc,CAAC,eAAe,EAAE,6DAA6D,CAAC;SAC9F,MAAM,CAAC,iBAAiB,EAAE,+DAA+D,CAAC;SAC1F,MAAM,CAAC,gBAAgB,EAAE,qEAAqE,CAAC;SAC/F,MAAM,CAAC,uBAAuB,EAAE,0HAA0H,CAAC;SAC3J,MAAM,CAAC,KAAK,EAAE,IAA6E,EAAE,EAAE;QAC9F,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAChI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAChF,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACzG,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,UAAU,0DAA0D,MAAM,CAAC,UAAU,qBAAqB,CAAC,CAAC;YAC1I,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,OAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACpI,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,QAAQ,iEAAiE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAC1H,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { apiErrorMessage } from "@appforge-ci/core";
4
4
  import { registerLoginCommand } from "./commands/login.js";
5
5
  import { registerAgentsCommands } from "./commands/agents.js";
6
6
  import { registerVpnHostsCommands } from "./commands/vpn-hosts.js";
7
+ import { registerWarmCacheCommand } from "./commands/warm-cache.js";
7
8
  /**
8
9
  * appforge-admin — fleet management for the AppForge platform operator.
9
10
  *
@@ -24,6 +25,7 @@ program
24
25
  registerLoginCommand(program);
25
26
  registerAgentsCommands(program);
26
27
  registerVpnHostsCommands(program);
28
+ registerWarmCacheCommand(program);
27
29
  program.parseAsync(process.argv).catch((err) => {
28
30
  // Preserves the original "print whatever was thrown" fallback for a
29
31
  // non-Error throw (rare, but not this fix's concern) — only the
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,uFAAuF,CAAC;KACpG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAElC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,oEAAoE;IACpE,gEAAgE;IAChE,2DAA2D;IAC3D,sEAAsE;IACtE,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,uFAAuF,CAAC;KACpG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAElC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,oEAAoE;IACpE,gEAAgE;IAChE,2DAA2D;IAC3D,sEAAsE;IACtE,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The hosted packages a pubspec.lock pins, as the `name-version` directory names pub uses in its cache. Git, path
3
+ * and sdk packages are not in the hosted tree, so they are skipped. pub writes the lock in one fixed two-level
4
+ * layout: `packages:`, then ` name:`, then indented `source:` and `version:` lines.
5
+ */
6
+ export declare function hostedPackagesFromLock(lockText: string): string[];
7
+ /**
8
+ * Which cloned Flutter SDK to warm against. The lock's solver depends on the SDK version, so the warm-up must use
9
+ * the same clone the builds use. `explicit` is a clone's directory name under the org's `flutter-sdk/`, or an
10
+ * absolute path. Without it, the org must have exactly one complete clone.
11
+ */
12
+ export declare function pickSdkClone(orgSdkDir: string, completeClones: readonly string[], explicit?: string): string;
13
+ export interface WarmCacheOptions {
14
+ orgId: string;
15
+ /** The Flutter app's directory: its pubspec.yaml and pubspec.lock. */
16
+ projectDir: string;
17
+ /** A clone's directory name, or an absolute path. Default: the org's only complete clone. */
18
+ flutterSdk?: string;
19
+ user?: string;
20
+ }
21
+ /** Every filesystem and command action the warm-up takes, behind one seam so the whole sequence is unit-tested. */
22
+ export interface WarmCacheDeps {
23
+ readText(path: string): string;
24
+ exists(path: string): boolean;
25
+ listDirs(path: string): string[];
26
+ orgCacheDir(orgId: string): string;
27
+ checkBuildUser(user: string): Promise<{
28
+ installed: boolean;
29
+ reason: string;
30
+ }>;
31
+ buildUserDirs(user: string): Promise<{
32
+ temp: string;
33
+ cache: string;
34
+ }>;
35
+ /** Copies the named files into a new directory the build user can read, and returns its path. */
36
+ stage(projectDir: string, names: readonly string[]): string;
37
+ unstage(dir: string): void;
38
+ /** Runs `argv` as the build user, streaming its output to the terminal. Rejects on a non-zero exit. */
39
+ runAsBuildUser(user: string, argv: string[]): Promise<void>;
40
+ /** Runs `argv` as the build user and returns its stdout. Rejects on a non-zero exit. */
41
+ captureAsBuildUser(user: string, argv: string[]): Promise<string>;
42
+ randomId(): string;
43
+ log(line: string): void;
44
+ }
45
+ export interface WarmCacheResult {
46
+ packages: number;
47
+ clone: string;
48
+ }
49
+ /**
50
+ * Fills the org's offline package cache from a project's lock, then proves it. The lock is resolved online once, as
51
+ * the build user, into the org's pub cache. A fresh workspace must then resolve the same lock with `--offline`, from
52
+ * that cache alone. A regulated build runs with no route to pub.dev, so this is how its dependencies get there.
53
+ */
54
+ export declare function warmOrgCache(opts: WarmCacheOptions, deps: WarmCacheDeps): Promise<WarmCacheResult>;
55
+ /** The real seam: the agent's own cache and build-user helpers, the terminal, and a staging directory. */
56
+ export declare function realWarmCacheDeps(): WarmCacheDeps;
57
+ /** The project-relative paths a Gradle dependency resolution needs, and nothing else. Included: the wrapper, the root
58
+ * `gradle/` directory (wrapper properties and jar, version catalogs), every settings/build/init script, gradle.properties,
59
+ * any `*.versions.toml`, and `buildSrc/` (its sources compile during configuration). Left out, on purpose: app source,
60
+ * keystores, `key.properties`, `local.properties` and `google-services.json`. Staging copies these into a directory the
61
+ * build user can read, so the list stays narrow. A project that needs something left out (an included build's convention
62
+ * plugin sources, say) fails the online step loudly instead of passing. */
63
+ export declare function gradleBuildFiles(relPaths: readonly string[]): string[];
64
+ /** The `dependencies` report exits 0 even when a dependency did not resolve (the line ends in FAILED), so the warm-up
65
+ * reads the report for those lines. Returns them, empty when the report is clean. */
66
+ export declare function unresolvedDependencyLines(report: string): string[];
67
+ /** The environment one Gradle step gets: the agent's own build-step environment (agent env.ts, buildSandboxEnv), with
68
+ * this warm-up's workspace as HOME and TMPDIR and the org's cache, so GRADLE_USER_HOME is the directory builds use. Only
69
+ * allow-listed host variables come through; no build secret is present. */
70
+ export declare function gradleStepEnv(i: {
71
+ agentEnv: NodeJS.ProcessEnv;
72
+ realHome: string;
73
+ loginToolchainEnv: Readonly<Record<string, string>>;
74
+ buildHome: string;
75
+ tmpDir: string;
76
+ orgCacheDir: string;
77
+ }): Record<string, string>;
78
+ export interface WarmGradleOptions {
79
+ orgId: string;
80
+ /** The Android project's directory: its Gradle wrapper and build files. */
81
+ projectDir: string;
82
+ user?: string;
83
+ }
84
+ export interface WarmGradleResult {
85
+ /** How many build-logic files were staged. */
86
+ buildFiles: number;
87
+ /** The GRADLE_USER_HOME that now holds the resolved dependencies. */
88
+ gradleHome: string;
89
+ }
90
+ /** Every filesystem, command and environment action the Gradle warm-up takes, behind seams so the sequence is unit-tested. */
91
+ export interface WarmGradleDeps extends Pick<WarmCacheDeps, "checkBuildUser" | "buildUserDirs" | "stage" | "unstage" | "captureAsBuildUser" | "orgCacheDir" | "randomId" | "log"> {
92
+ /** Every project-relative file path under the project directory (skipping GRADLE_SKIP_DIRS). */
93
+ listProjectFiles(projectDir: string): string[];
94
+ /** Runs `argv` as the build user with `stdin` as its input. Streams the output to the terminal, returns stdout, and
95
+ * rejects on a non-zero exit. */
96
+ runStepAsBuildUser(user: string, argv: string[], stdin: string): Promise<string>;
97
+ /** The operator's environment (only its allow-listed names reach a step). */
98
+ agentEnv(): NodeJS.ProcessEnv;
99
+ realHome(): string;
100
+ loginToolchainEnv(): Promise<Record<string, string>>;
101
+ }
102
+ /**
103
+ * Fills the org's Gradle cache from an Android project's build logic, then proves it. The project's wrapper resolves every
104
+ * dependency once, online, as the build user, into the org's GRADLE_USER_HOME. A fresh workspace must then resolve the same
105
+ * project with `--offline`, from that cache alone, and any unresolved dependency fails the warm-up. A regulated build has no
106
+ * route to the repositories, so this is how its Gradle dependencies get there.
107
+ */
108
+ export declare function warmGradleCache(opts: WarmGradleOptions, deps: WarmGradleDeps): Promise<WarmGradleResult>;
109
+ /** The real Gradle seams: the pub flow's real parts, plus the project walk, the streaming step runner and the operator's
110
+ * environment. */
111
+ export declare function realWarmGradleDeps(): WarmGradleDeps;
112
+ /** Every file path under `root`, relative and with forward slashes, skipping GRADLE_SKIP_DIRS and symlinks. */
113
+ export declare function listProjectFilesUnder(root: string, rel?: string): string[];
114
+ //# sourceMappingURL=warm-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-cache.d.ts","sourceRoot":"","sources":["../../src/lib/warm-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,320 @@
1
+ import { execFileSync, spawn } from "node:child_process";
2
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { BUILD_USER_NAME, buildUserDarwinDirs, detectBuildUser, realBuildUserProbeDeps } from "@appforge-ci/agent/dist/lib/sandbox/build-user.js";
6
+ import { cacheRootDir } from "@appforge-ci/agent/dist/lib/sandbox/cache.js";
7
+ import { buildSandboxEnv, envSourceScript } from "@appforge-ci/agent/dist/lib/sandbox/env.js";
8
+ import { loginShellToolchainEnv } from "@appforge-ci/agent/dist/lib/sandbox/toolchain.js";
9
+ /** The file a finished org cache leaves in its Flutter SDK clone (see the agent's toolchain.ts). Only such a clone is used. */
10
+ const CLONE_COMPLETE_MARKER = ".appforge-clone-complete";
11
+ /**
12
+ * The hosted packages a pubspec.lock pins, as the `name-version` directory names pub uses in its cache. Git, path
13
+ * and sdk packages are not in the hosted tree, so they are skipped. pub writes the lock in one fixed two-level
14
+ * layout: `packages:`, then ` name:`, then indented `source:` and `version:` lines.
15
+ */
16
+ export function hostedPackagesFromLock(lockText) {
17
+ const out = [];
18
+ let name = null;
19
+ let source = null;
20
+ let version = null;
21
+ const flush = () => {
22
+ if (name && source === "hosted" && version)
23
+ out.push(`${name}-${version}`);
24
+ };
25
+ for (const raw of lockText.split("\n")) {
26
+ const line = raw.replace(/\r$/, "");
27
+ const top = /^ {2}([A-Za-z0-9_]+):$/.exec(line);
28
+ if (top) {
29
+ flush();
30
+ name = top[1];
31
+ source = null;
32
+ version = null;
33
+ continue;
34
+ }
35
+ const src = /^ {4}source: (\S+)/.exec(line);
36
+ if (src)
37
+ source = src[1];
38
+ const ver = /^ {4}version: "([^"]+)"/.exec(line);
39
+ if (ver)
40
+ version = ver[1];
41
+ }
42
+ flush();
43
+ return out;
44
+ }
45
+ /**
46
+ * Which cloned Flutter SDK to warm against. The lock's solver depends on the SDK version, so the warm-up must use
47
+ * the same clone the builds use. `explicit` is a clone's directory name under the org's `flutter-sdk/`, or an
48
+ * absolute path. Without it, the org must have exactly one complete clone.
49
+ */
50
+ export function pickSdkClone(orgSdkDir, completeClones, explicit) {
51
+ if (explicit)
52
+ return explicit.startsWith("/") ? explicit : join(orgSdkDir, explicit);
53
+ if (completeClones.length === 0)
54
+ throw new Error("this org has no cached Flutter SDK clone yet — run one build for it first, or pass --flutter-sdk");
55
+ if (completeClones.length > 1)
56
+ throw new Error(`this org has ${completeClones.length} cached Flutter SDK clones (${completeClones.join(", ")}); pass --flutter-sdk to choose one`);
57
+ return join(orgSdkDir, completeClones[0]);
58
+ }
59
+ /** Refuses, before anything runs, unless the build user is installed and both its sudoers grants work. */
60
+ async function requireBuildUser(user, deps) {
61
+ const status = await deps.checkBuildUser(user);
62
+ if (!status.installed) {
63
+ throw new Error(`the build user '${user}' is not ready on this Mac (${status.reason}); run 'appforge-admin agents install-build-user' first`);
64
+ }
65
+ }
66
+ /** The environment the agent gives a pub step (the same variables), as `env -i` assignments. */
67
+ function pubEnv(home, tmp, clone, pubCache) {
68
+ return [`HOME=${home}`, `TMPDIR=${tmp}`, `PATH=${join(clone, "bin")}:/usr/bin:/bin:/usr/sbin:/sbin`, `PUB_CACHE=${pubCache}`, "LANG=en_US.UTF-8"];
69
+ }
70
+ /**
71
+ * Fills the org's offline package cache from a project's lock, then proves it. The lock is resolved online once, as
72
+ * the build user, into the org's pub cache. A fresh workspace must then resolve the same lock with `--offline`, from
73
+ * that cache alone. A regulated build runs with no route to pub.dev, so this is how its dependencies get there.
74
+ */
75
+ export async function warmOrgCache(opts, deps) {
76
+ const user = opts.user ?? BUILD_USER_NAME;
77
+ await requireBuildUser(user, deps);
78
+ const lockPath = join(opts.projectDir, "pubspec.lock");
79
+ const yamlPath = join(opts.projectDir, "pubspec.yaml");
80
+ if (!deps.exists(lockPath) || !deps.exists(yamlPath))
81
+ throw new Error(`the project directory needs both pubspec.yaml and pubspec.lock: ${opts.projectDir}`);
82
+ const packages = hostedPackagesFromLock(deps.readText(lockPath));
83
+ const orgCache = deps.orgCacheDir(opts.orgId);
84
+ const orgSdk = join(orgCache, "flutter-sdk");
85
+ const complete = deps.listDirs(orgSdk).filter((n) => deps.exists(join(orgSdk, n, CLONE_COMPLETE_MARKER)));
86
+ const clone = pickSdkClone(orgSdk, complete, opts.flutterSdk);
87
+ const flutter = join(clone, "bin", "flutter");
88
+ if (!deps.exists(flutter))
89
+ throw new Error(`no Flutter binary in ${clone}`);
90
+ const pubCache = join(orgCache, "pub");
91
+ deps.log(`==> Warming ${opts.orgId}'s pub cache for ${packages.length} hosted package(s), resolved as '${user}' with ${clone}`);
92
+ const stage = deps.stage(opts.projectDir, ["pubspec.yaml", "pubspec.lock"]);
93
+ const dirs = await deps.buildUserDirs(user);
94
+ const root = join(dirs.temp, `warm-${deps.randomId()}`);
95
+ const home = join(root, "home");
96
+ const tmp = join(root, "tmp");
97
+ const online = join(root, "online");
98
+ const offline = join(root, "offline");
99
+ try {
100
+ await deps.captureAsBuildUser(user, ["/bin/mkdir", "-p", home, tmp, online, offline]);
101
+ // Copied as the build user, because the build user is the one that must read the staging directory.
102
+ await deps.captureAsBuildUser(user, ["/bin/sh", "-c", 'cp "$1/pubspec.yaml" "$1/pubspec.lock" "$2/" && cp "$1/pubspec.yaml" "$1/pubspec.lock" "$3/"', "sh", stage, online, offline]);
103
+ // `env -i` clears the inherited environment, so every variable a pub step needs is listed explicitly. The
104
+ // directory is changed into in the shell, and then the real command replaces it.
105
+ const pubCommand = (dir, extra) => ["/usr/bin/env", "-i", ...pubEnv(home, tmp, clone, pubCache), "/bin/sh", "-c", 'cd "$1" && shift && exec "$@"', "sh", dir, flutter, "pub", "get", ...extra];
106
+ deps.log("==> Online: resolving the lock against the registry");
107
+ await deps.runAsBuildUser(user, pubCommand(online, []));
108
+ deps.log("==> Offline check: a fresh workspace must resolve from the cache alone");
109
+ const check = await deps.captureAsBuildUser(user, pubCommand(offline, ["--offline"]));
110
+ if (!check.includes("Got dependencies"))
111
+ throw new Error("the offline check did not resolve the lock from the cache; the warm-up is incomplete");
112
+ deps.log(`==> Warmed and verified offline: ${packages.length} hosted package(s) in ${pubCache}`);
113
+ return { packages: packages.length, clone };
114
+ }
115
+ finally {
116
+ await deps.captureAsBuildUser(user, ["/bin/rm", "-rf", "--", root]).catch(() => undefined);
117
+ deps.unstage(stage);
118
+ }
119
+ }
120
+ /** The real seam: the agent's own cache and build-user helpers, the terminal, and a staging directory. */
121
+ export function realWarmCacheDeps() {
122
+ return {
123
+ readText: (p) => readFileSync(p, "utf8"),
124
+ exists: (p) => existsSync(p),
125
+ listDirs: (p) => (existsSync(p) ? readdirSync(p).filter((n) => statSync(join(p, n)).isDirectory()) : []),
126
+ orgCacheDir: (orgId) => join(cacheRootDir(), orgId),
127
+ checkBuildUser: (user) => detectBuildUser(user),
128
+ buildUserDirs: (user) => buildUserDarwinDirs(user, realBuildUserProbeDeps),
129
+ stage: (projectDir, names) => {
130
+ // The staged copy can hold signing values (gradle.properties), so it is never world-readable: the directory
131
+ // stays 0700 and only the build user gets read access, through an ACL that new files and subdirectories inherit.
132
+ // /private/tmp is traversable by everyone, so the directory's own mode is the only gate.
133
+ const dir = mkdtempSync("/private/tmp/appforge-warm-");
134
+ execFileSync("/bin/chmod", ["+a", `${BUILD_USER_NAME} allow list,search,read,file_inherit,directory_inherit`, dir]);
135
+ for (const name of names) {
136
+ const target = join(dir, name);
137
+ mkdirSync(dirname(target), { recursive: true, mode: 0o700 });
138
+ copyFileSync(join(projectDir, name), target);
139
+ chmodSync(target, 0o600);
140
+ }
141
+ return dir;
142
+ },
143
+ unstage: (dir) => rmSync(dir, { recursive: true, force: true }),
144
+ runAsBuildUser: (user, argv) => new Promise((resolve, reject) => {
145
+ const child = spawn("/usr/bin/sudo", ["-n", "-u", user, "--", "/usr/bin/sandbox-exec", "-p", "(version 1)(allow default)", ...argv], { stdio: "inherit" });
146
+ child.on("error", reject);
147
+ child.on("exit", (code) => (code === 0 ? resolve() : reject(new Error(`the step exited with code ${code}`))));
148
+ }),
149
+ captureAsBuildUser: (user, argv) => realBuildUserProbeDeps.runAsBuildUser(user, argv),
150
+ randomId: () => Math.random().toString(36).slice(2, 10),
151
+ log: (l) => console.log(l),
152
+ };
153
+ }
154
+ // ---------------------------------------------------------------------------------------------------------------------
155
+ // Gradle. Same shape as the pub flow: resolve online as the build user into the org's GRADLE_USER_HOME, then resolve a
156
+ // fresh copy offline. Unlike pub, the Gradle wrapper has to run, so the project's build logic is staged, not just a lock.
157
+ // ---------------------------------------------------------------------------------------------------------------------
158
+ /** Directories that never hold build logic: generated output, Gradle's own project cache, VCS and editor state. */
159
+ const GRADLE_SKIP_DIRS = new Set(["build", ".gradle", ".git", ".idea", "node_modules"]);
160
+ /** The project-relative paths a Gradle dependency resolution needs, and nothing else. Included: the wrapper, the root
161
+ * `gradle/` directory (wrapper properties and jar, version catalogs), every settings/build/init script, gradle.properties,
162
+ * any `*.versions.toml`, and `buildSrc/` (its sources compile during configuration). Left out, on purpose: app source,
163
+ * keystores, `key.properties`, `local.properties` and `google-services.json`. Staging copies these into a directory the
164
+ * build user can read, so the list stays narrow. A project that needs something left out (an included build's convention
165
+ * plugin sources, say) fails the online step loudly instead of passing. */
166
+ export function gradleBuildFiles(relPaths) {
167
+ return relPaths
168
+ .filter((p) => {
169
+ if (p.split("/").some((seg) => GRADLE_SKIP_DIRS.has(seg)))
170
+ return false;
171
+ const base = p.slice(p.lastIndexOf("/") + 1);
172
+ if (p === "gradlew")
173
+ return true;
174
+ if (p.startsWith("gradle/") || p.startsWith("buildSrc/"))
175
+ return true;
176
+ if (/^(settings|build|init)\.gradle(\.kts)?$/.test(base))
177
+ return true;
178
+ if (base === "gradle.properties" || base.endsWith(".versions.toml"))
179
+ return true;
180
+ return false;
181
+ })
182
+ .sort();
183
+ }
184
+ /** The `dependencies` report exits 0 even when a dependency did not resolve (the line ends in FAILED), so the warm-up
185
+ * reads the report for those lines. Returns them, empty when the report is clean. */
186
+ export function unresolvedDependencyLines(report) {
187
+ return report.split("\n").filter((line) => /\bFAILED\s*$/.test(line) || /could not (be )?resolve/i.test(line));
188
+ }
189
+ /** The Gradle step's arguments, after the wrapper. `dependencies` resolves every configuration the project declares. */
190
+ const GRADLE_STEP_ARGS = ["--no-daemon", "--console=plain", "dependencies"];
191
+ /** Reads the environment from stdin, then runs the rest of argv inside the directory named by $1. */
192
+ const GRADLE_STEP_SHELL = `. /dev/stdin; cd "$1" && shift && exec "$@"`;
193
+ /** The environment one Gradle step gets: the agent's own build-step environment (agent env.ts, buildSandboxEnv), with
194
+ * this warm-up's workspace as HOME and TMPDIR and the org's cache, so GRADLE_USER_HOME is the directory builds use. Only
195
+ * allow-listed host variables come through; no build secret is present. */
196
+ export function gradleStepEnv(i) {
197
+ return buildSandboxEnv({
198
+ agentEnv: i.agentEnv,
199
+ realHome: i.realHome,
200
+ buildHome: i.buildHome,
201
+ tmpDir: i.tmpDir,
202
+ orgCacheDir: i.orgCacheDir,
203
+ loginToolchainEnv: i.loginToolchainEnv,
204
+ buildVars: {},
205
+ });
206
+ }
207
+ /**
208
+ * Fills the org's Gradle cache from an Android project's build logic, then proves it. The project's wrapper resolves every
209
+ * dependency once, online, as the build user, into the org's GRADLE_USER_HOME. A fresh workspace must then resolve the same
210
+ * project with `--offline`, from that cache alone, and any unresolved dependency fails the warm-up. A regulated build has no
211
+ * route to the repositories, so this is how its Gradle dependencies get there.
212
+ */
213
+ export async function warmGradleCache(opts, deps) {
214
+ const user = opts.user ?? BUILD_USER_NAME;
215
+ await requireBuildUser(user, deps);
216
+ const files = gradleBuildFiles(deps.listProjectFiles(opts.projectDir));
217
+ // The wrapper, not a system `gradle`: the wrapper's own Gradle version is the one a build downloads and caches, so
218
+ // resolving with any other version would fill a cache the builds never read.
219
+ if (!files.includes("gradlew")) {
220
+ throw new Error(`the Gradle project needs its wrapper (gradlew) at its root, so the warm-up uses the Gradle version the builds use: ${opts.projectDir}`);
221
+ }
222
+ if (!["settings.gradle", "settings.gradle.kts", "build.gradle", "build.gradle.kts"].some((n) => files.includes(n))) {
223
+ throw new Error(`no settings.gradle(.kts) or build.gradle(.kts) at the root of ${opts.projectDir}`);
224
+ }
225
+ const orgCache = deps.orgCacheDir(opts.orgId);
226
+ const gradleHome = join(orgCache, "gradle");
227
+ deps.log(`==> Warming ${opts.orgId}'s Gradle cache (${gradleHome}) from ${files.length} build file(s), resolved as '${user}'`);
228
+ const stage = deps.stage(opts.projectDir, files);
229
+ let root;
230
+ try {
231
+ const dirs = await deps.buildUserDirs(user);
232
+ root = join(dirs.temp, `warm-gradle-${deps.randomId()}`);
233
+ const home = join(root, "home");
234
+ const tmp = join(root, "tmp");
235
+ const online = join(root, "online");
236
+ const offline = join(root, "offline");
237
+ await deps.captureAsBuildUser(user, ["/bin/mkdir", "-p", home, tmp, online, offline]);
238
+ // Copied as the build user, which is the one that must read the staging directory.
239
+ await deps.captureAsBuildUser(user, ["/bin/sh", "-c", 'cp -R "$1/." "$2/" && cp -R "$1/." "$3/"', "sh", stage, online, offline]);
240
+ const env = gradleStepEnv({
241
+ agentEnv: deps.agentEnv(),
242
+ realHome: deps.realHome(),
243
+ loginToolchainEnv: await deps.loginToolchainEnv(),
244
+ buildHome: home,
245
+ tmpDir: tmp,
246
+ orgCacheDir: orgCache,
247
+ });
248
+ const stdin = envSourceScript(env);
249
+ const step = (dir, extra) => ["/bin/sh", "-c", GRADLE_STEP_SHELL, "sh", dir, "/bin/sh", "gradlew", ...extra, ...GRADLE_STEP_ARGS];
250
+ deps.log("==> Online: resolving every dependency against the repositories");
251
+ const onlineReport = await deps.runStepAsBuildUser(user, step(online, []), stdin);
252
+ const unresolvedOnline = unresolvedDependencyLines(onlineReport);
253
+ if (unresolvedOnline.length > 0)
254
+ throw new Error(`the online resolution left dependencies unresolved; the warm-up is incomplete: ${unresolvedOnline.slice(0, 5).join(" | ")}`);
255
+ deps.log("==> Offline check: a fresh workspace must resolve from the cache alone");
256
+ const offlineReport = await deps.runStepAsBuildUser(user, step(offline, ["--offline"]), stdin);
257
+ const unresolvedOffline = unresolvedDependencyLines(offlineReport);
258
+ if (unresolvedOffline.length > 0) {
259
+ throw new Error(`the offline check did not resolve every dependency from the cache; the warm-up is incomplete: ${unresolvedOffline.slice(0, 5).join(" | ")}`);
260
+ }
261
+ deps.log(`==> Warmed and verified offline: ${files.length} build file(s), Gradle cache ${gradleHome}`);
262
+ return { buildFiles: files.length, gradleHome };
263
+ }
264
+ finally {
265
+ if (root !== undefined)
266
+ await deps.captureAsBuildUser(user, ["/bin/rm", "-rf", "--", root]).catch(() => undefined);
267
+ deps.unstage(stage);
268
+ }
269
+ }
270
+ /** The real Gradle seams: the pub flow's real parts, plus the project walk, the streaming step runner and the operator's
271
+ * environment. */
272
+ export function realWarmGradleDeps() {
273
+ const base = realWarmCacheDeps();
274
+ return {
275
+ checkBuildUser: base.checkBuildUser,
276
+ buildUserDirs: base.buildUserDirs,
277
+ stage: base.stage,
278
+ unstage: base.unstage,
279
+ captureAsBuildUser: base.captureAsBuildUser,
280
+ orgCacheDir: base.orgCacheDir,
281
+ randomId: base.randomId,
282
+ log: base.log,
283
+ listProjectFiles: listProjectFilesUnder,
284
+ runStepAsBuildUser: (user, argv, stdin) => new Promise((resolve, reject) => {
285
+ const child = spawn("/usr/bin/sudo", ["-n", "-u", user, "--", "/usr/bin/sandbox-exec", "-p", "(version 1)(allow default)", ...argv], {
286
+ stdio: ["pipe", "pipe", "pipe"],
287
+ });
288
+ let out = "";
289
+ child.stdout.on("data", (d) => {
290
+ out += d.toString("utf8");
291
+ process.stdout.write(d);
292
+ });
293
+ child.stderr.on("data", (d) => process.stderr.write(d));
294
+ // A step that exits before reading its environment closes the pipe. Its exit status reports that, so the write is not an error here.
295
+ child.stdin.on("error", () => undefined);
296
+ child.stdin.end(stdin);
297
+ child.on("error", reject);
298
+ child.on("close", (code) => (code === 0 ? resolve(out) : reject(new Error(`the step exited with code ${code}`))));
299
+ }),
300
+ agentEnv: () => process.env,
301
+ realHome: () => homedir(),
302
+ loginToolchainEnv: () => loginShellToolchainEnv(homedir()),
303
+ };
304
+ }
305
+ /** Every file path under `root`, relative and with forward slashes, skipping GRADLE_SKIP_DIRS and symlinks. */
306
+ export function listProjectFilesUnder(root, rel = "") {
307
+ const out = [];
308
+ for (const ent of readdirSync(join(root, rel), { withFileTypes: true })) {
309
+ const p = rel ? `${rel}/${ent.name}` : ent.name;
310
+ if (ent.isDirectory()) {
311
+ if (!GRADLE_SKIP_DIRS.has(ent.name))
312
+ out.push(...listProjectFilesUnder(root, p));
313
+ }
314
+ else if (ent.isFile()) {
315
+ out.push(p);
316
+ }
317
+ }
318
+ return out;
319
+ }
320
+ //# sourceMappingURL=warm-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-cache.js","sourceRoot":"","sources":["../../src/lib/warm-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import "../test-support/home-sandbox.js";
2
+ //# sourceMappingURL=warm-cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-cache.test.d.ts","sourceRoot":"","sources":["../../src/lib/warm-cache.test.ts"],"names":[],"mappings":"AACA,OAAO,iCAAiC,CAAC"}
@@ -0,0 +1,277 @@
1
+ // Must stay the FIRST import — see ../test-support/home-sandbox.ts.
2
+ import "../test-support/home-sandbox.js";
3
+ import { test } from "node:test";
4
+ import assert from "node:assert/strict";
5
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
6
+ import { tmpdir } from "node:os";
7
+ import { join } from "node:path";
8
+ import { gradleBuildFiles, listProjectFilesUnder, hostedPackagesFromLock, pickSdkClone, unresolvedDependencyLines, warmGradleCache, warmOrgCache, } from "./warm-cache.js";
9
+ const LOCK = `# Generated by pub
10
+ packages:
11
+ flutter_lints:
12
+ dependency: "direct dev"
13
+ description:
14
+ name: flutter_lints
15
+ sha256: "abc"
16
+ url: "https://pub.dev"
17
+ source: hosted
18
+ version: "6.0.0"
19
+ my_local:
20
+ dependency: "direct main"
21
+ description:
22
+ path: "../my_local"
23
+ relative: true
24
+ source: path
25
+ version: "0.0.1"
26
+ flutter:
27
+ dependency: "direct main"
28
+ description: flutter
29
+ source: sdk
30
+ version: "0.0.0"
31
+ sdks:
32
+ dart: ">=3.13.1 <4.0.0"
33
+ `;
34
+ test("hostedPackagesFromLock lists only the hosted packages, as name-version, and skips path and sdk packages", () => {
35
+ assert.deepEqual(hostedPackagesFromLock(LOCK), ["flutter_lints-6.0.0"]);
36
+ assert.deepEqual(hostedPackagesFromLock(LOCK.replace(/\n/g, "\r\n")), ["flutter_lints-6.0.0"], "a CRLF lock parses the same");
37
+ assert.deepEqual(hostedPackagesFromLock(""), []);
38
+ });
39
+ test("pickSdkClone uses the one complete clone, takes an explicit name or path, and refuses to guess among several", () => {
40
+ assert.equal(pickSdkClone("/o/flutter-sdk", ["abc"]), "/o/flutter-sdk/abc");
41
+ assert.equal(pickSdkClone("/o/flutter-sdk", ["abc", "def"], "def"), "/o/flutter-sdk/def");
42
+ assert.equal(pickSdkClone("/o/flutter-sdk", [], "/elsewhere/clone"), "/elsewhere/clone");
43
+ assert.throws(() => pickSdkClone("/o/flutter-sdk", []), /no cached Flutter SDK clone/);
44
+ assert.throws(() => pickSdkClone("/o/flutter-sdk", ["abc", "def"]), /2 cached Flutter SDK clones/);
45
+ });
46
+ function fakeDeps(over = {}) {
47
+ const calls = [];
48
+ const logs = [];
49
+ const files = new Map([
50
+ ["/proj/pubspec.yaml", "name: app\n"],
51
+ ["/proj/pubspec.lock", LOCK],
52
+ ["/org/flutter-sdk/abc/bin/flutter", ""],
53
+ ["/org/flutter-sdk/abc/.appforge-clone-complete", "ok\n"],
54
+ ]);
55
+ const deps = {
56
+ readText: (p) => {
57
+ const t = files.get(p);
58
+ if (t === undefined)
59
+ throw new Error(`no ${p}`);
60
+ return t;
61
+ },
62
+ exists: (p) => files.has(p),
63
+ listDirs: (p) => (p === "/org/flutter-sdk" ? ["abc"] : []),
64
+ orgCacheDir: () => "/org",
65
+ checkBuildUser: async () => ({ installed: true, reason: "ok" }),
66
+ buildUserDirs: async () => ({ temp: "/bu/T", cache: "/bu/C" }),
67
+ stage: () => "/stage",
68
+ unstage: () => {
69
+ calls.push({ kind: "unstage" });
70
+ },
71
+ runAsBuildUser: async (user, argv) => {
72
+ calls.push({ kind: "online", user, argv });
73
+ },
74
+ captureAsBuildUser: async (user, argv) => {
75
+ calls.push({ kind: "capture", user, argv });
76
+ return argv.includes("--offline") ? "Resolving dependencies...\nGot dependencies!\n" : "";
77
+ },
78
+ randomId: () => "r1",
79
+ log: (l) => logs.push(l),
80
+ ...over,
81
+ };
82
+ return { deps, calls, logs };
83
+ }
84
+ test("warmOrgCache resolves the lock online as the build user into the org's pub cache, verifies it offline in a fresh workspace, and cleans up", async () => {
85
+ const { deps, calls } = fakeDeps();
86
+ const result = await warmOrgCache({ orgId: "org1", projectDir: "/proj" }, deps);
87
+ assert.deepEqual(result, { packages: 1, clone: "/org/flutter-sdk/abc" });
88
+ const online = calls.find((c) => c.kind === "online");
89
+ assert.equal(online.user, "_appforgebuild");
90
+ assert.ok(online.argv.includes("PUB_CACHE=/org/pub"), "the org's own pub cache, not the operator's");
91
+ assert.ok(!online.argv.includes("--offline"), "the online pass is the one allowed to reach the registry");
92
+ const offline = calls.find((c) => c.kind === "capture" && c.argv.includes("--offline"));
93
+ assert.match(offline.argv.join(" "), /\/warm-r1\/offline/, "the offline check runs in a fresh workspace, not the one the online pass warmed");
94
+ assert.ok(calls.some((c) => c.kind === "capture" && c.argv.includes("/bin/rm")), "the workspace is removed");
95
+ assert.equal(calls.at(-1)?.kind, "unstage", "and the staging copy is removed last");
96
+ });
97
+ test("warmOrgCache refuses, and touches nothing, when the build user is not ready on this Mac", async () => {
98
+ const { deps, calls } = fakeDeps({ checkBuildUser: async () => ({ installed: false, reason: "no account" }) });
99
+ await assert.rejects(warmOrgCache({ orgId: "org1", projectDir: "/proj" }, deps), /not ready on this Mac \(no account\); run 'appforge-admin agents install-build-user' first/);
100
+ assert.equal(calls.length, 0);
101
+ });
102
+ test("warmOrgCache fails loudly when the offline check cannot resolve from the cache, and still removes the workspace and the staging copy", async () => {
103
+ const { deps, calls } = fakeDeps({
104
+ captureAsBuildUser: async (user, argv) => {
105
+ calls.push({ kind: "capture", user, argv });
106
+ return argv.includes("--offline") ? "Because the app depends on flutter_lints any which doesn't exist" : "";
107
+ },
108
+ });
109
+ await assert.rejects(warmOrgCache({ orgId: "org1", projectDir: "/proj" }, deps), /did not resolve the lock from the cache/);
110
+ assert.ok(calls.some((c) => c.argv?.includes("/bin/rm")), "the workspace is removed even on failure");
111
+ assert.equal(calls.at(-1)?.kind, "unstage");
112
+ });
113
+ test("warmOrgCache needs both pubspec.yaml and pubspec.lock in the project", async () => {
114
+ const { deps } = fakeDeps({ exists: () => false });
115
+ await assert.rejects(warmOrgCache({ orgId: "org1", projectDir: "/proj" }, deps), /needs both pubspec\.yaml and pubspec\.lock/);
116
+ });
117
+ // ---- Gradle ---------------------------------------------------------------------------------------------------------
118
+ const GRADLE_PROJECT = [
119
+ "settings.gradle.kts",
120
+ "build.gradle.kts",
121
+ "gradle.properties",
122
+ "gradlew",
123
+ "gradle/wrapper/gradle-wrapper.jar",
124
+ "gradle/wrapper/gradle-wrapper.properties",
125
+ "gradle/libs.versions.toml",
126
+ "app/build.gradle.kts",
127
+ "buildSrc/src/main/kotlin/Conventions.kt",
128
+ "app/src/main/kotlin/com/example/MainActivity.kt",
129
+ "app/google-services.json",
130
+ "android/key.properties",
131
+ "upload-keystore.jks",
132
+ "local.properties",
133
+ "app/build/outputs/app-debug.apk",
134
+ ".gradle/8.7/fileHashes.bin",
135
+ ];
136
+ test("gradleBuildFiles keeps the build logic and the wrapper, and leaves out app source and local secrets", () => {
137
+ assert.deepEqual(gradleBuildFiles(GRADLE_PROJECT), [
138
+ "app/build.gradle.kts",
139
+ "build.gradle.kts",
140
+ "buildSrc/src/main/kotlin/Conventions.kt",
141
+ "gradle.properties",
142
+ "gradle/libs.versions.toml",
143
+ "gradle/wrapper/gradle-wrapper.jar",
144
+ "gradle/wrapper/gradle-wrapper.properties",
145
+ "gradlew",
146
+ "settings.gradle.kts",
147
+ ]);
148
+ });
149
+ test("unresolvedDependencyLines reads the FAILED lines of a dependencies report, which exits 0 even when a dependency did not resolve", () => {
150
+ const report = [
151
+ "debugRuntimeClasspath - Runtime classpath of compilation 'debug'.",
152
+ "+--- androidx.core:core:1.13.1",
153
+ "\\--- com.example:missing:2.0 FAILED",
154
+ "",
155
+ "BUILD SUCCESSFUL in 4s",
156
+ ].join("\n");
157
+ assert.deepEqual(unresolvedDependencyLines(report), ["\\--- com.example:missing:2.0 FAILED"]);
158
+ assert.deepEqual(unresolvedDependencyLines("+--- androidx.core:core:1.13.1\nBUILD SUCCESSFUL\n"), []);
159
+ });
160
+ function fakeGradleDeps(over = {}) {
161
+ const calls = [];
162
+ const logs = [];
163
+ const deps = {
164
+ listProjectFiles: () => GRADLE_PROJECT,
165
+ checkBuildUser: async () => ({ installed: true, reason: "ok" }),
166
+ buildUserDirs: async () => ({ temp: "/bu/T", cache: "/bu/C" }),
167
+ orgCacheDir: () => "/org",
168
+ stage: (projectDir, names) => {
169
+ calls.push({ kind: "stage", argv: [projectDir, ...names] });
170
+ return "/stage";
171
+ },
172
+ unstage: () => {
173
+ calls.push({ kind: "unstage" });
174
+ },
175
+ captureAsBuildUser: async (user, argv) => {
176
+ calls.push({ kind: "capture", user, argv });
177
+ return "";
178
+ },
179
+ runStepAsBuildUser: async (user, argv, stdin) => {
180
+ calls.push({ kind: "step", user, argv, stdin });
181
+ return "+--- androidx.core:core:1.13.1\nBUILD SUCCESSFUL\n";
182
+ },
183
+ agentEnv: () => ({ PATH: "/usr/bin:/bin", JAVA_HOME: "/jdk", GITHUB_TOKEN: "ghp_secret" }),
184
+ realHome: () => "/Users/op",
185
+ loginToolchainEnv: async () => ({}),
186
+ randomId: () => "r1",
187
+ log: (l) => logs.push(l),
188
+ ...over,
189
+ };
190
+ return { deps, calls, logs };
191
+ }
192
+ test("warmGradleCache resolves the project online as the build user into the org's GRADLE_USER_HOME, verifies it offline in a fresh workspace, and cleans up", async () => {
193
+ const { deps, calls } = fakeGradleDeps();
194
+ const result = await warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps);
195
+ assert.deepEqual(result, { buildFiles: gradleBuildFiles(GRADLE_PROJECT).length, gradleHome: "/org/gradle" });
196
+ const steps = calls.filter((c) => c.kind === "step");
197
+ assert.equal(steps.length, 2);
198
+ const [online, offline] = steps;
199
+ assert.equal(online.user, "_appforgebuild");
200
+ assert.ok(online.argv.includes("gradlew") && online.argv.includes("dependencies"), "the project's own wrapper runs the dependency resolution");
201
+ assert.ok(online.argv.includes("--no-daemon"), "no daemon is left running in the org's cache");
202
+ assert.ok(!online.argv.includes("--offline"), "the online pass is the one allowed to reach the repositories");
203
+ assert.match(online.argv.join(" "), /\/warm-gradle-r1\/online/, "the online pass runs in its own workspace");
204
+ assert.ok(offline.argv.includes("--offline"), "the offline check is --offline");
205
+ assert.match(offline.argv.join(" "), /\/warm-gradle-r1\/offline/, "the offline check runs in a fresh workspace, not the one the online pass warmed");
206
+ // The step environment is the agent's own build-step environment: GRADLE_USER_HOME is the org's, HOME is the workspace's,
207
+ // allow-listed host variables come through, and nothing else from the operator's environment does.
208
+ for (const step of [online, offline]) {
209
+ assert.ok(step.stdin.includes("export GRADLE_USER_HOME='/org/gradle'\n"), "GRADLE_USER_HOME is the directory the agent points builds at");
210
+ assert.ok(step.stdin.includes("export HOME='/bu/T/warm-gradle-r1/home'\n"), "HOME is this warm-up's own workspace, not the operator's");
211
+ assert.ok(step.stdin.includes("export JAVA_HOME='/jdk'\n"), "toolchain variables come through");
212
+ assert.ok(!step.stdin.includes("ghp_secret"), "no operator secret reaches a build step");
213
+ }
214
+ assert.ok(calls.some((c) => c.kind === "capture" && c.argv.includes("/bin/rm")), "the workspace is removed");
215
+ assert.equal(calls.at(-1)?.kind, "unstage", "and the staging copy is removed last");
216
+ });
217
+ test("warmGradleCache stages only the build logic, never the app source or local secrets", async () => {
218
+ const { deps, calls } = fakeGradleDeps();
219
+ await warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps);
220
+ const stage = calls.find((c) => c.kind === "stage");
221
+ assert.deepEqual(stage.argv, ["/proj", ...gradleBuildFiles(GRADLE_PROJECT)]);
222
+ assert.ok(!stage.argv.some((p) => p.includes("MainActivity") || p.includes("keystore") || p.includes("local.properties")));
223
+ });
224
+ test("warmGradleCache refuses, and touches nothing, when the build user is not ready on this Mac", async () => {
225
+ const { deps, calls } = fakeGradleDeps({ checkBuildUser: async () => ({ installed: false, reason: "no account" }) });
226
+ await assert.rejects(warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps), /not ready on this Mac \(no account\)/);
227
+ assert.equal(calls.length, 0);
228
+ });
229
+ test("warmGradleCache refuses a project with no wrapper, before staging or running anything", async () => {
230
+ const { deps, calls } = fakeGradleDeps({ listProjectFiles: () => ["settings.gradle", "build.gradle", "app/build.gradle"] });
231
+ await assert.rejects(warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps), /needs its wrapper \(gradlew\) at its root/);
232
+ assert.equal(calls.length, 0);
233
+ });
234
+ test("warmGradleCache refuses a directory with no Gradle settings or build script at its root", async () => {
235
+ const { deps, calls } = fakeGradleDeps({ listProjectFiles: () => ["gradlew", "app/build.gradle"] });
236
+ await assert.rejects(warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps), /no settings\.gradle\(\.kts\) or build\.gradle\(\.kts\) at the root/);
237
+ assert.equal(calls.length, 0);
238
+ });
239
+ test("warmGradleCache fails loudly when the offline check leaves a dependency unresolved, and still removes the workspace and the staging copy", async () => {
240
+ const { deps, calls } = fakeGradleDeps({
241
+ runStepAsBuildUser: async (user, argv, stdin) => {
242
+ calls.push({ kind: "step", user, argv, stdin });
243
+ return argv.includes("--offline") ? "\\--- com.example:missing:2.0 FAILED\nBUILD SUCCESSFUL\n" : "BUILD SUCCESSFUL\n";
244
+ },
245
+ });
246
+ await assert.rejects(warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps), /did not resolve every dependency from the cache.*com\.example:missing/);
247
+ assert.ok(calls.some((c) => c.kind === "capture" && c.argv.includes("/bin/rm")), "the workspace is removed even on failure");
248
+ assert.equal(calls.at(-1)?.kind, "unstage");
249
+ });
250
+ test("warmGradleCache fails when the online resolution cannot finish, and still removes the workspace and the staging copy", async () => {
251
+ const { deps, calls } = fakeGradleDeps({
252
+ runStepAsBuildUser: async (user, argv, stdin) => {
253
+ calls.push({ kind: "step", user, argv, stdin });
254
+ throw new Error("the step exited with code 1");
255
+ },
256
+ });
257
+ await assert.rejects(warmGradleCache({ orgId: "org1", projectDir: "/proj" }, deps), /exited with code 1/);
258
+ assert.ok(calls.some((c) => c.kind === "capture" && c.argv.includes("/bin/rm")));
259
+ assert.equal(calls.at(-1)?.kind, "unstage");
260
+ });
261
+ test("listProjectFilesUnder walks a real project tree, skipping generated and cache directories", () => {
262
+ const root = mkdtempSync(join(tmpdir(), "warm-gradle-walk-"));
263
+ for (const dir of ["app/src/main", "build/outputs", ".gradle/8.7", "gradle/wrapper", "buildSrc/src"])
264
+ mkdirSync(join(root, dir), { recursive: true });
265
+ for (const file of ["settings.gradle.kts", "gradlew", "app/build.gradle.kts", "app/src/main/Main.kt", "build/outputs/app.apk", ".gradle/8.7/x.bin", "gradle/wrapper/gradle-wrapper.jar", "buildSrc/src/C.kt"]) {
266
+ writeFileSync(join(root, file), "x");
267
+ }
268
+ assert.deepEqual(listProjectFilesUnder(root).sort(), [
269
+ "app/build.gradle.kts",
270
+ "app/src/main/Main.kt",
271
+ "buildSrc/src/C.kt",
272
+ "gradle/wrapper/gradle-wrapper.jar",
273
+ "gradlew",
274
+ "settings.gradle.kts",
275
+ ]);
276
+ });
277
+ //# sourceMappingURL=warm-cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-cache.test.js","sourceRoot":"","sources":["../../src/lib/warm-cache.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appforge-ci/admin-cli",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -15,8 +15,8 @@
15
15
  "dependencies": {
16
16
  "chalk": "^5.3.0",
17
17
  "commander": "^12.1.0",
18
- "@appforge-ci/agent": "0.3.8",
19
- "@appforge-ci/core": "0.3.8"
18
+ "@appforge-ci/agent": "0.3.10",
19
+ "@appforge-ci/core": "0.3.10"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^20.16.5",