looply-cli 0.5.14 → 0.5.18

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,51 @@
1
+ import { type EasRunner, type ReleaseDeps, type ReleaseExec } from './expo-release';
2
+ import { type GitExec } from './git-driver';
3
+ import type { MachineRunSlots } from './machine-run-slots';
4
+ import type { ServerClient } from './server-client';
5
+ /**
6
+ * THE DAEMON'S HANDLE ON APP RELEASES: one object per project, so `daemon-cmd`
7
+ * gains one call beside `branchDeliverer.advance()` and nothing else.
8
+ *
9
+ * `advance()` is bounded and never waits for a release: it lists this
10
+ * project's open releases and, when nothing is already in hand, starts ONE
11
+ * step of the oldest actionable one in the background — plan it, start it,
12
+ * or follow its builds — and reports what happened. A plan takes minutes
13
+ * (a clean install and the full suite); a build takes longer; the five-minute
14
+ * cadence keeps beating meanwhile.
15
+ *
16
+ * `LOOPLY_EAS_DRY_RUN=1` on the machine makes every release a dry run: plans
17
+ * are made and reported, and nothing is ever published.
18
+ */
19
+ export interface AppReleaser {
20
+ advance(): Promise<void>;
21
+ /** Resolves when the step in hand (if any) is done. Tests and shutdown. */
22
+ idle(): Promise<void>;
23
+ }
24
+ /** The Expo token on this machine: EXPO_TOKEN, else `~/.looply/secrets/expo-token`. Never logged. */
25
+ export declare function machineExpoToken(env?: NodeJS.ProcessEnv, home?: string): string | null;
26
+ export declare function makeAppReleaser(opts: {
27
+ cwd: string;
28
+ stateDir: string;
29
+ baseBranch?: string;
30
+ client: Pick<ServerClient, 'openAppReleases' | 'reportAppRelease'>;
31
+ projectId: string;
32
+ workRoot: string;
33
+ log(line: string): void;
34
+ machineSlots?: Pick<MachineRunSlots, 'claim' | 'bind' | 'release' | 'inUse'>;
35
+ publishBranch?: ReleaseDeps['publishBranch'];
36
+ /** Tests: fakes. */
37
+ eas?: EasRunner;
38
+ exec?: ReleaseExec;
39
+ git?: GitExec;
40
+ gitAt?: (dir: string) => GitExec;
41
+ expoToken?: () => string | null;
42
+ now?: () => number;
43
+ env?: NodeJS.ProcessEnv;
44
+ }): AppReleaser;
45
+ /**
46
+ * Push a release's version-bump branch to origin and open its pull request,
47
+ * under the same hard rules as every delivery push (`delivery-rules.ts`:
48
+ * origin only, a `looply/run-*` branch only, never forced). A sentence back.
49
+ */
50
+ export declare function makeReleaseBranchPublisher(cwd: string, baseBranch: string | undefined, protectedBranches: readonly string[]): NonNullable<ReleaseDeps['publishBranch']>;
51
+ //# sourceMappingURL=expo-release-wiring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-release-wiring.d.ts","sourceRoot":"","sources":["../src/expo-release-wiring.ts"],"names":[],"mappings":"AAIA,OAAO,EASL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,2EAA2E;IAC3E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,GAAG,IAAI,CAa9G;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,kBAAkB,CAAC,CAAC;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;IAC7E,aAAa,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;IAC7C,oBAAoB;IACpB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,WAAW,CAqHd;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,iBAAiB,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAsBvK"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.machineExpoToken = machineExpoToken;
4
+ exports.makeAppReleaser = makeAppReleaser;
5
+ exports.makeReleaseBranchPublisher = makeReleaseBranchPublisher;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_os_1 = require("node:os");
8
+ const node_path_1 = require("node:path");
9
+ const expo_release_1 = require("./expo-release");
10
+ const branch_delivery_1 = require("./branch-delivery");
11
+ const delivery_rules_1 = require("./delivery-rules");
12
+ const expo_release_rules_1 = require("./expo-release-rules");
13
+ const github_api_1 = require("./github-api");
14
+ const git_driver_1 = require("./git-driver");
15
+ /** The Expo token on this machine: EXPO_TOKEN, else `~/.looply/secrets/expo-token`. Never logged. */
16
+ function machineExpoToken(env = process.env, home = (0, node_os_1.homedir)()) {
17
+ const v = env['EXPO_TOKEN'];
18
+ if (typeof v === 'string' && v.trim() !== '')
19
+ return v.trim();
20
+ const file = (0, node_path_1.join)(home, '.looply', 'secrets', 'expo-token');
21
+ try {
22
+ if ((0, node_fs_1.existsSync)(file)) {
23
+ const t = (0, node_fs_1.readFileSync)(file, 'utf8').trim();
24
+ if (t !== '')
25
+ return t;
26
+ }
27
+ }
28
+ catch {
29
+ /* unreadable: missing */
30
+ }
31
+ return null;
32
+ }
33
+ function makeAppReleaser(opts) {
34
+ const env = opts.env ?? process.env;
35
+ const dry = env['LOOPLY_EAS_DRY_RUN'] === '1';
36
+ const eas = opts.eas ?? (dry ? (0, expo_release_1.dryRunEas)() : (0, expo_release_1.realEasRunner)(opts.exec ?? expo_release_1.nodeReleaseExec));
37
+ const token = opts.expoToken ?? (() => machineExpoToken(env));
38
+ const slots = opts.machineSlots;
39
+ const deps = {
40
+ repoDir: opts.cwd,
41
+ ...(opts.baseBranch === undefined ? {} : { baseBranch: opts.baseBranch }),
42
+ git: opts.git ?? (0, git_driver_1.nodeGitExec)(opts.cwd),
43
+ gitAt: opts.gitAt ?? ((dir) => (0, git_driver_1.nodeGitExec)(dir)),
44
+ exec: opts.exec ?? expo_release_1.nodeReleaseExec,
45
+ eas,
46
+ workRoot: opts.workRoot,
47
+ store: (0, expo_release_1.fileAppReleaseStore)(opts.stateDir),
48
+ othersRunning: async () => {
49
+ const n = slots?.inUse() ?? 0;
50
+ return n > 0 ? `${n} Looply run${n === 1 ? ' is' : 's are'} active on this machine` : null;
51
+ },
52
+ ...(slots === undefined
53
+ ? {}
54
+ : {
55
+ reserve: () => {
56
+ const key = `app-release:${opts.projectId}`;
57
+ const full = slots.claim(key);
58
+ if (full !== null)
59
+ return full;
60
+ slots.bind(key, process.pid);
61
+ return () => slots.release(key);
62
+ },
63
+ }),
64
+ expoToken: token,
65
+ ...(opts.publishBranch === undefined ? {} : { publishBranch: opts.publishBranch }),
66
+ log: (line) => opts.log((0, expo_release_rules_1.redact)(line, [token()])),
67
+ now: opts.now ?? (() => Date.now()),
68
+ };
69
+ let inHand = null;
70
+ const lastSaid = new Map();
71
+ const report = async (r, rep) => {
72
+ const clean = JSON.parse((0, expo_release_rules_1.redact)(JSON.stringify(rep), [token()]));
73
+ const key = JSON.stringify(clean);
74
+ if (lastSaid.get(r.id) === key)
75
+ return;
76
+ try {
77
+ await opts.client.reportAppRelease(opts.projectId, r.id, clean);
78
+ lastSaid.set(r.id, key);
79
+ }
80
+ catch (e) {
81
+ opts.log(`app-release ${r.id} : could not report ${clean.state} (${e.message})`);
82
+ }
83
+ };
84
+ /** Start it; an OTA says "releasing" first, so an interrupted one is known as such. */
85
+ const go = async (r, input, plan, approved) => {
86
+ if (plan.decision === 'ota' && !plan.dryRun && (plan.approvalReasons.length === 0 || approved))
87
+ await report(r, { state: 'releasing', plan });
88
+ return report(r, await (0, expo_release_1.startRelease)(deps, input, plan, approved));
89
+ };
90
+ const step = async (r) => {
91
+ const input = { id: r.id, title: r.title, tickets: r.tickets, settings: r.settings };
92
+ const local = deps.store.read().releases[r.id];
93
+ if (r.state === 'requested' || (r.state === 'planning' && local?.plan == null) || (r.state === 'planning' && r.plan === null)) {
94
+ await report(r, { state: 'planning' });
95
+ const out = await (0, expo_release_1.planRelease)(deps, input);
96
+ if (out.kind === 'wait')
97
+ return report(r, { state: 'planning', detail: out.detail });
98
+ if (out.kind === 'end') {
99
+ (0, expo_release_1.cleanup)(deps, r.id);
100
+ return report(r, { state: out.state, detail: out.detail, ...(out.plan ? { plan: out.plan } : {}) });
101
+ }
102
+ if (out.plan.dryRun) {
103
+ (0, expo_release_1.cleanup)(deps, r.id);
104
+ return report(r, { state: 'refused', plan: out.plan, detail: 'dry run: the plan is made and nothing was published (LOOPLY_EAS_DRY_RUN on this machine)' });
105
+ }
106
+ if (out.plan.approvalReasons.length > 0)
107
+ return report(r, { state: 'awaiting-approval', plan: out.plan });
108
+ await report(r, { state: 'planning', plan: out.plan });
109
+ return go(r, input, out.plan, false);
110
+ }
111
+ if (r.state === 'planning' && r.plan !== null) {
112
+ // Planned, needing no approval, and not yet started (a restart in between).
113
+ if (r.plan.approvalReasons.length > 0)
114
+ return report(r, { state: 'awaiting-approval', plan: r.plan });
115
+ return go(r, input, r.plan, false);
116
+ }
117
+ if (r.state === 'approved' && r.plan !== null) {
118
+ const approved = r.approval !== null && r.approval.planKey === r.plan.planKey;
119
+ return go(r, input, r.plan, approved);
120
+ }
121
+ if (r.state === 'releasing' && r.plan !== null && r.plan.decision === 'build') {
122
+ return report(r, await (0, expo_release_1.followRelease)(deps, input, r.plan));
123
+ }
124
+ if (r.state === 'releasing' && r.plan !== null && r.plan.decision === 'ota' && local?.platforms.length !== r.plan.platforms.length) {
125
+ // An OTA is one command; a release still "releasing" here was interrupted mid-command.
126
+ (0, expo_release_1.cleanup)(deps, r.id);
127
+ return report(r, { state: 'failed', plan: r.plan, detail: 'the OTA was interrupted (the machine restarted); check the channel in EAS before releasing again' });
128
+ }
129
+ };
130
+ return {
131
+ idle: () => inHand ?? Promise.resolve(),
132
+ async advance() {
133
+ if (inHand !== null)
134
+ return;
135
+ let open;
136
+ try {
137
+ open = (await opts.client.openAppReleases(opts.projectId)).releases;
138
+ }
139
+ catch {
140
+ return; // offline: next cadence
141
+ }
142
+ const next = [...open]
143
+ .filter((r) => ['requested', 'planning', 'approved', 'releasing'].includes(r.state))
144
+ .sort((a, b) => a.createdAt.localeCompare(b.createdAt))[0];
145
+ if (next === undefined)
146
+ return;
147
+ inHand = step(next)
148
+ .catch((e) => {
149
+ opts.log(`app-release ${next.id} : step failed (${(0, expo_release_rules_1.redact)(e.message, [token()])})`);
150
+ })
151
+ .finally(() => {
152
+ inHand = null;
153
+ });
154
+ },
155
+ };
156
+ }
157
+ /**
158
+ * Push a release's version-bump branch to origin and open its pull request,
159
+ * under the same hard rules as every delivery push (`delivery-rules.ts`:
160
+ * origin only, a `looply/run-*` branch only, never forced). A sentence back.
161
+ */
162
+ function makeReleaseBranchPublisher(cwd, baseBranch, protectedBranches) {
163
+ return async (branch, sha, title, body) => {
164
+ const git = (0, branch_delivery_1.nodeDeliveryGit)(cwd, baseBranch);
165
+ const url = await git.remoteUrl();
166
+ const base = await git.baseRef();
167
+ const refusal = (0, delivery_rules_1.pushRefusal)({ remote: delivery_rules_1.DELIVERY_REMOTE, remoteUrl: url, branch, base, protectedBranches });
168
+ if (refusal !== null)
169
+ return `the version bump stays on this machine: ${refusal}`;
170
+ const argv = (0, delivery_rules_1.deliveryPushArgv)(branch, sha);
171
+ const unsafe = (0, delivery_rules_1.unsafePushArgv)(argv);
172
+ if (unsafe !== null)
173
+ return `the version bump stays on this machine: ${unsafe}`;
174
+ const pushed = await git.push(argv);
175
+ if (!pushed.ok)
176
+ return `the version bump branch was not pushed: ${pushed.because}`;
177
+ const gh = url === null ? null : (0, delivery_rules_1.githubRepoOf)(url);
178
+ const t = gh === null ? null : await (0, github_api_1.githubToken)();
179
+ if (gh === null || t === null)
180
+ return `the version bump is on origin as ${branch}; open its pull request to keep the version`;
181
+ try {
182
+ const pr = await (0, github_api_1.makeGitHubApi)({ owner: gh.owner, repo: gh.repo, token: t.token }).createPull({ title, head: branch, base: (0, delivery_rules_1.shortBranch)(base ?? 'main'), body });
183
+ return `the version bump is pull request ${pr.url}; merge it so the next release starts from this version`;
184
+ }
185
+ catch (e) {
186
+ return `the version bump is on origin as ${branch}, but its pull request was not opened (${e.message})`;
187
+ }
188
+ };
189
+ }
190
+ //# sourceMappingURL=expo-release-wiring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-release-wiring.js","sourceRoot":"","sources":["../src/expo-release-wiring.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ import { type AppPlatform, type AppReleasePlan, type AppReleaseReport, type AppReleaseSettings, type PlatformStatus, type ReleaseTicket } from '@looply/core';
2
+ import type { GitExec } from './git-driver';
3
+ /**
4
+ * THE MACHINE'S APP RELEASE: plan it, then — approved or not needing it — run
5
+ * it and follow it until testers can have it.
6
+ *
7
+ * PLAN (publishes nothing):
8
+ * 1. a CLEAN checkout of origin's base branch, in its own folder;
9
+ * 2. a REAL node_modules from the lockfile (`npm ci`). Never a junction: a
10
+ * linked node_modules resolves native modules through another path and
11
+ * MOVES THE EXPO FINGERPRINT, so a plan made over one would OTA onto
12
+ * builds it does not match. Checked after the install, refused if linked;
13
+ * 3. the app's FULL jest suite, alone — no other Looply run of this
14
+ * repository at the same time, no path filter;
15
+ * 4. the runtime version per platform (`expo-updates runtimeversion:resolve`,
16
+ * which is the fingerprint under the `fingerprint` policy) and whether a
17
+ * finished EAS build on the build profile already has it;
18
+ * 5. OTA when every platform has such a build and OTA is allowed; else a
19
+ * store test build. The next version, release notes, approval reasons.
20
+ *
21
+ * RUN: `eas update` to the channel; or a version-bump commit on a
22
+ * `looply/run-release-*` branch, `eas build --no-wait`, followed with
23
+ * `eas build:view`, then `eas submit` (TestFlight / the Play track the
24
+ * eas.json submit profile names, checked). Every argv passes
25
+ * `unsafeEasArgv` first (expo-release-rules.ts).
26
+ */
27
+ export interface ExecResult {
28
+ code: number;
29
+ stdout: string;
30
+ stderr: string;
31
+ }
32
+ export type ReleaseExec = (bin: string, args: readonly string[], o: {
33
+ cwd: string;
34
+ env?: Record<string, string>;
35
+ timeoutMs: number;
36
+ }) => Promise<ExecResult>;
37
+ /** Runs `eas`. The dry-run one records and answers; it never runs anything. */
38
+ export interface EasRunner {
39
+ readonly dryRun: boolean;
40
+ run(argv: readonly string[], o: {
41
+ cwd: string;
42
+ env: Record<string, string>;
43
+ }): Promise<ExecResult>;
44
+ }
45
+ /** iOS: TestFlight processing after EAS's upload; Apple says nothing to EAS, so a window is waited out. */
46
+ export declare const IOS_PROCESSING_MS: number;
47
+ export declare const INSTALL_TIMEOUT_MS: number;
48
+ export declare const JEST_TIMEOUT_MS: number;
49
+ export declare const RESOLVE_TIMEOUT_MS: number;
50
+ export declare const EAS_TIMEOUT_MS: number;
51
+ export declare const SUBMIT_TIMEOUT_MS: number;
52
+ export declare const APP_RELEASES_FILE = "app-releases.json";
53
+ export interface LocalRelease {
54
+ id: string;
55
+ checkoutDir: string | null;
56
+ plan: AppReleasePlan | null;
57
+ platforms: PlatformStatus[];
58
+ /** The version-bump branch, once committed. */
59
+ branch: string | null;
60
+ processingSince: Partial<Record<AppPlatform, number>>;
61
+ /** True while this process is doing something for it (never persisted as true across a restart). */
62
+ updatedAt: number;
63
+ }
64
+ export interface AppReleaseStoreShape {
65
+ releases: Record<string, LocalRelease>;
66
+ /** The base commit of the last release that reached testers. */
67
+ lastReleasedSha: string | null;
68
+ credentials: {
69
+ appStoreConnect?: 'connected' | 'missing';
70
+ playServiceAccount?: 'connected' | 'missing';
71
+ };
72
+ }
73
+ export interface AppReleaseStore {
74
+ read(): AppReleaseStoreShape;
75
+ write(s: AppReleaseStoreShape): void;
76
+ }
77
+ export declare function fileAppReleaseStore(stateDir: string): AppReleaseStore;
78
+ export declare function memoryAppReleaseStore(): AppReleaseStore;
79
+ export interface ReleaseDeps {
80
+ repoDir: string;
81
+ /** The project's configured base branch, or undefined to ask origin. */
82
+ baseBranch?: string;
83
+ /** git in the repository (fetch, worktree add/remove). */
84
+ git: GitExec;
85
+ /** git in a clean checkout (commit, branch). */
86
+ gitAt(dir: string): GitExec;
87
+ exec: ReleaseExec;
88
+ eas: EasRunner;
89
+ /** Where clean checkouts are made (the machine's workspaces folder). */
90
+ workRoot: string;
91
+ store: AppReleaseStore;
92
+ /** A sentence when another Looply run of this repository is active (the suite runs alone), else null. */
93
+ othersRunning(): Promise<string | null>;
94
+ /** Hold the machine for the suite: a release function, or why it cannot be held now. */
95
+ reserve?(): (() => void) | string;
96
+ /** The Expo token on this machine, or null. Never logged, never reported. */
97
+ expoToken(): string | null;
98
+ /** Push the version-bump branch and open its pull request; a sentence back. Best effort. */
99
+ publishBranch?(branch: string, sha: string, title: string, body: string): Promise<string>;
100
+ log(line: string): void;
101
+ now(): number;
102
+ /** `npm ci` (default) or a copy of the repository's own node_modules (still a real directory). */
103
+ install?: 'ci' | 'copy';
104
+ /** Dry runs only: plan at this commit instead of origin's base. */
105
+ at?: string;
106
+ }
107
+ export interface ReleaseInput {
108
+ id: string;
109
+ title: string;
110
+ tickets: ReleaseTicket[];
111
+ settings: AppReleaseSettings;
112
+ }
113
+ export type PlanOutcome = {
114
+ kind: 'plan';
115
+ plan: AppReleasePlan;
116
+ } | {
117
+ kind: 'wait';
118
+ detail: string;
119
+ } | {
120
+ kind: 'end';
121
+ state: 'failed' | 'refused' | 'nothing-to-release';
122
+ detail: string;
123
+ plan?: AppReleasePlan;
124
+ };
125
+ /** The last JSON value in a command's output (eas prints warnings around it). */
126
+ export declare function lastJson<T>(stdout: string): T | null;
127
+ export declare function bumpVersion(v: string, how: AppReleaseSettings['versionBump']): string;
128
+ /** node_modules is a real directory, not a symlink or a junction. */
129
+ export declare function realNodeModules(dir: string): string | null;
130
+ /** Remove a clean checkout. Links at its top and in node_modules are unlinked first, so nothing they point at is touched. */
131
+ export declare function removeCheckout(dir: string): void;
132
+ export declare function planRelease(deps: ReleaseDeps, input: ReleaseInput): Promise<PlanOutcome>;
133
+ /**
134
+ * Start a planned release. `approved` is the server's word that the owner
135
+ * approved THIS plan; the rules re-check a production channel against it.
136
+ */
137
+ export declare function startRelease(deps: ReleaseDeps, input: ReleaseInput, plan: AppReleasePlan, approved: boolean): Promise<AppReleaseReport>;
138
+ /** One step of following a build release: build → submit → processing → available. */
139
+ export declare function followRelease(deps: ReleaseDeps, input: ReleaseInput, plan: AppReleasePlan): Promise<AppReleaseReport>;
140
+ export declare function cleanup(deps: Pick<ReleaseDeps, 'store' | 'log'> & Partial<Pick<ReleaseDeps, 'git'>>, id: string): void;
141
+ /** Spawn without a shell; on Windows `npm`/`yarn`/`pnpm` are .cmd files and go through cmd /c. Hidden windows. */
142
+ export declare const nodeReleaseExec: ReleaseExec;
143
+ /** The installed eas-cli's entry script, run with this node (no shell, no PATH lookup in the repository). */
144
+ export declare function easCliScript(env?: NodeJS.ProcessEnv): string | null;
145
+ export declare function realEasRunner(exec?: ReleaseExec): EasRunner;
146
+ /**
147
+ * THE DRY RUN'S EAS: records every argv it was asked to run and runs none of
148
+ * them. `builds` answers `build:list` (runtime version → build id), so a dry
149
+ * run can show both the OTA and the build decision.
150
+ */
151
+ export declare function dryRunEas(builds?: Record<string, string>): EasRunner & {
152
+ calls: string[][];
153
+ };
154
+ //# sourceMappingURL=expo-release.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-release.d.ts","sourceRoot":"","sources":["../src/expo-release.ts"],"names":[],"mappings":"AAGA,OAAO,EAOL,KAAK,WAAW,EAEhB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EAEvB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAiBtB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAE7J,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACpG;AAED,2GAA2G;AAC3G,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAC7C,eAAO,MAAM,kBAAkB,QAAc,CAAC;AAC9C,eAAO,MAAM,eAAe,QAAc,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,cAAc,QAAc,CAAC;AAC1C,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAI7C,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,oGAAoG;IACpG,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACvC,gEAAgE;IAChE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE;QAAE,eAAe,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;QAAC,kBAAkB,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;KAAE,CAAC;CAC1G;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,oBAAoB,CAAC;IAC7B,KAAK,CAAC,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACtC;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAkBrE;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAGvD;AAID,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,GAAG,EAAE,OAAO,CAAC;IACb,gDAAgD;IAChD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,SAAS,CAAC;IACf,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,yGAAyG;IACzG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,wFAAwF;IACxF,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC;IAClC,6EAA6E;IAC7E,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;IAC3B,4FAA4F;IAC5F,aAAa,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1F,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,IAAI,MAAM,CAAC;IACd,kGAAkG;IAClG,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACxB,mEAAmE;IACnE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC;AAiB/G,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAkBpD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,MAAM,CAMrF;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW1D;AAED,6HAA6H;AAC7H,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAUhD;AA8BD,wBAAsB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAuK9F;AAkCD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuF7I;AAED,sFAAsF;AACtF,wBAAsB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAqF3H;AAqBD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CActH;AAID,kHAAkH;AAClH,eAAO,MAAM,eAAe,EAAE,WA2B1B,CAAC;AAEL,6GAA6G;AAC7G,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAUhF;AAED,wBAAgB,aAAa,CAAC,IAAI,GAAE,WAA6B,GAAG,SAAS,CAU5E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CAehG"}