@expo/build-tools 21.5.0 → 21.6.0

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.
@@ -15,7 +15,6 @@ const projectSources_1 = require("../common/projectSources");
15
15
  const customBuildContext_1 = require("../customBuildContext");
16
16
  const datadog_1 = require("../datadog");
17
17
  const xcodeBuildLogs_1 = require("../ios/xcodeBuildLogs");
18
- const compositeFunctions_1 = require("../steps/compositeFunctions");
19
18
  const easFunctionGroups_1 = require("../steps/easFunctionGroups");
20
19
  const easFunctions_1 = require("../steps/easFunctions");
21
20
  const retry_1 = require("../utils/retry");
@@ -55,11 +54,13 @@ async function runCustomBuildAsync(ctx) {
55
54
  steps: ctx.job.steps,
56
55
  hooks: ctx.job.hooks,
57
56
  // Eager for job steps (always run), lazy loader for hooks (running anchors only).
58
- compositeFunctionCatalog: await (0, compositeFunctions_1.buildCompositeFunctionCatalogAsync)(projectRoot, {
59
- steps: ctx.job.steps,
57
+ compositeFunctionCatalog: await (0, steps_1.buildLocalCompositeFunctionCatalogAsync)(projectRoot, {
58
+ rootSteps: ctx.job.steps,
59
+ logger: ctx.logger,
60
+ }),
61
+ loadCompositeFunction: (0, steps_1.createLocalCompositeFunctionLoader)(projectRoot, {
60
62
  logger: ctx.logger,
61
63
  }),
62
- loadCompositeFunction: (0, compositeFunctions_1.createCompositeFunctionLoader)(projectRoot, ctx.logger),
63
64
  })
64
65
  : new steps_1.BuildConfigParser(globalContext, {
65
66
  externalFunctions: easFunctions,
@@ -4,7 +4,6 @@ exports.parseJobHooksAsync = parseJobHooksAsync;
4
4
  const eas_build_job_1 = require("@expo/eas-build-job");
5
5
  const steps_1 = require("@expo/steps");
6
6
  const customBuildContext_1 = require("../customBuildContext");
7
- const compositeFunctions_1 = require("../steps/compositeFunctions");
8
7
  const easFunctionGroups_1 = require("../steps/easFunctionGroups");
9
8
  const easFunctions_1 = require("../steps/easFunctions");
10
9
  /**
@@ -60,7 +59,7 @@ async function parseJobHooksAsync(ctx, wrappedAnchors) {
60
59
  const hookEntriesByKey = {};
61
60
  const orderedSteps = [];
62
61
  const compositeFunctionCatalog = {};
63
- const loadCompositeFunction = (0, compositeFunctions_1.createCompositeFunctionLoader)(ctx.getReactNativeProjectDirectory(), ctx.logger);
62
+ const loadCompositeFunction = (0, steps_1.createLocalCompositeFunctionLoader)(ctx.getReactNativeProjectDirectory(), { logger: ctx.logger });
64
63
  for (const anchor of wrappedAnchors) {
65
64
  for (const side of ['before', 'after']) {
66
65
  const key = `${side}_${anchor}`;
package/dist/generic.js CHANGED
@@ -11,7 +11,6 @@ const promises_1 = __importDefault(require("fs/promises"));
11
11
  const nullthrows_1 = __importDefault(require("nullthrows"));
12
12
  const projectSources_1 = require("./common/projectSources");
13
13
  const customBuildContext_1 = require("./customBuildContext");
14
- const compositeFunctions_1 = require("./steps/compositeFunctions");
15
14
  const easFunctionGroups_1 = require("./steps/easFunctionGroups");
16
15
  const easFunctions_1 = require("./steps/easFunctions");
17
16
  const outputs_1 = require("./utils/outputs");
@@ -38,8 +37,8 @@ async function runGenericJobAsync(ctx) {
38
37
  try {
39
38
  const projectRoot = ctx.getReactNativeProjectDirectory(customBuildCtx.projectSourceDirectory);
40
39
  // Eager for job steps (always run), lazy loader for hooks (running anchors only).
41
- const compositeFunctionCatalog = await (0, compositeFunctions_1.buildCompositeFunctionCatalogAsync)(projectRoot, {
42
- steps: ctx.job.steps,
40
+ const compositeFunctionCatalog = await (0, steps_1.buildLocalCompositeFunctionCatalogAsync)(projectRoot, {
41
+ rootSteps: ctx.job.steps,
43
42
  logger: ctx.logger,
44
43
  });
45
44
  const parser = new steps_1.StepsConfigParser(globalContext, {
@@ -48,7 +47,9 @@ async function runGenericJobAsync(ctx) {
48
47
  steps: ctx.job.steps,
49
48
  hooks: ctx.job.hooks,
50
49
  compositeFunctionCatalog,
51
- loadCompositeFunction: (0, compositeFunctions_1.createCompositeFunctionLoader)(projectRoot, ctx.logger),
50
+ loadCompositeFunction: (0, steps_1.createLocalCompositeFunctionLoader)(projectRoot, {
51
+ logger: ctx.logger,
52
+ }),
52
53
  });
53
54
  return await parser.parseAsync();
54
55
  }
@@ -1,5 +1,7 @@
1
1
  import { SpawnOptions, SpawnResult } from '@expo/turtle-spawn';
2
2
  import { Env } from '@expo/eas-build-job';
3
+ /** Test-only: clears the memoized versions promise so each test fetches fresh. */
4
+ export declare function resetCachedEasCliVersionsForTest(): void;
3
5
  export declare function resolveEasCommandPrefixAndEnvAsync(): Promise<{
4
6
  cmd: string;
5
7
  args: string[];
@@ -3,11 +3,48 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resetCachedEasCliVersionsForTest = resetCachedEasCliVersionsForTest;
6
7
  exports.resolveEasCommandPrefixAndEnvAsync = resolveEasCommandPrefixAndEnvAsync;
7
8
  exports.runEasCliCommand = runEasCliCommand;
8
9
  const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
9
10
  const eas_build_job_1 = require("@expo/eas-build-job");
10
11
  const packageManager_1 = require("./packageManager");
12
+ const sentry_1 = require("../sentry");
13
+ let cachedEasCliVersionsPromise;
14
+ /**
15
+ * Resolves the `eas-cli` versions to install for staging/production. Prefers the
16
+ * versions committed to `cli-versions.json` (fetched from expo/eas-cli); on any
17
+ * failure (e.g. GitHub is unreachable or slow) reports to Sentry and falls back
18
+ * to the `latest-eas-build*` npm dist-tags so the build can still proceed.
19
+ *
20
+ * Memoized: `resolveEasCommandPrefixAndEnvAsync` runs more than once per build,
21
+ * so the (never-rejecting) result promise is cached to fetch GitHub at most once
22
+ * per process.
23
+ */
24
+ async function resolveEasCliVersionsAsync() {
25
+ if (!cachedEasCliVersionsPromise) {
26
+ cachedEasCliVersionsPromise = fetchEasCliVersionsWithFallbackAsync();
27
+ }
28
+ return await cachedEasCliVersionsPromise;
29
+ }
30
+ async function fetchEasCliVersionsWithFallbackAsync() {
31
+ try {
32
+ return await (0, eas_build_job_1.fetchEasCliVersionsAsync)();
33
+ }
34
+ catch (error) {
35
+ const message = error instanceof eas_build_job_1.EasCliVersionsFetchTimeoutError
36
+ ? 'Timed out fetching cli-versions.json; falling back to npm dist-tags'
37
+ : 'Failed to fetch cli-versions.json; falling back to npm dist-tags';
38
+ sentry_1.Sentry.capture(message, error instanceof Error ? error : new Error(String(error)), {
39
+ level: 'warning',
40
+ });
41
+ return { STAGING: eas_build_job_1.EasCliNpmTags.STAGING, PRODUCTION: eas_build_job_1.EasCliNpmTags.PRODUCTION };
42
+ }
43
+ }
44
+ /** Test-only: clears the memoized versions promise so each test fetches fresh. */
45
+ function resetCachedEasCliVersionsForTest() {
46
+ cachedEasCliVersionsPromise = undefined;
47
+ }
11
48
  async function probeEasdAsync() {
12
49
  try {
13
50
  const result = await (0, turtle_spawn_1.default)('easd', ['--help'], {
@@ -25,23 +62,26 @@ async function resolveEasCommandPrefixAndEnvAsync() {
25
62
  if (await probeEasdAsync()) {
26
63
  return { cmd: 'easd', args: [], extraEnv: {} };
27
64
  }
65
+ const versions = await resolveEasCliVersionsAsync();
28
66
  return {
29
67
  cmd: 'npx',
30
- args: [...npxArgsPrefix, `eas-cli@${eas_build_job_1.EasCliNpmTags.STAGING}`],
68
+ args: [...npxArgsPrefix, `eas-cli@${versions.STAGING}`],
31
69
  extraEnv: {},
32
70
  };
33
71
  }
34
72
  else if (process.env.ENVIRONMENT === 'staging') {
73
+ const versions = await resolveEasCliVersionsAsync();
35
74
  return {
36
75
  cmd: 'npx',
37
- args: [...npxArgsPrefix, `eas-cli@${eas_build_job_1.EasCliNpmTags.STAGING}`],
76
+ args: [...npxArgsPrefix, `eas-cli@${versions.STAGING}`],
38
77
  extraEnv: { EXPO_STAGING: '1' },
39
78
  };
40
79
  }
41
80
  else {
81
+ const versions = await resolveEasCliVersionsAsync();
42
82
  return {
43
83
  cmd: 'npx',
44
- args: [...npxArgsPrefix, `eas-cli@${eas_build_job_1.EasCliNpmTags.PRODUCTION}`],
84
+ args: [...npxArgsPrefix, `eas-cli@${versions.PRODUCTION}`],
45
85
  extraEnv: {},
46
86
  };
47
87
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "21.5.0",
3
+ "version": "21.6.0",
4
4
  "bugs": "https://github.com/expo/eas-cli/issues",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Expo <support@expo.io>",
@@ -39,14 +39,14 @@
39
39
  "@expo/config": "55.0.10",
40
40
  "@expo/config-plugins": "55.0.7",
41
41
  "@expo/downloader": "21.0.0",
42
- "@expo/eas-build-job": "21.5.0",
42
+ "@expo/eas-build-job": "21.6.0",
43
43
  "@expo/env": "^0.4.0",
44
44
  "@expo/logger": "21.0.0",
45
45
  "@expo/package-manager": "1.9.10",
46
46
  "@expo/plist": "^0.3.5",
47
47
  "@expo/results": "^1.0.0",
48
48
  "@expo/spawn-async": "1.7.2",
49
- "@expo/steps": "21.5.0",
49
+ "@expo/steps": "21.6.0",
50
50
  "@expo/template-file": "21.0.2",
51
51
  "@expo/turtle-spawn": "21.0.0",
52
52
  "@expo/xcpretty": "^4.3.1",
@@ -100,5 +100,5 @@
100
100
  "typescript": "^5.5.4",
101
101
  "uuid": "^9.0.1"
102
102
  },
103
- "gitHead": "b27fe84a1ed87c96bebc2b341817bb520989b186"
103
+ "gitHead": "866febb1ba2a66e33859ae8a6c67bd845e8ce8a6"
104
104
  }
@@ -1,11 +0,0 @@
1
- /**
2
- * Loads local function.yml files from the project and builds the catalog consumed by
3
- * {@link StepsConfigParser}. Keeps filesystem I/O in build-tools; expansion logic lives in @expo/steps.
4
- */
5
- import { bunyan } from '@expo/logger';
6
- import { CompositeFunctionCatalog, CompositeFunctionConfig, Step } from '@expo/eas-build-job';
7
- export declare function createCompositeFunctionLoader(projectRoot: string, logger?: bunyan): (compositeFunctionPath: string) => Promise<CompositeFunctionConfig>;
8
- export declare function buildCompositeFunctionCatalogAsync(projectRoot: string, { steps, logger }: {
9
- steps: readonly Step[];
10
- logger?: bunyan;
11
- }): Promise<CompositeFunctionCatalog>;
@@ -1,62 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createCompositeFunctionLoader = createCompositeFunctionLoader;
7
- exports.buildCompositeFunctionCatalogAsync = buildCompositeFunctionCatalogAsync;
8
- const eas_build_job_1 = require("@expo/eas-build-job");
9
- const steps_1 = require("@expo/steps");
10
- const promises_1 = __importDefault(require("fs/promises"));
11
- const path_1 = __importDefault(require("path"));
12
- const yaml_1 = __importDefault(require("yaml"));
13
- const zod_1 = require("zod");
14
- async function loadLocalCompositeFunctionConfigAsync(projectRoot, compositeFunctionPath, { logger } = {}) {
15
- const resolvedPath = (0, steps_1.resolveLocalCompositeFunctionPath)(projectRoot, compositeFunctionPath);
16
- for (const ext of ['yml', 'yaml']) {
17
- const absolutePath = path_1.default.join(resolvedPath, `function.${ext}`);
18
- let rawContents;
19
- try {
20
- rawContents = await promises_1.default.readFile(absolutePath, 'utf-8');
21
- }
22
- catch (err) {
23
- if (err?.code === 'ENOENT') {
24
- continue;
25
- }
26
- throw new Error(`Failed to read local composite function "${compositeFunctionPath}" from ${absolutePath}`, {
27
- cause: err,
28
- });
29
- }
30
- let parsed;
31
- try {
32
- parsed = yaml_1.default.parse(rawContents);
33
- }
34
- catch (err) {
35
- throw new Error(`Failed to parse local composite function "${compositeFunctionPath}" YAML at ${absolutePath}`, {
36
- cause: err,
37
- });
38
- }
39
- let config;
40
- try {
41
- config = eas_build_job_1.CompositeFunctionConfigZ.parse(parsed);
42
- }
43
- catch (err) {
44
- if (err instanceof zod_1.ZodError) {
45
- throw new Error(`Invalid composite function "${compositeFunctionPath}": ${zod_1.z.prettifyError(err)}`);
46
- }
47
- throw err;
48
- }
49
- logger?.debug(`Loaded local composite function "${compositeFunctionPath}" from ${path_1.default.relative(projectRoot, absolutePath)}`);
50
- return config;
51
- }
52
- throw new Error(`Local composite function "${compositeFunctionPath}" was referenced by a step but no such composite function exists. A local composite function is resolved from a "function.yml" (or "function.yaml") file at the referenced path relative to the EAS project root (e.g. "uses: ${compositeFunctionPath}" resolves "${compositeFunctionPath}/function.yml"). The recommended convention is to keep composite functions under ".eas/functions/<name>".`);
53
- }
54
- function createCompositeFunctionLoader(projectRoot, logger) {
55
- return compositeFunctionPath => loadLocalCompositeFunctionConfigAsync(projectRoot, compositeFunctionPath, { logger });
56
- }
57
- async function buildCompositeFunctionCatalogAsync(projectRoot, { steps, logger }) {
58
- return (0, steps_1.buildCompositeFunctionCatalogFromStepsAsync)({
59
- rootSteps: steps,
60
- loadCompositeFunction: createCompositeFunctionLoader(projectRoot, logger),
61
- });
62
- }