Skip to content

[eas-cli] Add eas update:embedded:upload command#3720

Open
gwdp wants to merge 4 commits into
mainfrom
gwdp/embedded-update-upload-cmd-skeleton
Open

[eas-cli] Add eas update:embedded:upload command#3720
gwdp wants to merge 4 commits into
mainfrom
gwdp/embedded-update-upload-cmd-skeleton

Conversation

@gwdp
Copy link
Copy Markdown
Contributor

@gwdp gwdp commented May 12, 2026

Why

EAS Update bundle diffing can't generate patches against the JS bundle embedded in a native build, so the first OTA after install always downloads the full bundle. This command registers the embedded bundle with EAS Update so the diff worker can use it as a patch base.

Ref ENG-21033

How

  • New eas update:embedded:upload command with --platform, --bundle, --manifest, --channel, and optional --build-id / --json flags
  • Uploads the bundle via presigned URL then registers it via uploadEmbeddedUpdate; two-phase spinner shows progress for each step
  • Retries registration on EMBEDDED_UPDATE_ASSET_NOT_AVAILABLE (GCS finalization race) with exponential backoff; hints on other failures that the bundle may already be registered

Test Plan

  • yarn jest src/commands/update/embedded/__tests__/upload.test.ts src/graphql/__tests__/client-test.ts — 24 tests pass
  • yarn tsc && yarn lint pass
  • Ran locally against a real iOS archive:
$ node bin/dev update:embedded:upload \
  --platform ios \
  --bundle ios/CoinFlip.xcarchive/Products/Applications/CoinFlipPreview.app/main.jsbundle \
  --manifest ios/CoinFlip.xcarchive/Products/Applications/CoinFlipPreview.app/EXUpdates.bundle/app.manifest \
  --channel production
✔ Uploaded bundle
✔ Registered ios embedded update (runtimeVersion: 1.0.0, channel: "production")
Embedded update ID: 5f2b4c4b-77a0-45cc-9320-bc8ec2eb36fb

Copy link
Copy Markdown
Contributor Author

gwdp commented May 12, 2026

@linear
Copy link
Copy Markdown

linear Bot commented May 12, 2026

ENG-21033

@gwdp gwdp force-pushed the gwdp/embedded-update-upload-cmd-skeleton branch 4 times, most recently from bbd2f9d to 71ba6bc Compare May 19, 2026 18:52
@gwdp gwdp changed the title [eas-cli] Add eas update:upload-embedded command [eas-cli] Add eas update:embedded:upload command May 20, 2026
@gwdp gwdp force-pushed the gwdp/embedded-update-upload-cmd-skeleton branch 4 times, most recently from 3fef5e4 to 427e5a9 Compare May 20, 2026 18:32
@gwdp gwdp force-pushed the gwdp/embedded-update-upload-cmd-skeleton branch from 427e5a9 to 4375d57 Compare May 20, 2026 18:38
@gwdp gwdp requested a review from quinlanj May 20, 2026 18:42
@gwdp gwdp marked this pull request as ready for review May 20, 2026 18:43
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.91%. Comparing base (fa6c877) to head (de82930).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3720      +/-   ##
==========================================
+ Coverage   56.80%   56.91%   +0.12%     
==========================================
  Files         904      908       +4     
  Lines       39112    39210      +98     
  Branches     8173     8187      +14     
==========================================
+ Hits        22214    22314     +100     
+ Misses      15428    15426       -2     
  Partials     1470     1470              

☔ View full report in Codecov by Sentry.
📢 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.

@github-actions
Copy link
Copy Markdown

Subscribed to pull request

File Patterns Mentions
**/* @douglowder
packages/eas-cli/src/update/** @wschurman, @quinlanj
packages/eas-cli/src/commands/update/** @wschurman, @quinlanj

Generated by CodeMention

@github-actions
Copy link
Copy Markdown

✅ Thank you for adding the changelog entry!

enableJsonOutput();
}

if (!fs.existsSync(bundlePath)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

use fs-extra so you can await instead

Comment on lines +141 to +145
registerSpinner.fail('Failed to register embedded update');
Log.warn(
'This bundle may already be registered. To replace it, delete it manually and re-upload.'
);
throw e;
Copy link
Copy Markdown
Member

@quinlanj quinlanj May 21, 2026

Choose a reason for hiding this comment

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

This code will run on any error that is not an EmbeddedUpdateAssetNotAvailableError, so it wouldn't make sense to print this since we don't know if the issue is bundleregistration (ie) network error, etc.

Also I'm not sure i follow the use case here, if the bundle is already registered (the embedded asset) wouldn't the creation of the embedded update succeed? Or if you meant the EmbeddedUpdateEntity already exists, we can detect that from www and throw a special error to catch that specific case (so we aren't telling users to delete manually when we catch a generic error)

export function readEmbeddedManifest(manifestPath: string): { id: string } {
let parsed: unknown;
try {
parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

use fs-extra so we can await

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants