Skip to content

[eas-build-job][build-tools][steps] Accept legacy command/path custom function shape in function.yml; rename references in the consumers - #4095

Open
sswrk wants to merge 5 commits into
mainfrom
szymonswierk/eng-25402-eas-build-job-legacy-function-shape
Open

[eas-build-job][build-tools][steps] Accept legacy command/path custom function shape in function.yml; rename references in the consumers#4095
sswrk wants to merge 5 commits into
mainfrom
szymonswierk/eng-25402-eas-build-job-legacy-function-shape

Conversation

@sswrk

@sswrk sswrk commented Jul 27, 2026

Copy link
Copy Markdown
Member

Why

We want to grandfather the legacy reusable functions from custom builds (https://docs.expo.dev/custom-builds/functions/) into the new reusable functions that can be used in workflows. This is to make the migration from custom builds to workflows easier.

Currently, we only support composite functions. The first step towards extending the support is modifying the eas-build-job Zod schema.

How

  • Added the legacyFunction module with Zod schemas to match the legacy custom builds functions.
    • Two separate schemas: LegacyCommandFunctionConfigZ (functions with command: present) and LegacyPathFunctionConfigZ (functions with path: present).
  • Extracted compositeFunction and created a new localFunction module with schema that is a union of composite function schema and legacy function schemas.
  • Renamed references of "composite local functions" schema in steps and build-tools that should reference "local functions".

Test Plan

Added unit tests.

@linear-code

linear-code Bot commented Jul 27, 2026

Copy link
Copy Markdown

ENG-25402

@sswrk sswrk added the no changelog PR that doesn't require a changelog entry label Jul 27, 2026
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from e893fae to 3b018d6 Compare July 28, 2026 09:04
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from 3b018d6 to 891ef23 Compare July 28, 2026 12:58
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from 891ef23 to 27f53d7 Compare July 28, 2026 13:11
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from 27f53d7 to e8d69a0 Compare July 28, 2026 15:30
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from e8d69a0 to 702bea2 Compare July 29, 2026 09:01
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch 2 times, most recently from 961f32c to 9d5f159 Compare July 29, 2026 13:40
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from 9d5f159 to 36a1945 Compare July 30, 2026 15:09
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch 2 times, most recently from b98bbfd to a241370 Compare August 4, 2026 13:46
@sswrk sswrk added the ai-review Commits pushed to PRs with this label be automatically reviewed. label Aug 4, 2026
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from a241370 to d957ecb Compare August 4, 2026 14:16
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from d957ecb to ef13e90 Compare August 4, 2026 14:22
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🤖 AI code review

Decision: Approve with comments

Overall PR risk: Low. The change is additive: it adds new Zod schemas (LegacyCommandFunctionConfigZ, LegacyPathFunctionConfigZ, LocalFunctionConfigZ) and renames CompositeFunctionCatalog to LocalFunctionCatalog, without changing the set of function.yml files that the composite schema currently accepts. No production loader calls the new schemas yet, so the legacy-shape support the PR title describes is not actually reachable at runtime — this is the one confirmed warning. Blast radius is limited to function.yml schema definitions and the composite function expander, with no credential, log, or process-execution changes, and a revert would be a single-commit operation with no data migration.

🟡 Warning (1)

  • Legacy function schema is not wired into the loader that reads function.ymlpackages/eas-build-job/src/localFunction.ts:10 (correctness) · id:e6bddd1cbc22
    Confidence: High — the reviewer traced the loader and confirmed it still uses the old schema.
    Impact if shipped: Medium — legacy function.yml files still fail to load, so the PR's stated goal is not met yet.
    Suggested remediation: Wire loadLocalCompositeFunctionConfigAsync to parse with LocalFunctionConfigZ, or update the doc comment to state that this wiring is not done yet.

    Evidence and reasoning

    The doc comment on LocalFunctionConfigZ says callers format validation errors from it. No production code calls LocalFunctionConfigZ yet. Only the new test file imports it. The real loader, loadLocalCompositeFunctionConfigAsync in packages/steps/src/utils/localCompositeFunctions.ts, still parses with CompositeFunctionConfigZ only. A function.yml with a legacy command or path shape still fails with the composite-only Zod error, not the friendlier union message this PR adds. The new isLegacyFunctionConfig check in CompositeFunctionExpander.lookupCompositeFunction stays unreachable for the same reason: the catalog is only ever filled through this same loader.


This review is advisory — it never blocks a merge and never auto-approves.

@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.15385% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 62.48%. Comparing base (e383931) to head (c4b9c7b).

Files with missing lines Patch % Lines
packages/steps/src/CompositeFunctionExpander.ts 66.67% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4095      +/-   ##
==========================================
+ Coverage   62.47%   62.48%   +0.02%     
==========================================
  Files        1008     1010       +2     
  Lines       45778    45796      +18     
  Branches     9632     9633       +1     
==========================================
+ Hits        28596    28613      +17     
- Misses      15721    15722       +1     
  Partials     1461     1461              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from ef13e90 to ca56231 Compare August 5, 2026 10:19
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch 3 times, most recently from 975902e to 6faae3b Compare August 5, 2026 11:08
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from 6faae3b to 709f6de Compare August 5, 2026 12:14
Base automatically changed from szymonswierk/eng-22387-eas-cli-validate-hook-composite-functions to main August 5, 2026 12:29
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from 709f6de to fb38166 Compare August 5, 2026 12:29
@sswrk sswrk changed the title [eas-build-job] Accept legacy command/path custom function shape in function.yml [eas-build-job][build-tools][steps] Accept legacy command/path custom function shape in function.yml; rename references in the consumers Aug 5, 2026
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from c006824 to abf928e Compare August 6, 2026 12:25
@sswrk
sswrk force-pushed the szymonswierk/eng-25402-eas-build-job-legacy-function-shape branch from abf928e to c4b9c7b Compare August 6, 2026 13:28
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

⏩ The changelog entry check has been skipped since the "no changelog" label is present.

@sswrk
sswrk marked this pull request as ready for review August 6, 2026 14:39
@sswrk
sswrk requested review from hSATAC and sjchmiela August 6, 2026 14:39

@hSATAC hSATAC left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a pass through this and left two inline questions. I don't have much context on legacy custom build functions, so I'm mostly calling out a couple of compatibility differences I noticed rather than making a call on the intended behavior.

Neither is meant to block from my side, and I'll leave the final approval to Stanley since he has more context on the intended compatibility scope.


const LegacyFunctionPlatformZ = z.enum(['darwin', 'linux']);

const LegacyFunctionBaseZ = z.object({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking, and this may be intentional: should the legacy schema also accept the camelCase spellings?

From what I can tell, those are the native keys in the old Joi schema and snake_case is added as a rename alias, so supportedRuntimePlatforms, defaultValue, allowedValues, and allowedValueType work in custom builds today. Here they fail with the generic union error:

command: echo hi
supportedRuntimePlatforms: [darwin]

Maybe only grandfathering the documented snake_case shape is what we want. If so, could we add a rejection test to make that boundary explicit? Otherwise I think these branches should accept both.

return config.runs === undefined;
}

export type LocalFunctionCatalog = Record<string, LocalFunctionConfig>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor and non-blocking: do we want to keep a deprecated alias for CompositeFunctionCatalog? It has been exported from the published package since 21.3.0, so removing it would be a source break for existing importers.

/** @deprecated Use `LocalFunctionCatalog`. */
export type CompositeFunctionCatalog = LocalFunctionCatalog;

The widened return types of buildCompositeFunctionCatalogFromStepsAsync and buildLocalCompositeFunctionCatalogAsync look like another possible source break: the loader still only returns CompositeFunctionConfig, but downstream code accessing catalog[path].runs.steps may stop compiling. Would it make sense to keep those return types composite-only until the loader starts returning legacy functions?

If we'd rather make both changes now, should they go under breaking changes in the changelog so the version bump comes out right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Commits pushed to PRs with this label be automatically reviewed. no changelog PR that doesn't require a changelog entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants