expo-release 2.3.1 → 2.3.2

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.
package/dist/args.d.ts CHANGED
@@ -32,47 +32,47 @@ export declare const releaseFlags: z.ZodObject<{
32
32
  profile: z.ZodString;
33
33
  base: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
34
34
  head: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
35
- platform: z.ZodDefault<z.ZodEnum<{
35
+ platform: z.ZodDefault<z.ZodPreprocess<z.ZodEnum<{
36
36
  android: "android";
37
37
  ios: "ios";
38
- }>>;
38
+ }>, unknown>>;
39
39
  impactPaths: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<string[], string>>;
40
- ignoreExpoImpact: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
40
+ ignoreExpoImpact: z.ZodPipe<z.ZodDefault<z.ZodPreprocess<z.ZodEnum<{
41
41
  false: "false";
42
42
  true: "true";
43
- }>>, z.ZodTransform<boolean, "false" | "true">>;
44
- operation: z.ZodDefault<z.ZodEnum<{
43
+ }>, unknown>>, z.ZodTransform<boolean, "false" | "true">>;
44
+ operation: z.ZodDefault<z.ZodPreprocess<z.ZodEnum<{
45
45
  deploy: "deploy";
46
46
  "force-native": "force-native";
47
47
  republish: "republish";
48
48
  "retry-ota": "retry-ota";
49
49
  "rollback-embedded": "rollback-embedded";
50
- }>>;
51
- deployType: z.ZodDefault<z.ZodEnum<{
50
+ }>, unknown>>;
51
+ deployType: z.ZodDefault<z.ZodPreprocess<z.ZodEnum<{
52
52
  native: "native";
53
53
  none: "none";
54
54
  ota: "ota";
55
- }>>;
55
+ }>, unknown>>;
56
56
  channel: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
57
57
  environment: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
58
- autoSubmit: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
58
+ autoSubmit: z.ZodPipe<z.ZodDefault<z.ZodPreprocess<z.ZodEnum<{
59
59
  false: "false";
60
60
  true: "true";
61
- }>>, z.ZodTransform<boolean, "false" | "true">>;
61
+ }>, unknown>>, z.ZodTransform<boolean, "false" | "true">>;
62
62
  preUpdate: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
63
63
  postUpdate: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
64
64
  updateExtraArgs: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
65
- exportSourceMaps: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
65
+ exportSourceMaps: z.ZodPipe<z.ZodDefault<z.ZodPreprocess<z.ZodEnum<{
66
66
  false: "false";
67
67
  true: "true";
68
- }>>, z.ZodTransform<boolean, "false" | "true">>;
68
+ }>, unknown>>, z.ZodTransform<boolean, "false" | "true">>;
69
69
  group: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
70
70
  runtimeVersion: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
71
71
  message: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
72
72
  fingerprint: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
73
- dryRun: z.ZodBoolean;
73
+ dryRun: z.ZodPreprocess<z.ZodBoolean, unknown>;
74
74
  }, z.core.$strip>;
75
75
  export type ReleaseFlags = z.output<typeof releaseFlags>;
76
- export declare function toReleaseOptions(command: CommandName, { context: flags, env }: CommandContext<ReleaseFlags>): ReleaseOptions;
76
+ export declare function toReleaseOptions(command: CommandName, { context: flags }: CommandContext<ReleaseFlags>): ReleaseOptions;
77
77
  export declare function needsDecide(operation: Operation): boolean;
78
78
  export declare function shouldIgnoreExpoImpact(options: Pick<ReleaseOptions, 'ignoreExpoImpact' | 'operation'>): boolean;
package/dist/cli.js CHANGED
@@ -2,18 +2,23 @@
2
2
  // @bun
3
3
 
4
4
  // src/cli.ts
5
- import { defineCli, defineCommand } from "hanzio/cli";
5
+ import {
6
+ CliUsageError,
7
+ defineCli,
8
+ defineCommand
9
+ } from "hanzio/cli";
6
10
 
7
11
  // src/args.ts
8
12
  import { z } from "zod";
9
13
  var DEFAULT_IMPACT_PATHS = ["apps/expo/"];
10
14
  var text = (env) => z.string().transform((value) => value.trim() || undefined).optional().meta({ env: `EXPO_RELEASE_${env}` });
11
- var trueFalse = (env, fallback) => z.enum(["true", "false"]).default(fallback).transform((value) => value === "true").meta({ env: `EXPO_RELEASE_${env}` });
15
+ var trimmed = (schema) => z.preprocess((value) => typeof value === "string" ? value.trim() : value, schema);
16
+ var trueFalse = (env, fallback) => trimmed(z.enum(["true", "false"])).default(fallback).transform((value) => value === "true").meta({ env: `EXPO_RELEASE_${env}` });
12
17
  var releaseFlags = z.object({
13
18
  profile: z.string().trim().min(1).meta({ env: "EXPO_RELEASE_PROFILE" }).describe("EAS build profile, also the default update channel"),
14
- base: text("BASE").describe("Git base SHA for the impact diff (falls back to GITHUB_EVENT_BEFORE)"),
15
- head: text("HEAD").describe("Git head SHA for the impact diff (falls back to GITHUB_SHA)"),
16
- platform: z.enum(["ios", "android"]).default("ios").meta({ env: "EXPO_RELEASE_PLATFORM" }).describe("Native platform"),
19
+ base: text("BASE").meta({ env: ["EXPO_RELEASE_BASE", "GITHUB_EVENT_BEFORE"] }).describe("Git base SHA for the impact diff"),
20
+ head: text("HEAD").meta({ env: ["EXPO_RELEASE_HEAD", "GITHUB_SHA"] }).describe("Git head SHA for the impact diff"),
21
+ platform: trimmed(z.enum(["ios", "android"])).default("ios").meta({ env: "EXPO_RELEASE_PLATFORM" }).describe("Native platform"),
17
22
  impactPaths: z.string().default(DEFAULT_IMPACT_PATHS.join(",")).transform((value, ctx) => {
18
23
  const paths = value.split(",").map((path) => path.trim()).filter(Boolean);
19
24
  if (paths.length === 0)
@@ -24,14 +29,14 @@ var releaseFlags = z.object({
24
29
  return paths;
25
30
  }).meta({ env: "EXPO_RELEASE_IMPACT_PATHS" }).describe("Comma-separated repo-root paths that count as an Expo change"),
26
31
  ignoreExpoImpact: trueFalse("IGNORE_EXPO_IMPACT", "false").describe("Check the fingerprint even when no impact path changed"),
27
- operation: z.enum([
32
+ operation: trimmed(z.enum([
28
33
  "deploy",
29
34
  "force-native",
30
35
  "retry-ota",
31
36
  "republish",
32
37
  "rollback-embedded"
33
- ]).default("deploy").meta({ env: "EXPO_RELEASE_OPERATION" }).describe("What to run"),
34
- deployType: z.enum(["none", "ota", "native"]).default("none").meta({ env: "EXPO_RELEASE_DEPLOY_TYPE" }).describe("Decision type for operate"),
38
+ ])).default("deploy").meta({ env: "EXPO_RELEASE_OPERATION" }).describe("What to run"),
39
+ deployType: trimmed(z.enum(["none", "ota", "native"])).default("none").meta({ env: "EXPO_RELEASE_DEPLOY_TYPE" }).describe("Decision type for operate"),
35
40
  channel: text("CHANNEL").describe("EAS Update channel (default: the profile)"),
36
41
  environment: text("ENVIRONMENT").describe("EAS environment for eas update (required for Expo SDK 55+)"),
37
42
  autoSubmit: trueFalse("AUTO_SUBMIT", "true").describe("Pass --auto-submit on native builds"),
@@ -43,7 +48,7 @@ var releaseFlags = z.object({
43
48
  runtimeVersion: text("RUNTIME_VERSION").describe("Runtime version for rollback-embedded (default: the fingerprint)"),
44
49
  message: text("MESSAGE").describe("Override the eas update message"),
45
50
  fingerprint: text("FINGERPRINT").describe("Fingerprint hash to use instead of generating one"),
46
- dryRun: z.boolean().meta({ env: "EXPO_RELEASE_DRY_RUN" }).describe("Print mutating EAS commands without running them")
51
+ dryRun: z.preprocess((value) => typeof value === "string" && /^\s*(true|false)\s*$/.test(value) ? value.trim() === "true" : value, z.boolean()).meta({ env: "EXPO_RELEASE_DRY_RUN" }).describe("Print mutating EAS commands without running them")
47
52
  }).superRefine((flags, ctx) => {
48
53
  if (flags.operation === "republish" && !flags.group)
49
54
  ctx.addIssue({
@@ -52,12 +57,10 @@ var releaseFlags = z.object({
52
57
  message: "required by --operation republish"
53
58
  });
54
59
  });
55
- function toReleaseOptions(command, { context: flags, env }) {
60
+ function toReleaseOptions(command, { context: flags }) {
56
61
  return {
57
62
  ...flags,
58
63
  command,
59
- base: flags.base ?? env.GITHUB_EVENT_BEFORE,
60
- head: flags.head ?? env.GITHUB_SHA,
61
64
  channel: flags.channel ?? flags.profile
62
65
  };
63
66
  }
@@ -568,12 +571,20 @@ async function operate(options, decision, ctx) {
568
571
  ctx.stdout.write(`${result}
569
572
  `);
570
573
  }
571
- var COMMANDS = ["release", "decide", "operate"];
572
574
  var cli = defineCli({
573
575
  name: "expo-release",
574
576
  description: "Fingerprint-driven Expo EAS release: OTA update or native store build",
575
577
  globals: releaseFlags,
576
578
  context: (flags) => flags,
579
+ defaultCommand: (env) => env.EXPO_RELEASE_COMMAND?.trim() || undefined,
580
+ onError: (error, io) => {
581
+ if (error instanceof CliUsageError && error.kind === "missing-command" && process.argv.length <= 2) {
582
+ io.stdout.write(error.help);
583
+ return 0;
584
+ }
585
+ const code = io.print();
586
+ return code === 2 ? 1 : code;
587
+ },
577
588
  commands: {
578
589
  release: defineCommand({
579
590
  description: "Run decide, then operate on its decision",
@@ -597,10 +608,4 @@ var cli = defineCli({
597
608
  })
598
609
  }
599
610
  });
600
- var env = Object.fromEntries(Object.entries(process.env).flatMap(([name, value]) => value?.trim() ? [[name, value.trim()]] : []));
601
- var argv = process.argv.slice(2);
602
- if (!argv.some((arg) => COMMANDS.includes(arg))) {
603
- argv = env.EXPO_RELEASE_COMMAND ? [env.EXPO_RELEASE_COMMAND, ...argv] : argv.length === 0 ? ["--help"] : argv;
604
- }
605
- var code = await cli.run(argv, { env });
606
- process.exitCode = code === 2 ? 1 : code;
611
+ process.exitCode = await cli.run();
package/dist/index.js CHANGED
@@ -3,12 +3,13 @@
3
3
  import { z } from "zod";
4
4
  var DEFAULT_IMPACT_PATHS = ["apps/expo/"];
5
5
  var text = (env) => z.string().transform((value) => value.trim() || undefined).optional().meta({ env: `EXPO_RELEASE_${env}` });
6
- var trueFalse = (env, fallback) => z.enum(["true", "false"]).default(fallback).transform((value) => value === "true").meta({ env: `EXPO_RELEASE_${env}` });
6
+ var trimmed = (schema) => z.preprocess((value) => typeof value === "string" ? value.trim() : value, schema);
7
+ var trueFalse = (env, fallback) => trimmed(z.enum(["true", "false"])).default(fallback).transform((value) => value === "true").meta({ env: `EXPO_RELEASE_${env}` });
7
8
  var releaseFlags = z.object({
8
9
  profile: z.string().trim().min(1).meta({ env: "EXPO_RELEASE_PROFILE" }).describe("EAS build profile, also the default update channel"),
9
- base: text("BASE").describe("Git base SHA for the impact diff (falls back to GITHUB_EVENT_BEFORE)"),
10
- head: text("HEAD").describe("Git head SHA for the impact diff (falls back to GITHUB_SHA)"),
11
- platform: z.enum(["ios", "android"]).default("ios").meta({ env: "EXPO_RELEASE_PLATFORM" }).describe("Native platform"),
10
+ base: text("BASE").meta({ env: ["EXPO_RELEASE_BASE", "GITHUB_EVENT_BEFORE"] }).describe("Git base SHA for the impact diff"),
11
+ head: text("HEAD").meta({ env: ["EXPO_RELEASE_HEAD", "GITHUB_SHA"] }).describe("Git head SHA for the impact diff"),
12
+ platform: trimmed(z.enum(["ios", "android"])).default("ios").meta({ env: "EXPO_RELEASE_PLATFORM" }).describe("Native platform"),
12
13
  impactPaths: z.string().default(DEFAULT_IMPACT_PATHS.join(",")).transform((value, ctx) => {
13
14
  const paths = value.split(",").map((path) => path.trim()).filter(Boolean);
14
15
  if (paths.length === 0)
@@ -19,14 +20,14 @@ var releaseFlags = z.object({
19
20
  return paths;
20
21
  }).meta({ env: "EXPO_RELEASE_IMPACT_PATHS" }).describe("Comma-separated repo-root paths that count as an Expo change"),
21
22
  ignoreExpoImpact: trueFalse("IGNORE_EXPO_IMPACT", "false").describe("Check the fingerprint even when no impact path changed"),
22
- operation: z.enum([
23
+ operation: trimmed(z.enum([
23
24
  "deploy",
24
25
  "force-native",
25
26
  "retry-ota",
26
27
  "republish",
27
28
  "rollback-embedded"
28
- ]).default("deploy").meta({ env: "EXPO_RELEASE_OPERATION" }).describe("What to run"),
29
- deployType: z.enum(["none", "ota", "native"]).default("none").meta({ env: "EXPO_RELEASE_DEPLOY_TYPE" }).describe("Decision type for operate"),
29
+ ])).default("deploy").meta({ env: "EXPO_RELEASE_OPERATION" }).describe("What to run"),
30
+ deployType: trimmed(z.enum(["none", "ota", "native"])).default("none").meta({ env: "EXPO_RELEASE_DEPLOY_TYPE" }).describe("Decision type for operate"),
30
31
  channel: text("CHANNEL").describe("EAS Update channel (default: the profile)"),
31
32
  environment: text("ENVIRONMENT").describe("EAS environment for eas update (required for Expo SDK 55+)"),
32
33
  autoSubmit: trueFalse("AUTO_SUBMIT", "true").describe("Pass --auto-submit on native builds"),
@@ -38,7 +39,7 @@ var releaseFlags = z.object({
38
39
  runtimeVersion: text("RUNTIME_VERSION").describe("Runtime version for rollback-embedded (default: the fingerprint)"),
39
40
  message: text("MESSAGE").describe("Override the eas update message"),
40
41
  fingerprint: text("FINGERPRINT").describe("Fingerprint hash to use instead of generating one"),
41
- dryRun: z.boolean().meta({ env: "EXPO_RELEASE_DRY_RUN" }).describe("Print mutating EAS commands without running them")
42
+ dryRun: z.preprocess((value) => typeof value === "string" && /^\s*(true|false)\s*$/.test(value) ? value.trim() === "true" : value, z.boolean()).meta({ env: "EXPO_RELEASE_DRY_RUN" }).describe("Print mutating EAS commands without running them")
42
43
  }).superRefine((flags, ctx) => {
43
44
  if (flags.operation === "republish" && !flags.group)
44
45
  ctx.addIssue({
@@ -47,12 +48,10 @@ var releaseFlags = z.object({
47
48
  message: "required by --operation republish"
48
49
  });
49
50
  });
50
- function toReleaseOptions(command, { context: flags, env }) {
51
+ function toReleaseOptions(command, { context: flags }) {
51
52
  return {
52
53
  ...flags,
53
54
  command,
54
- base: flags.base ?? env.GITHUB_EVENT_BEFORE,
55
- head: flags.head ?? env.GITHUB_SHA,
56
55
  channel: flags.channel ?? flags.profile
57
56
  };
58
57
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-release",
3
- "version": "2.3.1",
3
+ "version": "2.3.2",
4
4
  "description": "Fingerprint-driven Expo EAS release: OTA update or native store build, plus app runtime helpers",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -58,7 +58,7 @@
58
58
  "verify:package": "node scripts/verify-package.mjs"
59
59
  },
60
60
  "dependencies": {
61
- "hanzio": "^3.1.0",
61
+ "hanzio": "^3.3.0",
62
62
  "zod": "^4.3.6"
63
63
  },
64
64
  "peerDependencies": {
package/src/args.ts CHANGED
@@ -48,10 +48,16 @@ const text = (env: string) =>
48
48
  .optional()
49
49
  .meta({ env: `EXPO_RELEASE_${env}` })
50
50
 
51
+ // hanzio/cli skips blank env values but keeps padding (`platform: |` in YAML adds a newline).
52
+ const trimmed = <T extends z.ZodType>(schema: T) =>
53
+ z.preprocess(
54
+ (value) => (typeof value === 'string' ? value.trim() : value),
55
+ schema
56
+ )
57
+
51
58
  // `--auto-submit false` takes a value, so these are not boolean switches.
52
59
  const trueFalse = (env: string, fallback: 'true' | 'false') =>
53
- z
54
- .enum(['true', 'false'])
60
+ trimmed(z.enum(['true', 'false']))
55
61
  .default(fallback)
56
62
  .transform((value) => value === 'true')
57
63
  .meta({ env: `EXPO_RELEASE_${env}` })
@@ -64,14 +70,13 @@ export const releaseFlags = z
64
70
  .min(1)
65
71
  .meta({ env: 'EXPO_RELEASE_PROFILE' })
66
72
  .describe('EAS build profile, also the default update channel'),
67
- base: text('BASE').describe(
68
- 'Git base SHA for the impact diff (falls back to GITHUB_EVENT_BEFORE)'
69
- ),
70
- head: text('HEAD').describe(
71
- 'Git head SHA for the impact diff (falls back to GITHUB_SHA)'
72
- ),
73
- platform: z
74
- .enum(['ios', 'android'])
73
+ base: text('BASE')
74
+ .meta({ env: ['EXPO_RELEASE_BASE', 'GITHUB_EVENT_BEFORE'] })
75
+ .describe('Git base SHA for the impact diff'),
76
+ head: text('HEAD')
77
+ .meta({ env: ['EXPO_RELEASE_HEAD', 'GITHUB_SHA'] })
78
+ .describe('Git head SHA for the impact diff'),
79
+ platform: trimmed(z.enum(['ios', 'android']))
75
80
  .default('ios')
76
81
  .meta({ env: 'EXPO_RELEASE_PLATFORM' })
77
82
  .describe('Native platform'),
@@ -95,19 +100,19 @@ export const releaseFlags = z
95
100
  ignoreExpoImpact: trueFalse('IGNORE_EXPO_IMPACT', 'false').describe(
96
101
  'Check the fingerprint even when no impact path changed'
97
102
  ),
98
- operation: z
99
- .enum([
103
+ operation: trimmed(
104
+ z.enum([
100
105
  'deploy',
101
106
  'force-native',
102
107
  'retry-ota',
103
108
  'republish',
104
109
  'rollback-embedded'
105
110
  ])
111
+ )
106
112
  .default('deploy')
107
113
  .meta({ env: 'EXPO_RELEASE_OPERATION' })
108
114
  .describe('What to run'),
109
- deployType: z
110
- .enum(['none', 'ota', 'native'])
115
+ deployType: trimmed(z.enum(['none', 'ota', 'native']))
111
116
  .default('none')
112
117
  .meta({ env: 'EXPO_RELEASE_DEPLOY_TYPE' })
113
118
  .describe('Decision type for operate'),
@@ -141,7 +146,14 @@ export const releaseFlags = z
141
146
  'Fingerprint hash to use instead of generating one'
142
147
  ),
143
148
  dryRun: z
144
- .boolean()
149
+ .preprocess(
150
+ // hanzio/cli makes booleans of exact `true`/`false`; this takes padded ones too.
151
+ (value) =>
152
+ typeof value === 'string' && /^\s*(true|false)\s*$/.test(value)
153
+ ? value.trim() === 'true'
154
+ : value,
155
+ z.boolean()
156
+ )
145
157
  .meta({ env: 'EXPO_RELEASE_DRY_RUN' })
146
158
  .describe('Print mutating EAS commands without running them')
147
159
  })
@@ -158,13 +170,11 @@ export type ReleaseFlags = z.output<typeof releaseFlags>
158
170
 
159
171
  export function toReleaseOptions(
160
172
  command: CommandName,
161
- { context: flags, env }: CommandContext<ReleaseFlags>
173
+ { context: flags }: CommandContext<ReleaseFlags>
162
174
  ): ReleaseOptions {
163
175
  return {
164
176
  ...flags,
165
177
  command,
166
- base: flags.base ?? env.GITHUB_EVENT_BEFORE,
167
- head: flags.head ?? env.GITHUB_SHA,
168
178
  channel: flags.channel ?? flags.profile
169
179
  }
170
180
  }
package/src/cli.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- import { type CommandContext, defineCli, defineCommand } from 'hanzio/cli'
4
3
  import {
5
- type CommandName,
4
+ CliUsageError,
5
+ type CommandContext,
6
+ defineCli,
7
+ defineCommand
8
+ } from 'hanzio/cli'
9
+ import {
6
10
  needsDecide,
7
11
  type ReleaseFlags,
8
12
  type ReleaseOptions,
@@ -76,8 +80,6 @@ async function operate(
76
80
  ctx.stdout.write(`${result}\n`)
77
81
  }
78
82
 
79
- const COMMANDS: CommandName[] = ['release', 'decide', 'operate']
80
-
81
83
  const cli = defineCli({
82
84
  name: 'expo-release',
83
85
  description:
@@ -85,6 +87,22 @@ const cli = defineCli({
85
87
  // All three commands take the same flags, before or after the command name.
86
88
  globals: releaseFlags,
87
89
  context: (flags) => flags,
90
+ // The composite action names the command in EXPO_RELEASE_COMMAND and passes no argv.
91
+ defaultCommand: (env) => env.EXPO_RELEASE_COMMAND?.trim() || undefined,
92
+ onError: (error, io) => {
93
+ // With no arguments at all, print help and exit 0.
94
+ if (
95
+ error instanceof CliUsageError &&
96
+ error.kind === 'missing-command' &&
97
+ process.argv.length <= 2
98
+ ) {
99
+ io.stdout.write(error.help)
100
+ return 0
101
+ }
102
+ // Bad arguments exit 1, as before hanzio/cli, which uses 2.
103
+ const code = io.print()
104
+ return code === 2 ? 1 : code
105
+ },
88
106
  commands: {
89
107
  release: defineCommand({
90
108
  description: 'Run decide, then operate on its decision',
@@ -112,23 +130,4 @@ const cli = defineCli({
112
130
  }
113
131
  })
114
132
 
115
- // GitHub Actions passes an unset input as an empty string; treat it as unset.
116
- const env = Object.fromEntries(
117
- Object.entries(process.env).flatMap(([name, value]) =>
118
- value?.trim() ? [[name, value.trim()]] : []
119
- )
120
- )
121
-
122
- let argv = process.argv.slice(2)
123
- if (!argv.some((arg) => COMMANDS.includes(arg as CommandName))) {
124
- // The composite action names the command in EXPO_RELEASE_COMMAND and passes no argv.
125
- argv = env.EXPO_RELEASE_COMMAND
126
- ? [env.EXPO_RELEASE_COMMAND, ...argv]
127
- : argv.length === 0
128
- ? ['--help']
129
- : argv
130
- }
131
-
132
- const code = await cli.run(argv, { env })
133
- // Bad arguments exit 1, as before hanzio/cli, which uses 2.
134
- process.exitCode = code === 2 ? 1 : code
133
+ process.exitCode = await cli.run()