Apple supports up to 3 video previews per device type, but the
metadata:push/pull pipeline previously hard-coded a single preview per
PreviewType. Lift that limitation by accepting an array of preview
configs alongside the existing single-config form (which still works
for backwards compat). Sync semantics now mirror screenshots: match by
filename + size, upload only changed entries, delete removed ones, and
reorder the set to match config order.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
* Add App Clip metadata support
Introduce App Clip support across metadata pipeline: add JSON schema definitions for AppleAppClip and related types; extend Apple types with AppClip interfaces and action enum; add reader accessors (getAppClip*, getAppClipLocalizedInfo) and writer mutators (setAppClipDefaultExperience, setAppClipReviewDetail, setAppClipLocalizedInfo). Implement AppClipTask to prepare/download/upload App Clip default experience, localizations, header images and review invocation URLs, including helper functions for syncing and downloading header images. Wire the task into the tasks index, include AppClipData in AppleData, and add unit tests for reader, writer, and task behavior.
* Preserve placeholder assets and app clip fallback
Fix race/regression issues when App Store Connect records are not yet rendered: - ScreenshotsTask and PreviewsTask now preserve placeholder local paths when imageAsset/videoUrl is null (AWAITING_UPLOAD) so pulled config doesn't drop entries and users can recover by adding files or removing entries. - PreviewsTask/ScreenshotsTask use the downloaded path when available, otherwise build a deterministic store path (with filename or index-based fallback). - AppClipTask.downloadAsync now falls back to the template experience when the current version has no default experience.
Also adds/updates unit tests for app clip behaviors (fallback to template, preserving header image path, skipping no-op PATCHes and review detail updates, and aborting when no editable version), screenshots (placeholder paths and index-based filename fallback), and previews (preserving placeholder entries when videoUrl is null). These changes address intermittent failures and improve round-trip push/pull resilience.
* [eas-cli] Bump @expo/apple-utils to 2.1.19
Brings in the fix for image and video uploads via metadata:push. The
asset client was inheriting Bearer token injection from the App Store
Connect API client, which caused S3 presigned URL uploads to be silently
mishandled by Apple's CDN — leaving screenshots, previews, and App Clip
header images stuck in AWAITING_UPLOAD state.
Also adds new App Clip models (AppClipDefaultExperience,
AppClipDefaultExperienceLocalization, AppClipHeaderImage,
AppClipAppStoreReviewDetail) used by the new App Clip metadata support.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* Sync Apple metadata schema, docs, and flags
Add new Apple advisory fields to metadata-0.json (advertising, ageAssurance, ageRatingOverrideV2, developerAgeRatingInfoUrl, gunsOrOtherWeapons, healthOrWellnessTopics, messagingAndChat, parentalControls, userGeneratedContent) and an AppleAgeRatingOverrideV2 enum. Introduce CLAUDE.md documenting how to keep schema and reader/writer in sync. Replace manual 'non-interactive' flags in metadata push/pull with the shared EASNonInteractiveFlag. Add a unit test that validates AppleConfigWriter output against the JSON schema (imports validateConfig) as a drift guard to surface mismatches between writer output and the schema early. These changes prevent confusing validation errors when pulling/pushing metadata by keeping schema, docs, CLI flags, and tests aligned.
* [eas-cli] Bump @expo/apple-utils to 2.1.18
Fixes `eas metadata:push` failing in the age-rating phase with
"'gamblingAndContests' is not an attribute on the resource
'ageRatingDeclarations'". The published 2.1.17 bundle still emitted
that field at runtime even though its `.d.ts` typed it as `never`,
because @expo/apple-utils' prepare script regenerated types from source
but bundled @expo/app-store from a stale `build/` directory.
2.1.18 rebuilds @expo/app-store as part of the prepare flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
* Fix changelog PR link
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* Add new Apple metadata attributes
Extend AppleConfigReader and AppleConfigWriter to include additional app rating/content fields (advertising, ageAssurance, ageRatingOverrideV2, developerAgeRatingInfoUrl, gunsOrOtherWeapons, healthOrWellnessTopics, messagingAndChat, parentalControls, userGeneratedContent) with sensible defaults (false/null or Rating.NONE). This ensures these attributes are preserved when reading and writing Apple metadata.
* update package
* Add missing fields to test fixtures and CHANGELOG entry
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* [build-tools] Detect iOS Development provisioning profiles and set correct code signing identity
Add DEVELOPMENT distribution type to distinguish Development profiles
from Ad Hoc. Development profiles have get-task-allow=true in their
entitlements; Ad Hoc profiles don't.
When a Development profile is detected, override CODE_SIGN_IDENTITY to
"Apple Development" instead of the "iPhone Distribution" that
@expo/config-plugins hardcodes. This fixes builds that use
credentialsSource: "local" with Development profiles (e.g., for
Family Controls entitlement).
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* [eas-cli] Accept Development provisioning profiles for internal distribution
Fix isAdHocProfile() to distinguish Development from Ad Hoc profiles by
checking the get-task-allow entitlement. Add isDevelopmentProfile() for
explicit detection.
Update assertProvisioningProfileType() to accept Development profiles
for internal distribution, and reject them for store distribution.
This enables credentialsSource: "local" with Development profiles needed
for entitlements like Family Controls (com.apple.developer.family-controls)
that only work with Development provisioning profiles.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* [build-tools] Use certificateCommonName for development code signing identity
Address review feedback: use the certificate common name from the
provisioning profile instead of hardcoding "Apple Development", which
doesn't cover all certificate types (e.g. "iPhone Developer", "iOS
Development"). Also fix grammar in error message ("an development" →
"a development").
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* [build-tools] Add CHANGELOG entry for development provisioning profile fix
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* [build-tools] Use upstream codeSignIdentity parameter instead of workaround
Now that @expo/[email protected] supports the optional
codeSignIdentity parameter in setProvisioningProfileForPbxproj,
pass profile.certificateCommonName directly for development profiles
and remove the overrideCodeSignIdentityForDevelopment workaround
that was reading/writing the pbxproj a second time.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix changelog
Temporary Commit at 4/2/2026, 1:09:37 PM
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Quinlan Jung <[email protected]>
* Add app_store_connect.build_upload workflow interpolation context
* limit the possible states
* make the id type uuid
* Update packages/eas-build-job/src/common.ts
Co-authored-by: Stanisław Chmiela <[email protected]>
* Update packages/eas-build-job/src/common.ts
Co-authored-by: Stanisław Chmiela <[email protected]>
* remove no longer valid test
---------
Co-authored-by: Stanisław Chmiela <[email protected]>
## Summary
- remove the internal `eas/__maestro_test` function registration and implementation
- delete the Maestro flow/config discovery helper used by that internal path
- remove the related tests and fixture files for Maestro config parsing and flow resolution
## Testing
- `yarn --cwd packages/build-tools typecheck`
- `yarn --cwd packages/build-tools jest-unit --runInBand maestroResultParser reportMaestroTestResults easFunctions`
## Summary
- remove the worker and build-tools plumbing for precompiled dependency downloads and extraction
- stop waiting on precompiled dependency preparation before `pod install`
- delete the dedicated precompiled dependency helpers, fixtures, and tests
- keep the `EAS_USE_PRECOMPILED_MODULES=1` passthrough so iOS jobs still set `EXPO_USE_PRECOMPILED_MODULES=1`
## Testing
CI should pass.
## Why
`hasIgnoredIosProjectAsync()` currently always returns `false` because its `finally` block unconditionally returns `false`, overriding the value from the `try` block.
That means callers never see a positive ignored result even when the Xcode project is actually ignored.
## How
- replace the unconditional `finally` return with a `catch` fallback
- add a unit test that covers the ignored iOS project case
## Test Plan
CI should pass. Verified the test would fail if not for this change.
## Summary
- mark `FAILED_TO_REPORT_PROJECT_DEPENDENCIES_EVENT` as a Sentry warning instead of an error
- reduce noise from non-critical analytics failures in worker project dependency reporting
* Add support for Apple screenshots and video previews
Introduces new tasks for managing App Store screenshots and video previews, including downloading and uploading assets per locale and display type. Updates AppleData and PartialAppleData types to include screenshots and previews, and extends config reader/writer to handle these assets. Also bumps @expo/apple-utils to 2.1.13 and updates related tests and types.
* Update apple-utils and improve asset file handling
Bump @expo/apple-utils to 2.1.14 and add a version check for preview support. Normalize preview and screenshot asset directory structure and filenames for consistency and future compatibility.
* Use original type names for preview and screenshot dirs
Updated directory structure for storing Apple previews and screenshots to use the original previewType and displayType values instead of lowercased, hyphenated versions. This change ensures consistency with the original type naming.
* Improve Apple metadata tasks error handling and schema
Replaces assert-based error handling with conditional checks and log messages in Apple metadata tasks (age-rating, app-review-detail, previews, screenshots) to prevent crashes when context is missing. Updates the metadata schema to add support for 'screenshots' and 'previews' fields, including detailed structure for video previews.
* Use original filenames for Apple previews and screenshots
Updated the download logic to use the original filenames from Apple metadata for previews and screenshots instead of normalized index-based names. This change improves file matching during sync operations.
* Update tests to skip on missing context instead of abort
Changed age rating and app review detail task tests to expect skipping (not throwing) when required context is missing, reflecting updated behavior. Also updated CHANGELOG to note new screenshots and previews support for metadata commands.
* wip -- unit tests for metadata
* Include .query(true) in apple metadata tests
Allow nock mocks to match requests with query parameters in two tests. Added `.query(true)` to the GET interceptors in packages/eas-cli/src/metadata/apple/tasks/__tests__/previews.test.ts and packages/eas-cli/src/metadata/apple/tasks/__tests__/screenshots.test.ts so the mocks won't fail when requests include query strings.
* [eas-cli] Fix age rating API and update @expo/apple-utils to 2.1.16
Move age rating from appStoreVersions to appInfos — Apple removed the
ageRatingDeclaration relationship from appStoreVersions. Also apply
formatting fixes from oxfmt.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
* Update CHANGELOG.md
* [eas-cli] Improve screenshots/previews tasks: native fs, fileSize matching, parallel fetching
- Replace fs-extra with native fs/fs.promises
- Add fileSize check alongside filename matching to detect changed files
- Parallelize locale fetching in prepareAsync with Promise.all
- Skip reorder API call when screenshot order is unchanged
- Remove unnecessary runtime method check for getAppPreviewSetsAsync
- Use consistent index-based fallback filenames for previews
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* Support non-interactive metadata commands
Add a --non-interactive flag to metadata pull/push and thread nonInteractive through context and helper calls. Propagate the flag to ensureProjectConfiguredAsync, getProfilesAsync, getAppStoreAuthAsync, downloadMetadataAsync and uploadMetadataAsync so prompts are skipped or fail fast when non-interactive.
Improve App Store Connect auth resolution: try ASC API key from submit profile, then EAS credentials service (via GraphQL lookup), then environment variables; fall back to interactive cookie auth only when allowed. In non-interactive mode, throw a clear error if no ASC API key is available. Also update upload/download to auto-overwrite in non-interactive mode and make config validation in upload fail instead of prompting.
Minor: import/fs usage and GraphQL client types added, small logging improvements and error messages to aid non-interactive workflows.
* Add metadata tests and enhance App Store auth
Add unit tests for metadata auth, download, and upload flows and update App Store auth resolution to include team metadata.
- New tests: src/metadata/__tests__/auth.test.ts, download.test.ts, upload.test.ts covering API key resolution, interactive vs non-interactive behavior, telemetry, and validation prompts.
- auth.ts: refactor tryResolveAscApiKeyAsync to return ascApiKey plus optional teamId/teamName, read profile-provided keyP8 and prefer profile keys over stored keys, and include teamId/teamName/teamType (defaulting to COMPANY_OR_ORGANIZATION) when calling ensureAuthenticatedAsync.
These changes improve handling of ASC API keys and team info during authentication and add coverage for metadata CLI flows and edge cases.
* Use fs.promises.readFile instead of fs-extra
Replace import of fs-extra with Node's built-in fs and call fs.promises.readFile when loading the ASC API key. Update tests to mock fs.promises.readFile accordingly. This removes the dependency on fs-extra for this code path and aligns the readFile usage with the fs.promises API.
* [eas-cli] Add CHANGELOG entry for metadata non-interactive support
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
## Summary
- export precompiled modules helpers from `@expo/build-tools` and start preparation when flagged builds enable precompiled modules
- wait for precompiled module preparation before running `pod install` in both build-tools pod flows
- set worker env and config for precompiled module downloads, including proxy-aware download handling and coverage for the new behavior
## Testing
<img width="812" height="325" alt="Zrzut ekranu 2026-03-28 o 22 26 35" src="https://github.com/user-attachments/assets/9e4deb10-d233-4bb6-ac5d-48cef31c17ed" />
<img width="1032" height="548" alt="Zrzut ekranu 2026-03-28 o 22 27 27" src="https://github.com/user-attachments/assets/a6bbcb75-4845-4dce-9f31-5097ece800ae" />
## Summary
- disable Android emulator window and transition animation scales once the emulator is booted and ready
- apply the setting for the initial emulator and any cloned emulator instances used by the start step
- add unit coverage for the new adb settings commands and the startup orchestration
## Why
Maestro test runs already avoid the emulator boot animation, but Android window and transition animations still run after boot. Those system animations add avoidable UI transition latency and can introduce test flake without affecting in-app animator timing.
See https://bsky.app/profile/rdperottoni.bsky.social/post/3mfnhnt77mk2f.
## Validation
- `yarn fmt packages/build-tools/src/utils/AndroidEmulatorUtils.ts packages/build-tools/src/steps/functions/startAndroidEmulator.ts packages/build-tools/src/steps/functions/__tests__/startAndroidEmulator.test.ts packages/build-tools/src/utils/__tests__/AndroidEmulatorUtils.test.ts`
- `yarn --cwd packages/build-tools jest-unit -- runInBand src/steps/functions/__tests__/startAndroidEmulator.test.ts src/utils/__tests__/AndroidEmulatorUtils.test.ts`
## Summary
- remove `buildStepInternalId` emission from `BuildStep`
- stop generating the extra UUID entirely
- drop the now-unused field from local build log sanitization
Just want to make logs smaller.
## Testing
- yarn --cwd packages/steps test --runInBand BuildStep-test.ts
- yarn --cwd packages/steps typecheck
## Summary
- key workflow log groups by `buildStepId` instead of display text (this might cause two steps named the same to appear as one)
- treat `buildStepInternalId` as nonexistent in the CLI parser (want to remove it)
- keep display names for prompts and status output while preserving stable selection keys
## Testing
- yarn --cwd packages/eas-cli test src/__tests__/commands/workflow-logs-test.ts src/commandUtils/workflow/__tests__/utils-test.ts
- yarn --cwd packages/eas-cli typecheck
## Summary
- add a dedicated `packages/eas-cli/src/sentry.ts` module that initializes `@sentry/node` for eas-cli
- capture command failures from `EasCommand`, including `EasCommandError`, and flush Sentry on exit
- propagate `EAS_CLI_SENTRY_DSN` into the worker child-process environment so worker-run eas-cli commands can report errors too
https://exponent-internal.slack.com/archives/C06EFBQK3B7/p1773432161848589?thread_ts=1773417343.042269&cid=C06EFBQK3B7
## Validation
- `yarn test src/commandUtils/__tests__/EasCommand-test.ts --runInBand`
- `yarn test:unit --runInBand src/__unit__/env.test.ts`
- `yarn build` in `packages/eas-cli`
- `node ./bin/run --version`
- `node ./bin/run --help`
- `node ./bin/run analytics`
- `EAS_CLI_SENTRY_DSN=https://[email protected]/1 node ./bin/run analytics`
## Manual Sentry Verification
- ran the compiled CLI against the test Sentry project `expo-stanley-test/test-local` with a real DSN
- forced an `EasCommandError` from `eas analytics` and confirmed the CLI failed locally as expected
- verified that Sentry ingested the event and created issue `TEST-LOCAL-1`
- confirmed the event in Sentry at `https://expo-stanley-test.sentry.io/issues/TEST-LOCAL-1`
## Summary
- standardize workspace clean/rebuild/prepack deletion steps on `rimraf`
- add `rimraf` where package-local scripts invoke it directly
- keep `worker` and root clean flows working from a clean install
Also adds Codex config for new workspace.
And the problem it solves is that sometimes `yarn clean` would fail if there were no `*.tsbuildinfo` files. Something weird about zsh in package.json
## Validation
- mise exec -- yarn clean
- mise exec -- yarn install --immutable
- mise exec -- yarn build
- mise exec -- yarn typecheck
- mise exec -- yarn clean (in packages/worker)
- mise exec -- yarn clean (in packages/logger)
# Why
Logs from EAS build jobs using the built-in flow are in a different form than those from build jobs using custom YAML. Because of this, `eas workflow:logs` and `eas workflow:status` were not working correctly for workflow runs with these jobs.
# How
Analyze the differences in format, and modify the utils that parse logs to handle both formats.
# Test Plan
- Tested with recent workflow runs from expo/expo
- Unit tests updated
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
After new union type addition GQL fails TSC in `eas-cli`.
# How
Added fetching of `username` for `PartnerActor` and used it where we would previously use `username` of a `User`.
Removed `getUsernameForBuildMetadataAndBuildJob` in favor of `getActorUsername`, I don't think these will every be different?
Removed
# Test Plan
CI should pass.
## Why
UNKNOWN submit failures include App Store Connect SDK compatibility error `90725`.
This should be surfaced as actionable EAS guidance (rebuild with newer iOS SDK/Xcode image) instead of generic unknown.
## How
- add `90725` detection in `upload_to_asc` failed-state handling
- throw `EAS_UPLOAD_TO_ASC_SDK_VERSION_ISSUE` with EAS-specific remediation
- include docs URL to iOS build image/Xcode configuration docs
- add unit tests for `isSdkVersionIssueError`
## Examples
- https://expo.dev/uuid/019cbbe7-9d71-7c90-80b5-a98870478265
- https://expo.dev/uuid/019cbf52-3cbd-7491-b35e-c3fc2f24afc9
- https://expo.dev/uuid/019cbf4f-41d9-7ab7-8e85-e53596526a82
## Test Plan
- `yarn --cwd packages/build-tools jest-unit src/steps/functions/__tests__/uploadToAsc.test.ts`
- `yarn --cwd packages/build-tools typecheck`
- `yarn fmt`
Summary
- add the missing `ITSAppUsesNonExemptEncryption` boolean to `packages/worker/app.json` so the worker app can declare non-exempt encryption usage and avoid iOS config errors
Should fix system tests!
## Summary
- enable worker HTTP log streaming for staging using https://staging-logs.expo.dev/logs/
This is not tied to anything in UI yet. Just want to see the logs flowing.
## Summary
- stop mutating the original error instance in worker Sentry reporting
- attach the worker message to Sentry as an extra instead of rewriting the exception message — matches `universe/server-logging`
- keep the launcher-facing error payload unchanged
- fixes integration tests
## Testing
- yarn test:integration:watch stateSync
- yarn test:unit sentry
## Summary
- introduce `SystemError` as the explicit system-failure type
- replace in-repo `BuildError` usage with `ExpoError`, `UserError`, and `SystemError`
- keep unknown errors on the user-error side
## Changes
- remove the old `BuildError` class from the in-repo error flow
- make `SystemError` always publish `SERVER_ERROR` while keeping `trackingCode` for internal use
- update worker handling, analytics, and state sync to use the shared `ExpoError` contract
- avoid mutating the user-facing error object during Sentry reporting
## Testing
- `packages/eas-build-job`: `npm exec -- corepack yarn build && npm exec -- corepack yarn test src/__tests__/errors.test.ts --runInBand`
- `packages/build-tools`: `npm exec -- corepack yarn jest-unit src/buildErrors/__tests__/detectError.test.ts --runInBand`
- `packages/worker`: `npm exec -- corepack yarn test:integration src/__integration__/stateSync.test.ts`
# Why
`eas build -p android` prompts for keystore generation and fails in CI or non-TTY environments:
```
Input is required, but stdin is not readable. Failed to display prompt: Generate a new Android Keystore?
```
Passing `--non-interactive` works around this, but it should be auto-detected when `CI=1` or stdin is not a TTY.
# How
Set a `default` function on both `--non-interactive` flag definitions (`EasNonInteractiveAndJsonFlags` and `EASNonInteractiveFlag`) in `packages/eas-cli/src/commandUtils/flags.ts`. The default checks `CI` env var (via `boolish` from `getenv`) and `process.stdin.isTTY`.
- oclif evaluates `default` only when the user does NOT pass `--non-interactive` on CLI
- `noCacheDefault: true` prevents baking the developer's environment into `oclif.manifest.json`
- All ~60 commands using these flag definitions automatically get CI/TTY auto-detection with no other changes needed
# Test Plan
- Added 5 unit tests for `isNonInteractiveByDefault()` covering: TTY without CI (false), CI=1 (true), CI=true (true), non-TTY stdin (true), both CI and non-TTY (true)
- All existing `resolveNonInteractiveAndJsonFlags` tests pass unchanged
- `yarn typecheck` passes
- `yarn lint` passes (0 errors)
```
PASS src/commandUtils/__tests__/flags-test.ts
isNonInteractiveByDefault
✓ returns false when stdin is a TTY and CI is not set
✓ returns true when CI=1
✓ returns true when CI=true
✓ returns true when stdin is not a TTY
✓ returns true when both CI is set and stdin is not a TTY
resolveNonInteractiveAndJsonFlags
✓ returns both false when no flags are set
✓ --json implies --non-interactive
✓ --non-interactive alone does not enable json
✓ both flags explicitly set
✓ both flags explicitly false
✓ --json false with --non-interactive true
Test Suites: 1 passed, 1 total
Tests: 11 passed, 11 total
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
# Why
There have been failures recently with the GitHub CHANGELOG check. Adjusting the workflow so that it can be manually tested.
# How
Add `workflow_dispatch:`
# Test Plan
CI should pass
* add skip-build-if-not-found to build:dev
* add changelog entry for build:dev skip flag
* Remove duplicate line in CHANGELOG
* Adjust CHANGELOG
* Bump add-pr-comment workflow dep
---------
Co-authored-by: Douglas Lowder <[email protected]>
* [build-tools] Check all certificates in provisioning profile during verification
Apple provisioning profiles can contain multiple developer certificates
(e.g., when a team has multiple developers). The previous code only
checked DeveloperCertificates[0], causing false "profile and
distribution certificate don't match" errors when the signing
certificate was at a different index.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* [build-tools] Add CHANGELOG entry for multi-cert provisioning profile fix
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
# Why
Some environments that run Gradle do not have `en_US.UTF-8` available, which can lead to locale warnings and Gradle failures when Java falls back to a non-UTF-8 default charset.
In the affected environment, `locale -a` returned only:
```sh
C
C.utf8
POSIX
```
Setting `LC_ALL=C.UTF-8` fixed the Gradle issue. This matches the behavior described in [gradle/gradle#23391](https://github.com/gradle/gradle/issues/23391#issuecomment-1878979127), where Gradle/archive handling fails under a non-UTF-8 locale.
# How
Inline `LC_ALL: 'C.UTF-8'` at the two Android Gradle subprocess call sites in `@expo/build-tools`:
- `packages/build-tools/src/android/gradle.ts`
- `packages/build-tools/src/steps/utils/android/gradle.ts`
This keeps the change narrowly scoped to Gradle execution instead of changing the broader worker environment or unrelated iOS/macOS build paths.
# Test Plan
- Verified the affected environment does not support `en_US.UTF-8`:
```sh
locale -a
```
Output:
```sh
C
C.utf8
POSIX
```
- Confirmed that setting `LC_ALL=C.UTF-8` fixes the Gradle issue locally.
- Ran a targeted TypeScript check after the code change:
```sh
./node_modules/.bin/tsc -p packages/build-tools/tsconfig.json --noEmit
```
# Why
The Android builder currently only injects Gradle config during `PREPARE_CREDENTIALS`. That means `job.version.versionCode` and `job.version.versionName` are ignored for builds that do not provide Android build credentials, even though those version values are present on the job.
This ports the Android version injection change from `expo/eas-build#425`, now on top of the merged enum-backed `CONFIGURE_ANDROID_VERSION` build phase.
# How
- switch the Android builder from the legacy `eas-build.gradle` shim to the existing direct Gradle injection helpers
- keep credential injection gated on build credentials
- inject the Android version Gradle config whenever `job.version` includes `versionCode` or `versionName`, even if there are no credentials
- run that injection in `BuildPhase.CONFIGURE_ANDROID_VERSION`
- remove the now-unused legacy shim files
- warn when deprecated `eas-build.gradle` still exists, matching the previous conservative behavior
- add focused Android builder coverage for the no-credentials version case
- add helper coverage for the legacy warning path
# Test Plan
- `mise exec -- yarn workspace @expo/build-tools jest-unit src/steps/utils/android/__tests__/gradleConfig.test.ts src/builders/__tests__/android.test.ts`
- `mise exec -- yarn workspace @expo/build-tools test`
- `mise exec -- yarn workspace @expo/build-tools typecheck`
- `git diff --check`
# Why
Preparation for https://github.com/expo/eas-cli/pull/3483.
# How
- add `BuildPhase.CONFIGURE_ANDROID_VERSION`
- add display metadata for the new phase
- add website ID metadata for the new phase
# Test Plan
CI should pass.
## Why
Old task I asked Codex to do.
## How
- upgrade `eas-cli` from oclif v3 to v4 using the native v4 APIs
- migrate legacy array-style `static args = [...]` declarations to native v4 object-style `Args.*` definitions
- keep command typing fully native and type-safe, including `Flags.option(...).options` const assertions where needed for inference
- update tests and shared test helpers for the v4 config/hook behavior
Notes:
- argument order is preserved in oclif v4 because `static args = { ... }` is treated as an ordered object; positional args follow object insertion order
- the bin entrypoints now use `@oclif/core` `execute(...)`, which is the supported v4 boot path
- `execute(...)` already performs the old `run().then(flush).catch(handle)` flow internally, so the explicit `flush` and `handle` chaining was removed as redundant rather than as a behavior change
- `bin/dev` keeps the dev entrypoint behavior through `execute({ development: true, ... })`, which enables the development boot path and verbose debugging behavior in v4
## Test plan
- `./node_modules/.bin/tsc --project packages/eas-cli/tsconfig.build.json`
- `node packages/eas-cli/bin/run --help`
- `node packages/eas-cli/bin/dev --help`
- `npx -y @yarnpkg/[email protected].0 workspace eas-cli test --runInBand`
Instead of throwing an error when running `eas build -p android --non-interactive`
without existing credentials, automatically generate a keystore using the existing
`generateRandomKeystoreAsync()` function.
Co-authored-by: Claude Opus 4.5 <[email protected]>
# Why
Provide a way to override the new requirement for the `--environment` flag in `eas update`.
# How
Modify the check to skip when the `EAS_UPDATE_SKIP_ENVIRONMENT_CHECK` variable is set to a boolish value (1 or true).
If the command is run interactively, we now prompt the user for the environment, instead of throwing an error. This is skipped if the `--auto` flag is set. A missing environment flag already throws an error if `--non-interactive` is set.
Add the `CI` flag to the tests for whether we should skip the check in a CI environment.
# Test Plan
New unit tests added.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We want to push logs to a logs service.
# How
Initially I wanted to set up a WebSocket connection between worker and the logs service to reduce the HTTP overhead, but I found having a persistent/reconnecting WebSocket connection is not trivial and HTTP should be ok.
Confirmed failure to upload is not logged in the GCS log.
# Test Plan
Tested manually.
https://github.com/user-attachments/assets/f80f0482-73f5-4dfb-855f-2361ed04aa4f
## Summary
- remove the duplicated `userFacingMessage` and `userFacingErrorCode` fields from the build error flow
- keep current runtime behavior and unknown-error semantics
- preserve the current worker protocol shape
Stanley: I don't want to have separate `userFacingMessage` and `message` / `userFacingErrorCode` and `errorCode`. It looks like the reason we had them separate was to log "UNKNOWN_ERROR" to the user if we encounter an internal issue like "NPM_CORRUPTED_PACKAGE". This pull request inverts the logic — we're going to have a `trackingCode` so we keep logging "NPM_CORRUPTED_PACKAGE" to Sentry and the default `errorCode` is the one we log to the user.
## Changes
- make `BuildError.format()` use canonical `message` and `errorCode`
- make `build-tools` store internal-only classification in `trackingCode` instead of parallel public fields
- make worker derive `internalErrorCode` from `trackingCode ?? errorCode`
- delete the obsolete `userFacing...` fields from `BuildError`
## Testing
- `packages/eas-build-job`: `npm exec -- corepack yarn test src/__tests__/errors.test.ts --runInBand`
- `packages/build-tools`: `npm exec -- corepack yarn jest-unit src/buildErrors/__tests__/detectError.test.ts --runInBand`
- `packages/worker`: `npm exec -- corepack yarn test:integration src/__integration__/stateSync.test.ts`
## Why
`submit_ios_from_linux` UNKNOWN_ERROR analysis showed App Store Connect responses that clearly indicate the same version-train failure class but with mixed codes (`90062`, `90186`, `90478`).
Current handling recognizes only `90062` and `90186`, so runs that include `90478` fall back to `UNKNOWN_ERROR`.
## How
- extend `isClosedVersionTrainError` to include ASC code `90478` while keeping strict `.every` matching
- broaden `EAS_UPLOAD_TO_ASC_CLOSED_VERSION_TRAIN` user-facing message to cover both closed train and lower-than-approved version cases
- update unit test to include `90478` in positive closed-train detection
## Examples
Existing `EAS_UPLOAD_TO_ASC_CLOSED_VERSION_TRAIN` runs:
- https://expo.dev/uuid/019cbe83-ac3b-756f-b7ef-447bae5ef4dc
- https://expo.dev/uuid/019cbe66-4f9b-7d95-a35e-06886b646434
Would-be closed-train runs currently persisted as `UNKNOWN_ERROR` (log errors include `90478` with `90062`/`90186`):
- https://expo.dev/uuid/019cbe71-62fa-7fee-9e77-bdc051cc6e8b
- https://expo.dev/uuid/019cbe44-5c75-7211-af66-35fe96a86903
## Test Plan
- `yarn --cwd packages/build-tools jest-unit src/steps/functions/__tests__/uploadToAsc.test.ts`
- `yarn --cwd packages/build-tools typecheck`
- `yarn fmt`
## Why
Uploads to App Store Connect can fail with code `90683` when required `*UsageDescription` privacy keys are missing in `Info.plist`.
Without dedicated handling this ends up as a generic upload failure, even though ASC already returns structured details that can guide the user.
## How
- add ASC error recognition for `90683` in `uploadToAsc` failed-state handling
- throw a specific `UserFacingError` with code `EAS_UPLOAD_TO_ASC_MISSING_PURPOSE_STRING`
- parse ASC error descriptions to extract and list missing `*UsageDescription` keys
- provide concrete remediation for both CNG (`ios.infoPlist`) and non-CNG (`Info.plist`) workflows
- set `docsUrl` on the user-facing error to Expo permissions docs
- add unit tests for detection and missing-key parsing helpers
## Test Plan
- `yarn --cwd packages/build-tools jest-unit src/steps/functions/__tests__/uploadToAsc.test.ts`
- `yarn --cwd packages/build-tools typecheck`
- `yarn fmt`
## Why
Some App Store Connect uploads currently end up as generic failures even when ASC returns explicit bundle identifier mismatch validation ([`90054`](https://expo.dev/accounts/dobrokruh/projects/dobrokruh/job-runs/019cb865-ef97-71d1-9137-f6ae4c05d94d)/[`90055`](https://expo.dev/accounts/central-studio/projects/hfc-fuels/job-runs/019cb882-1550-7801-9b4b-9647e1bce364)). We want a user-facing error that explains the mismatch and shows both identifiers so users can quickly determine whether they selected the wrong app or the wrong build profile/build.
## How
- add `isInvalidBundleIdentifierError` detector in `uploadToAsc` for ASC error codes `90054`/`90055`
- when matched, throw `UserFacingError` with code `EAS_UPLOAD_TO_ASC_INVALID_BUNDLE_ID`
- include both identifiers in message:
- IPA bundle identifier (best-effort read via `readIpaInfoAsync`)
- selected ASC app bundle identifier
- provide remediation covering both paths:
- wrong selected app identifier in submit profile
- wrong build selected / rebuild with different profile
- use `asyncResult` for best-effort IPA introspection (no nested catch needed)
- add unit tests for invalid bundle-id detector
## Test Plan
- `yarn --cwd packages/build-tools jest-unit src/steps/functions/__tests__/uploadToAsc.test.ts`
- `yarn --cwd packages/build-tools typecheck`
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Older (default) Android system image package does not support `-z`.
```
Forward stdin/stdout to a file or network connection.
-4 Force IPv4
-6 Force IPv6
-L Listen for multiple incoming connections (server mode)
-U Use a UNIX domain socket
-W SECONDS timeout for more data on an idle connection
-f Use FILENAME (ala /dev/ttyS0) instead of network
-l Listen for one incoming connection
-p Local port number
-q Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet
-s Local source address
-t Allocate tty (must come before -l or -L)
-u Use UDP
-w SECONDS timeout to establish connection
```
# How
Replaced `-z` with a closed stdin.
# Test Plan
System tests should work.
Deployed worker from this branch at https://github.com/expo/eas-cli/actions/runs/22666833774/job/65700594158.
Confirmed works at https://staging.expo.dev/accounts/expo-services/projects/worker-system-tests/workflows/019cb88e-f710-74d3-87ba-3c17bfe45c00.
## Why
Generic/custom workflow steps can throw `UserFacingError`, but worker-level error handling currently maps any non-`BuildError` to `UnknownBuildError` / `UnknownCustomBuildError`. That causes actionable step errors to be persisted and exposed as `UNKNOWN_ERROR`.
## How
- add a `toBuildError` conversion in worker service catch path
- preserve existing `BuildError` values
- convert `UserFacingError` into `BuildError` with the same code/message/docsUrl
- keep unknown fallbacks only for truly unstructured errors
- add integration coverage in `stateSync` to assert generic job `UserFacingError` is exposed in `externalBuildError` and `internalErrorCode`
We should make a bigger refactor to error handling, but it's more involved — https://github.com/expo/eas-cli/pull/3447.
## Test Plan
CI should pass.
```
PASS src/__integration__/stateSync.test.ts
State sync mechanism
query new worker
✓ should return 'new' state (210 ms)
query worker after dispatch
✓ should return 'in-progress' state (170 ms)
query worker after build
✓ should return 'success' state (2062 ms)
query worker after error
✓ should return 'error' state with artifacts from error (88 ms)
✓ should expose user-facing error from generic job (60 ms)
```
Co-authored-by: Copilot <[email protected]>
https://github.com/user-attachments/assets/37835e4d-fca0-48a3-87e7-8c26e0c80a32
## Summary
- When running `eas go` while not logged in, an `ora` spinner ("Logging in to Expo...") was started before `getContextAsync` was called
- `getContextAsync` triggers interactive login prompts when unauthenticated, but the active spinner animation conflicts with readline input display, causing garbled/invisible prompts
- Fix: remove the spinner before `getContextAsync` and replace with `Log.withTick(...)` after it completes
## Test plan
- [ ] Run `eas go` while not logged in and verify login prompts are visible and interactive
- [ ] Run `eas go` while already logged in and verify "Logged in as ..." tick appears as expected
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
## Why
App Store Connect build upload failures were often surfaced as generic errors, which made remediation unclear for common cases like duplicate build numbers. We also needed stricter and safer response parsing so JSON parsing failures don’t leak raw parse errors.
## How
- Added typed `AscApiRequestError` in `AscApiClient` for structured ASC error payloads only.
- Kept non-structured ASC failures as regular `Error`.
- Hardened response parsing in `AscApiClient`:
- parse response text with `asyncResult` + `JSON.parse`,
- convert invalid success JSON into a controlled `Malformed JSON response...` error.
- Added `AscApiUtils.createBuildUploadAsync` and switched `uploadToAsc` to call it.
- Added duplicate build-number recognition for `/v1/buildUploads` failures when all ASC error codes are `ENTITY_ERROR.ATTRIBUTE.INVALID.DUPLICATE`.
- Added specific `UserFacingError` (`EAS_UPLOAD_TO_ASC_VERSION_DUPLICATE`) with concrete remediation:
- increment `ios.buildNumber` (or set `"autoIncrement": true`),
- rebuild and resubmit,
- include docs URL.
- Inlined closed-train constants in `uploadToAsc` as requested.
## Test Plan
- `yarn --cwd packages/build-tools jest-unit src/steps/utils/ios/__tests__/AscApiClient.test.ts`
- `yarn --cwd packages/build-tools jest-unit src/steps/utils/ios/__tests__/AscApiUtils.test.ts`
- `yarn --cwd packages/build-tools jest-unit src/steps/functions/__tests__/uploadToAsc.test.ts`
All commands above pass on this branch.
# Why
This adjusts the change in #3418 that added a requirement for the `--environment` flag in `eas update` for SDK 55 and greater.
The requirement should not have applied to the `update:configure` subcommand. This PR removes the requirement there.
# How
Remove the check in `configure.ts`, and adjust flag descriptions.
# Test Plan
Existing tests should pass.
# Why
When yarn moved to version 4, they removed the `--silent` flag. Because of this change, any use of yarn to call scripts and get output will also get yarn debugging garbage, and there is no way to suppress it.
The release scripts are mostly ok with this, except for calling the `next-version` script. The output of this script has to be clean for it to be used as input for `lerna version`.
# How
Replaced the yarn call with a direct invocation of the node Typescript source, bypassing yarn.
# Test Plan
Since the `trigger-release.yml` workflow supports a dry run mode, it's safe to modify it to check out a test branch and run the workflow many times to debug the issue.
Once this change is merged, a dry run invocation of the workflow should succeed even if no version string is passed in.
# Why
Problems can occur if an update intended for a development build is published with the environment defaulting to or set to production, and vice versa.
To prevent such problems in the future, this PR makes the `--environment` flag a required flag for projects using SDK 55 and greater.
# How
Add a new utility function to throw an error if sdkVersion does not meet the requirement, and use that function in `eas update:configure` and `eas update`.
Skip the check if EAS_BUILD env is set.
# Test Plan
Unit tests added.
Testing locally with different projects.
## Why
Release publish failed in `Publish to npm` for `v18.0.2`.
- `packages/eas-cli/scripts/prepack.js` invoked `yarn oclif manifest`, which fails on Yarn v4 (`Couldn't find a script named \"oclif\"`).
- `packages/create-eas-build-function` `clean` script used an unquoted `*.tsbuildinfo` glob, which fails when no files match.
## How
- Update `packages/eas-cli/scripts/prepack.js` to run `yarn run -T oclif manifest`.
- Quote the tsbuildinfo glob in `packages/create-eas-build-function/package.json`:
- `rimraf ./build/ "*.tsbuildinfo"`
## Test plan
- `cd packages/eas-cli && mise exec [email protected].4 -- node ./scripts/prepack.js`
- `cd packages/create-eas-build-function && mise exec [email protected].4 -- yarn run clean`
- CI
## Summary
- introduce a shared `Hooks` type/schema with reusable Zod/Joi validation so any string key maps to step arrays
- wire the new hooks definition through the generic, Android, and iOS job schemas and exports
- expand existing tests to cover accepting arbitrary hook names, empty hook arrays, and invalid hook step payloads
Not sure if it makes sense to make this "smart". I think let's just roll this out manually? Like, have `eas/install_node_modules` steps be sort of manually wrapped with hooks? Or maybe we'll sprinkle them when parsing the steps. I'll see. What I think is right is _not_ to limit the keys to only a few known values.
## Test plan
CI should pass.
## Why
In https://github.com/expo/eas-cli/pull/3406 EAS workflow building the worker was **not** updated to Yarn v4. This breaks building worker.
I tried adding `defaults.tools.yarn: 4.12.0`, but this unfortunately [is **not** the way to use Yarn v4 on EAS as I've learned](https://docs.expo.dev/more/create-expo/#yarn-2-modern). The right way is using Corepack.
However, previously we explicitly did **not** use Corepack, because `pnpm --version` check the worker does in the beginning of its run was failing because it was run without `cwd`, so it was running within worker package which was configured with Yarn.
Since we want to use Yarn v4, we need to figure out a way to use Corepack.
## How
- Enabled Corepack.
- Set up `yarn` executable like the one we have in `universe`.
- Changed `pnpm --version` to **not** run inside worker (so it does not error).
- Removed `setup-node` for specific Node versions in favor of a Mise override.
## Test plan
- Corepack + Yarn resolution checks (local):
- `mise exec [email protected].4 -- bash -lc 'corepack enable; yarn --version'` => `4.12.0`
- same check from `scripts/` => `4.12.0`
- Worker runtime unit test (local):
- `mise exec [email protected].4 -- bash -lc 'corepack enable; yarn workspace @expo/worker test:unit -- runtimeEnvironment.test.ts'`
- GitHub workflow runs:
- success on Corepack worker workflow update: https://github.com/expo/eas-cli/actions/runs/22133707462
- latest run for full set of changes: https://github.com/expo/eas-cli/actions/runs/22133932635
## Why
- Repository maintenance: standardize on Yarn 4 managed via Mise.
- Prepare for introducing minimum package-age constraints in dependency policy.
## How
- Migrated repo tooling to Yarn 4 with Mise.
- Updated CI and scripts for Yarn 4 behavior:
- Lerna invoked via `yarn run -T lerna`.
- Coverage args forwarded correctly (`-- --coverage`).
- Removed unsupported Yarn 4 `--silent` usage.
- Added missing package-local script dependencies surfaced by Yarn 4 (`jest`, `oxlint`, `rimraf`).
- Increased `EasCommand` coverage test timeout from 30s to 60s. (Was consistently failing in CI.)
## Test Plan
- CI only: `Run tests` matrix (including Node 20 coverage) and other touched workflows.
- Release behavior will be verified during the normal release run.
# Why
We need a build function that can read metadata directly from an IPA so later steps (for example App Store Connect upload flows) can consume canonical bundle values without requiring manual input.
# How
- Added a new build function `eas/read_ipa_info` in `packages/build-tools/src/steps/functions/readIpaInfo.ts`.
- The function accepts `ipa_path` and outputs:
- `bundle_identifier`
- `bundle_short_version`
- `bundle_version`
- IPA inspection reads `Payload/*.app/Info.plist` from the zip and supports both plist formats commonly seen in IPAs:
- binary plist (`bplist00`) via `bplist-parser`
- XML plist via `plist`
- Added `UserFacingError` handling for parsing failures/invalid binary plist.
- Added the function to the EAS function registry in `packages/build-tools/src/steps/easFunctions.ts`.
- Added fixture-based tests using `SmallestAppExample.ipa` under `packages/build-tools/src/steps/functions/__tests__/fixtures/`.
- Added `node-stream-zip` and pinned `bplist-parser` to `0.3.2`.
# Test Plan
- Automated tests:
- `yarn --cwd packages/build-tools test src/steps/functions/__tests__/readIpaInfo.test.ts`
- Typecheck:
- `yarn --cwd packages/build-tools typecheck`
Coverage in `readIpaInfo.test.ts`:
- reads bundle identifier/short version/version from the fixture IPA
- fails when `Info.plist` is missing
- fails when required plist keys are missing
- verifies build-function outputs are populated correctly
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
For the new logs experience we need to identify every log with a unique ID.
Also, in the new logs experience we're going to be handling logs in plaintext, uncompressed, so size starts to matter.
# How
Decorating every log with a unique ID is surprisingly difficult with bunyan. It only runs serializers on the object passed in, I tried adding a `log_id` serializer `serializers: { log_id: () => uuidv7() }` and a non-empty value to build logger, but it was getting serialized in the moment of logger creation.
Instead, I'm adding `log_id` in the `Transform` that also masks secrets. The overall architecture looks like this now:
<img width="1742" height="1126" alt="Bez tytułu-2026-02-04-1436-3" src="https://github.com/user-attachments/assets/956e1b58-75ca-41c5-92ba-8229dd981ff6" />
Also removes `service: 'worker'` and `hostname` from logs. `service` was only being used [here](https://github.com/expo/universe/blob/3246198a3f913bf6fd0fd82e8e3df402cb59e82e/server/website/common/logs-utils.ts#L218) which I don't think is a thing right now.
# Test Plan
Added unit test that ensures `Transform` adds `logId`.
<img width="1257" height="1102" alt="Zrzut ekranu 2026-02-12 o 16 02 32" src="https://github.com/user-attachments/assets/4cfbbf43-744f-4af0-9faf-de0cab54f178" />
## Summary
- extend the `upload_to_asc` build status polling window from 10 minutes to 30 minutes so slowly processed builds have time to reach TestFlight
- keep the rest of the polling logic and `wait_for_processing` default untouched
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
After a new release is cut, `lerna.json` and `README.md` want to be reformatted by Oxfmt.
# How
Excluded them from being formatted.
# Test Plan
`yarn fmt` changes no files.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We're moving to Oxc in universe too. The toolset is faster than ESLint / Prettier.
# How
Asked Codex to migrate the repository. I don't think all rules got migrated, unfortunately, but also the lint are in a bit weird state (different rules in `eas-cli` vs the rest of the repo). I hope we can unify the rules soon.
# Test Plan
CI should pass.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Release failed because in `prepack` in some packages we delete `dist`, but don't delete `.tsbuildinfo` file.
# How
Made Codex fix all the package scripts. I _think_ we also could skip `yarn build` before publishing.
# Test Plan
Try to release and see if it works.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Our GitHub released executable Oclif bundles of `eas-cli` are… not too popular. v16.28.0 was downloaded 154k times in the last 7 days from NPM. Since its release (2 months ago) it was downloaded from GitHub 82 times.
<img width="1247" height="491" alt="Zrzut ekranu 2026-01-30 o 15 15 35" src="https://github.com/user-attachments/assets/9c5a904a-e00e-43ee-9875-d1cea15b2108" />
# How
Asked Gemini to remove this. This should speed up release process significantly. This release process has been created 5 years ago (https://github.com/expo/eas-cli/pull/54).
Also removed size comparison workflow. It's not going to make comments like https://github.com/expo/eas-cli/pull/3361#issuecomment-3824036144.
Closes https://github.com/expo/eas-cli/pull/3346.
# Test Plan
CI should pass.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I noticed I didn't migrate all workflows to Mise (because not all worklfows were using Volta lol).
# How
Codex added a shared Mise action (in other repos we have it set up like this too) and used it in all places where we require Node related to code (there's one workflow which does not use checkout, it remains on `setup-node` too). `test.yml` where we test against different Node versions still uses `setup-node`.
Note: this does downgrade Node in a few workflows from 22 to 20, but if 20 is what we decide to use for our development maybe CI should use it too?
# Test Plan
CI should pass.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
When oclif is building tarballs with executables it does so in a directory separate from the monorepo which requires us to change `eas-cli` dependencies from the monorepo to `file`.
# How
Asked Gemini to update the script to include all local dependencies of `eas-cli`.
Or… we can land https://github.com/expo/eas-cli/pull/3361 …
# Test Plan
Release should pass. Validated locally. (Hmm but on CI it failed? Will see.)
Ok, so size failed because it ran on `main` which is broken because it lacks this pull request.
<img width="944" height="1031" alt="Zrzut ekranu 2026-02-5 o 19 05 41" src="https://github.com/user-attachments/assets/1134493c-bbdb-4f08-85d6-07e59fa28750" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I want to iterate on this faster.
# How
Asked Codex to move this to build functions.
# Test Plan
Unit tests were moved too. Land and test on staging.
# How
I like these flag names a bit better (AI preferred them too). Also made it so we don't wait for build processing by default.
# Test Plan
Tested manually.
# Why
The Cuttlefish device may remain locked after an initial `KEYCODE_MENU` event which blocks reaching the home screen, so the unlock flow must verify the real lock state instead of blindly sending HOME. See https://exponent-internal.slack.com/archives/C02VC9BLMQW/p1769703880840729?thread_ts=1763747642.435979&cid=C02VC9BLMQW.
# How
- Updated `packages/build-tools/src/steps/functions/startCuttlefishDevice.ts` to poll `adb shell dumpsys window` and check `mDreamingLockscreen` before deciding the device is unlocked.
- Implemented a retry loop that sends `adb shell input keyevent 82` while the lockscreen remains active, waits 1s between attempts, and uses a 30 second deadline for the unlock attempts.
- When unlock is detected the code now sends `adb shell input keyevent 3` to return to the home screen and logs success, and it logs warnings on query failures or on timeout.
# Test Plan
- Ran `yarn typecheck` which completed successfully.
- Ran `yarn lint --fix` which completed successfully.
------
[Codex Task](https://chatgpt.com/codex/tasks/task_e_698374b75b88832890754e697e58e5ea)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I knew https://github.com/expo/eas-cli/pull/3366 won't work! ([Failure](https://github.com/expo/eas-cli/actions/runs/21709140672/job/62608616635).)
Using corepack for Yarn breaks EAS Build because when we run `pnpm --version` when setting up the environment, it runs in default cwd which is the worker directory and if worker has `packageManager` different than PNPM, PNPM throws an error. This was originally found in February 2025 by @szdziedzic.
# How
Use Mise for Yarn installation (instead of corepack).
# Test Plan
Merge and see if system tests work.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I think we migrated from Volta to Mise in… most if not all places?
# How
I think I let Codex do all the work, nothing too difficult. Grepped repo for "volta" leftover afterwards.
One thing I'm not sure of is whether worker is going to work. I remember trying to remove Volta in `turtle-v2` and it wasn't working for some reason? We'll see.
# Test Plan
Compared these changes with https://github.com/expo/universe/commit/acca8169746c5cb4d708add083f77b927341ae4a.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We moved more packages into this monorepo and the existing test setup didn’t scale well:
- the root Jest config only covered a subset of packages,
- PRs ran heavier “all tests” workflows,
- worker builds ran on PRs even though typecheck + tests were enough.
This PR aligns testing with the dependency graph, reduces unnecessary CI work, and standardizes Jest config handling.
# How
- Switched root testing to Lerna and updated docs.
- CI now runs affected+dependent tests on PRs and all packages on main.
- Coverage runs via Lerna with per-package reports (no merge) and is kept for PRs.
- Worker builds are skipped on PRs; worker workflow triggers include dependency paths on main.
- All Jest configs are now TypeScript with a shared base (`jest/jest.shared.config.ts`) and use `@jest/types` to avoid TS config parsing errors.
- CI stays unit-only (no integration tests).
# Test Plan
Not run locally. CI covers:
- `yarn lerna run test` (affected on PRs, all on main)
- `yarn lerna run test -- --coverage`
* [eas-cli] Don't show build credits warning bar at 100% usage
The warning bar is meant to alert users when they're approaching their
limit. At 100%, they've already hit it, so the bar is redundant.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Update CHANGELOG for #3371
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [eas-cli] Hide progress bar (not warning) at 100% usage
The warning should still show at 100% to inform users they've hit the
limit, but the progress bar is redundant when completely full.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
---------
Co-authored-by: Claude Opus 4.5 <[email protected]>
* Improve error message for Apple team selection in non-interactive mode
Enhanced the error thrown when selecting an Apple team in non-interactive mode to include a list of available teams and guidance on using the --apple-team-id flag. This provides better context and instructions for users running the CLI in non-interactive environments.
* List available options in non-interactive mode errors across all selection prompts
Non-interactive mode errors now include the available options so agents and
scripts can discover valid values and retry with the correct flag. This applies
to selection prompts for Apple teams, Apple devices, builds, branches, channels,
update groups, runtimes, rollout actions, and environment variable type/visibility/environment.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Fix test expectation and update changelog PR number
Update test for selectUpdateGroupOnBranchAsync to match the new error
message when no update groups are found in non-interactive mode. Update
changelog entry with PR #3359.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Fix prettier formatting
Co-Authored-By: Claude Opus 4.5 <[email protected]>
---------
Co-authored-by: Claude Opus 4.5 <[email protected]>
`package.sh` currently does not copy workspace packages into the temporary build folder which makes worker pull packages from NPM.
Instead, we want to use local versions from workspace.
Added `copy_package` calls for all dependencies of `@expo/worker`.
It was done in a similar way in `turtle-v2` — https://github.com/expo/turtle-v2/blob/245eaf23492f2dcd9204a4606bb95c109208d29e/src/services/worker/package.sh#L46-L47.
Ran `./package.sh` and confirmed `@expo/eas-build-job` and other packages are symlinked.
## Consolidate eas-build packages into eas-cli monorepo
This PR completes the migration of packages from the `eas-build` repository into `eas-cli`, consolidating all EAS Build tooling into a single monorepo.
### Background
Previously, the EAS Build libraries lived in a separate `expo/eas-build` repository. This made development and releases more complex, requiring coordination between two repos. By consolidating into `eas-cli`, we can:
- Develop and test changes across CLI and build tools in a single PR
- Simplify the release process
- Reduce dependency version drift between packages
### Migrated Packages
The following packages have been moved from `eas-build`:
| Package | npm Name | License |
|---------|----------|---------|
| `build-tools` | `@expo/build-tools` | BUSL-1.1 |
| `eas-build-job` | `@expo/eas-build-job` | MIT |
| `steps` | `@expo/steps` | BUSL-1.1 |
| `logger` | `@expo/logger` | BUSL-1.1 |
| `downloader` | `@expo/downloader` | BUSL-1.1 |
| `turtle-spawn` | `@expo/turtle-spawn` | BUSL-1.1 |
| `template-file` | `@expo/template-file` | BUSL-1.1 |
| `local-build-plugin` | `eas-cli-local-build-plugin` | BUSL-1.1 |
| `create-eas-build-function` | `create-eas-build-function` | MIT |
### Changes
**Package Configuration:**
- Updated `repository` and `bugs` URLs in all migrated package.json files to point to `expo/eas-cli`
- Updated README repository links
- Aligned dependency versions across `eas-cli`, `eas-json`, and `worker` to use workspace packages
**Documentation:**
- Expanded `CLAUDE.md` with comprehensive documentation covering all packages, architectural patterns, and development workflows
- Added `AGENTS.md` for AI agent guidance
**Licensing:**
- Added `LICENSE-BUSL` for BUSL-1.1 licensed packages
- Added `LICENSE-eas-build-job` for MIT licensed packages
**Build Infrastructure:**
- Added `.gitignore` entries for build artifacts: `dist`, `*.tsbuildinfo` (needed for `tsconfig.json` and `tsconfig.build.json`), vim swap files
- Added `bin/eas-cli-local-build-plugin` symlink for local build testing
**Dependency Cleanup:**
- Removed stale npm registry entries from `yarn.lock` - workspace packages now resolve locally
### Testing
- [x] `yarn install` completes successfully
- [x] `yarn build` builds all packages
- [x] `yarn test` passes
- [x] Worker builds and runs correctly against workspace packages
### Follow-up
After this PR is merged:
- Archive or deprecate the `expo/eas-build` repository
- Update any CI/CD pipelines that referenced the old repo
- Update internal documentation pointing to eas-build
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Noticed we're not running tests on Node 18 anymore (since https://github.com/expo/eas-cli/commit/6bb09c4e99950a6b46b0b908a93e8fcd9b3002aa). I think we probably want to officially drop support for Node 18 too.
# How
Looked at https://github.com/expo/eas-cli/commit/eb4c5e073d02f38d7f90fbd6a1b2b5491dc40464, pinned Node to a newer version, updated types, adjusted `engines`.
# Test Plan
CI should pass.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We want to move iOS submissions to Linux machines, which requires us to either:
- have Builds generate not only an IPA but also an Xcode asset file for use with Transporter
- reimplement upload ourselves with App Store Connect API.
# How
As much as I fear the unknown (does this support App Clips? do App Clips come in a different package files? what about macOS apps?) I wonder if, by any chance, this would… just work?
Planning to wire this to submissions in some opt-in way and ask for early feedback in Discord.
# Test Plan
Tested manually — uploaded a file as IPA. It obviously failed to process, but at least it uploaded all right.
```
Generating JWT...
Reading App information...
Uploading Build to "turtle-cli-example" (com.expo.turtle.cli.example)...
Creating Build Upload...
Build Upload initialized (ID: 6a3f6a72-d088-4ac8-9cdd-7d1fb83f7c8b). Preparing IPA upload...
IPA Upload initialized (ID: 0374ffc4-c51b-42df-9b2f-48e9a81a62eb). Uploading IPA...
Uploading chunk 1/1 (offset: 0, length: 359)...
Chunk 1/1 uploaded.
Committing upload...
Checking upload file status...
File upload (ID: 0374ffc4-c51b-42df-9b2f-48e9a81a62eb) complete!
Checking build upload status...
Waiting for build upload to finish... (status = PROCESSING)
Waiting for build upload to finish... (status = PROCESSING)
Waiting for build upload to finish... (status = PROCESSING)
Waiting for build upload to finish... (status = PROCESSING)
Waiting for build upload to finish... (status = PROCESSING)
Waiting for build upload to finish... (status = PROCESSING)
Waiting for build upload to finish... (status = PROCESSING)
Errors:
- Invalid package. The uploaded package is corrupt. Verify that you have sufficient disk space on your computer and are uploading only one package at a time. If you created the package manually, verify that it‘s a valid ZIP archive file. (90168)
Build upload (ID: 6a3f6a72-d088-4ac8-9cdd-7d1fb83f7c8b) failed.
Error: submit:upload-to-asc command failed.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```
## Summary
Add a new `eas account:usage` command that displays account usage and billing information for the current billing cycle. The command is hidden for now, until we fully test it in production.
```
USAGE
$ eas account:usage [ACCOUNT_NAME] [--json --non-interactive]
ARGUMENTS
ACCOUNT_NAME Account name to view usage for. If not provided, the account will be selected
interactively (or defaults to the only account if there is just one)
FLAGS
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
view account usage and billing estimates for the current cycle
```
- View EAS Build usage with iOS/Android platform breakdown
- View EAS Update usage (MAU and bandwidth)
- Display billing period dates and progressOptional account name argument
- Display upcoming invoice, similarly to the billing website
- If no account name passed in, and user has more than one account, a selection list is shown
- `--json` flag for JSON output (optimized for agents/automation)
- Supports `--non-interactive`
- Forces JSON output
- Requires account name if user has more than one account
## Example Output
```
✔ Usage data loaded for example-customer
Account: example-customer
Plan: Production
Concurrencies: 6 total (iOS: 6, Android: 6)
Billing Period: Jan 9, 2026 - Feb 9, 2026
Days: 18 elapsed / 31 total (14 remaining)
EAS Build
Builds (plan): 10,000/10,000 builds
████████████████████ 100%
Builds (overage): 781 builds ($1462.00)
Breakdown by platform/worker:
Android large: 86 builds
iOS medium: 695 builds
EAS Update
Unique Updaters (plan): 50,000/50,000 users
████████████████████ 100%
Unique Updaters (overage): 1,021,888 users ($5109.44)
Bandwidth (plan): 17.7 TiB/40.0 TiB
█████████░░░░░░░░░░░ 44%
Billing
Addons:
Additional Concurrency: 4
Upcoming invoice:
EAS Build - Plan credit: $-100.00
EAS Build - Build (Android: 64 large builds; iOS: 628 medium builds): $1384.00
EAS Update - 1,094,102 monthly active users: $3857.30
EAS Workflows - 5,347 jobs (3,970.4 minutes): $71.46
1 × Expo Application Services - Production (at $99.00 / month): $99.00
4 Concurrency × EAS Build - Additional Concurrency (at $50.00 / month): $200.00
Invoice total: $5511.76
View detailed billing: https://expo.dev/accounts/example-customer/settings/billing)
```
## Test plan
- [x] Build passes (`yarn build`)
- [x] TypeScript type check passes (`yarn typecheck`)
- [x] Lint passes for new files
- [x] Unit tests pass (`yarn test packages/eas-cli/src/commands/account/__tests__/usage-test.ts`)
- [x] Manual testing with real account
Slack thread: https://exponent-internal.slack.com/archives/C017N0N99RA/p1769054123592549?thread_ts=1768439335.822519&cid=C017N0N99RA
Closes ENG-18827
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
> Apple's altool in Xcode 26.0 has a bug where it incorrectly selects the wrong app when multiple apps share a common bundle ID prefix (e.g., `com.example`, `com.example.app1`, `com.example.app2`). This causes builds to be uploaded to the wrong app on App Store Connect.
> See: https://github.com/fastlane/fastlane/issues/29698https://github.com/expo/universe/pull/23310 + https://exponent-internal.slack.com/archives/C06EFBQK3B7/p1765365928911459
# How
If `xcodebuild -version` matches "Xcode 26.0", we'll add `DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS='--use-old-altool'`. This helps if the code does not re-override `$DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS` further, in which case it should do `DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS="overrides $DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS"` or sth like that.
I hope this fixes Launch.
# Test Plan
Tested manually on my computer
```
> spawnSync("xcodebuild", ["-version"]).stdout.includes("Xcode")
true
> spawnSync("xcodebuild", ["-version"]).stdout.includes("Xcode 26.0")
false
(below did not throw)
> spawnSync("abc")
{
error: Error: spawnSync abc ENOENT
at Object.spawnSync (node:internal/child_process:1123:20)
at spawnSync (node:child_process:877:24)
at REPL12:1:1
at ContextifyScript.runInThisContext (node:vm:137:12)
at REPLServer.defaultEval (node:repl:598:22)
at bound (node:domain:433:15)
at REPLServer.runBound [as eval] (node:domain:444:12)
at REPLServer.onLine (node:repl:927:10)
at REPLServer.emit (node:events:536:35)
at REPLServer.emit (node:domain:489:12) {
errno: -2,
code: 'ENOENT',
syscall: 'spawnSync abc',
path: 'abc',
spawnargs: []
},
status: null,
signal: null,
output: null,
pid: 0,
stdout: null,
stderr: null
}
```
* bump apple utils
* Add App Clip support to iOS bundle ID registration
Detects App Clips via entitlements and registers App Clip bundle identifiers with parent app relationships. Updates related interfaces and logic to handle App Clip-specific requirements during bundle ID creation.
* Update CHANGELOG.md
* Update ensureAppExists.ts
## Why
The build-and-deploy-worker workflow had three separate jobs (setup, build-workers, deploy) with complex inter-job dependencies and redundant conditional logic. I think if we put it all in one job it should make stuff faster.
## How
Consolidated all three jobs into a single `build-and-deploy` job with conditional steps:
1. **Check**: Verify if tarballs for the current SHA exist in GCS (when deploying)
2. **Build**: Execute EAS workflow if needed (PR testing or cache miss)
3. **Upload**: Upload tarballs to GCS with SHA-based naming
4. **Deploy**: Copy tarballs to environment-specific names (when deploying)
Key simplifications:
- **Assumption**: Main branch always specifies an environment (staging/production), so `environment == ''` only occurs on PR builds
- **SHA-based caching**: Check cache by SHA regardless of branch - if the code is identical (same SHA), reuse existing tarballs
- **Clearer conditions**: Each step has a single clear purpose without overlapping branch-specific logic
I also added back building Linux tarball on Linux not to mix CPU architectures accidentally.
## Test Plan
[Build on PR](https://github.com/expo/eas-cli/actions/runs/20920297113/job/60104039095?pr=3303). [Deployment from a branch](https://github.com/expo/eas-cli/actions/runs/20921082109/job/60106516235).
Co-authored-by: Claude <[email protected]>
# Why
- Build Android and iOS worker tarballs together in a single EAS workflow run
- Avoid split builds across different machines and simplify uploads
# How
- Update the EAS workflow to build and upload both iOS and Android tarballs
- Update the GitHub Actions workflow to run the EAS workflow once and upload both artifacts
- Cancel the EAS workflow run when the GitHub Actions job is canceled
# Test plan
- Verified auto-cancel behavior: https://github.com/expo/eas-cli/actions/runs/20849238272/job/59900072125
# Why
- Canceling the GitHub Actions workflow should cancel the underlying EAS build/workflow runs to avoid wasting resources.
# How
- Start the iOS build and Android workflow with `--no-wait` and capture their IDs from JSON.
- Poll the EAS build/workflow statuses to determine success/failure.
- Persist IDs to `GITHUB_ENV` and cancel them in a `if: cancelled()` step.
# Test Plan
https://github.com/expo/eas-cli/actions/runs/20859556010/job/59935355509
* Handle missing Apple metadata gracefully in tasks
Updated Apple metadata tasks to skip operations when app version or info is not available, instead of throwing errors. This improves support for cases where the app or version has not been set up yet, particularly for metadata:pull. Tests have been updated to reflect the new behavior.
* Update CHANGELOG.md
This PR adds system tests that run after staging deployment and gate production deployment.
## Changes
- Add `system-tests.yml` workflow (can be dispatched manually or called from worker.yml)
- Add EAS workflow fixture for Android build
- Gate production deployment on system tests passing
- Run iOS build (`eas build`) and Android build (`eas workflow:run`) concurrently
## Testing
Once merged, the workflow can be manually dispatched to test, or it will run automatically on the next push to main that touches worker files.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Gives us more concurrencies for building worker (which is not a huge problem, but may be nice). Also, IF we botched worker staging, we won't break the whole pipeline (system tests won't let worker deploy to production so worker in production will still work and let us rebuild worker).
# How
Changed app ID and token to expo.dev ones.
# Test Plan
CI ran ok.
# Why
The worker integration tests were slow and required platform-specific CI runners (macOS for iOS, Linux for Android) because they attempted to build real React Native apps. This made the CI pipeline complex, slow, and resource-intensive.
# How
- **Replace full-build tests with fast mocked tests**: Instead of running actual Android/iOS builds, we now mock `@expo/build-tools` at the library boundary. This lets us test the worker's WebSocket communication, job dispatch, state sync, abort handling, and hanging worker detection without the overhead of real builds.
- **Add new `jobExecution.test.ts`**: A new integration test that verifies the worker accepts jobs, executes them (via mocked builders), and returns success/error responses correctly.
- **Update existing tests**: `abortBuild.test.ts`, `stateSync.test.ts`, and `possiblyHangingWorker.test.ts` now mock `@expo/build-tools` instead of the worker's internal `build.ts` module, allowing more of the real code path to execute.
- **Simplify CI**: Consolidated the separate `worker-android-checks` and `worker-ios-checks` jobs into a single `worker-checks` job running on `ubuntu-latest`. Removed dependencies on `direnv`, `setup-gcloud`, and platform-specific scripts.
- **Cleanup**: Deleted unused files including `__mocks__/build.ts`, macOS-specific Jest config, CI shell scripts, and the `direnv` internal action.
The build-build part is going to be tested in system tests running in CI on `main`.
# Test Plan
cd packages/worker
yarn test:integrationAll 19 tests pass in ~6 seconds (down from minutes with real builds).
```bash
cd packages/worker
yarn test:integration
```
All 19 tests pass in ~6 seconds (down from minutes with real builds).
## Why
The `worker.yml` GitHub Actions workflow was recently moved from a private repository to this public one. This means we lost access to private GitHub Actions runners and now have to wait in long queues for public `macos-latest` runners when building the iOS worker tarball.
## How
Instead of building the iOS worker tarball on GitHub Actions `macos-latest`, we now:
1. **Trigger an EAS Workflow** from GitHub Actions that builds the tarball on EAS's macOS runners
2. **Upload the tarball as an EAS artifact** using `eas/upload_artifact`
3. **Uploads the artifact to tarball bucket** from GitHub Actions
### Changes
- Added `packages/worker/app.json` - minimal Expo app config required for EAS
- Added `packages/worker/eas.json` - EAS configuration
- Added `packages/worker/.eas/workflows/build-worker.yml` - EAS Workflow that builds the iOS worker tarball and uploads it as an artifact
- Updated `.github/workflows/build-and-deploy-worker.yml`:
- Split the matrix build into separate `build-android` and `build-ios` jobs
- `build-ios` now runs on `ubuntu-latest` and triggers the EAS Workflow using `eas workflow:run --ref --wait --json`
- Extracts the artifact download URL from the workflow output and streams it directly to GCS
## Test Plan
https://github.com/expo/eas-cli/actions/runs/20796579975 Don't mind the CI failure on the PR, I dispatched the workflow manually later.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We want to streamline DX of the worker part of EAS. Part of it is colocating all code in one repository.
# How
Copied code over to `eas-cli`. Adjusted code — each commit represents a single piece of work towards adjusting code to this repository. The main changes are around removing dependency on `turtle-v2` internal libraries.
One thing to figure out still is deployment process. I've added `build-and-deploy-worker` which is capable of deploying to staging and production. The question is how to automate it. In `turtle-v2` we have system tests. Should we just copy them over to here? (Don't like that.) Should we streamline system tests now and instead of having this weird `turtle-v2-example` repo, create project on the go? Should we deploy worker manually for now?
I think I'd rather deploy manually for now?
# Test Plan
Deployed worker to staging. Ran system tests. They succeeded!! https://github.com/expo/turtle-v2/actions/runs/20042956545/job/57535011098
# Why
The CLI does not validate the project name and slug before creating the project on the server, leading to unnecessary GraphQL errors.
# How
Copy the server's self-contained validation code to the CLI. Eventually, this code should move to `eas-build` repo for use by both CLI and server. Add code to run the same validation checks that the server GraphQL resolver uses, and add a method to strip invalid characters from the project name before suggesting it at the prompt.
# Test Plan
The server's validation unit tests have been added here as well.
# Why
The command `eas credentials` does not provide a way to exit other than control-C, if no platform flag is passed in.
# How
Add an "Exit" choice to the platform prompt.
# Test Plan
Tested locally.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Node 24 is in LTS, it's time to officially support it and test for it.
# How
Add 24 to CI test matrix.
# Test Plan
CI
# Why
GraphQL test started failing today after a recent server change in updates GraphQL queries. Failed test run at https://github.com/expo/eas-cli/actions/runs/19529909252
# How
- Updated GraphQL generated code
- Fixed a TS type error in one test
# Test Plan
- CI should pass
# Why
In `workflow:status`, the argument name for the passed-in workflow run ID is incorrect. Instead of showing the status of that run, it shows the dialog to select from recent runs.
# How
Fixed the argument name.
# Test Plan
Works when testing locally.
# Why
Shows the status of a workflow run that has already started.
If the run is in progress, and the `--wait` flag is set, the command will show periodic updates on running jobs, the current job steps, and recent log lines, similarly to `eas workflow:run --wait`.
Otherwise, the command immediately returns with information on the run result, exactly as `eas workflow:run --wait` will show at the end of a run. If the run failed, the failed jobs, failed steps, and last few log lines are shown.
```bash
USAGE
$ eas workflow:status [WORKFLOW_RUN_ID] [--non-interactive] [--wait] [--json]
ARGUMENTS
WORKFLOW_RUN_ID A workflow run ID.
FLAGS
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
--[no-]wait Wait for workflow run to complete. Defaults to false.
DESCRIPTION
show the status of an existing workflow run. If no run ID is provided, you will be prompted to select from recent
workflow runs for the current project.
FLAG DESCRIPTIONS
--[no-]wait Wait for workflow run to complete. Defaults to false.
Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
```
# How
Leverages utility code already written for `eas workflow:run` and `eas workflow:logs`.
# Test Plan
- Tested on running and completed workflow runs.
- CI should pass.
# Why
The manual release workflow is broken after #3237, since the local plugin version is no longer hardcoded, but tied to the `@expo/eas-build-job` dependency.
# How
Remove this step from the workflow.
# Test Plan
Workflow should succeed in dry run mode.
# Why
Provide a way to move the "latest-eas-build" version tag added in the EAS CLI release process. After https://github.com/expo/universe/pull/22530, this is the EAS CLI version that will be used by EAS workflows.
# Test Plan
Test with different version inputs, ensure failures are handled correctly.
# Why
Currently, the CLI is using an old version of `eas-cli-local-build-plugin` for builds with `eas build --local`. This is not ideal, as this means that local builds are not using the most recent `build-tools` and other packages.
# How
- Modify `local.ts` so that the version of the plugin matches the version of `@expo/eas-build-job` used by the CLI
- Add some missing environment variables that are required in the most recent releases of `@expo/build-tools`
# Test Plan
- Testing with local builds on my dev machine
- CI should pass
# Why
Customers would like to wait for a workflow run to complete, and get JSON output.
# How
Remove the restriction on --wait and --json flags together, and ensure that when --json is enabled, all messages other than the final JSON result will go to stderr.
# Test Plan
- Tested locally by running workflows
- CI should pass
# Why
If a user executes `eas workflow:run --wait`, it would be desirable to show status updates for the individual jobs and steps in the workflow while the workflow run is in progress.
# How
Added code that leverages some of the same utilities used by `workflow:logs`.
During the run, the logs for the various workflow jobs are retrieved and parsed, and the progress of each job is shown in the text of a spinner, showing the current step and the last few lines of the step's logs.
If the workflow run fails, the output will show jobs that failed, along with the failed step for each, and any logs for the failed steps.
Other changes:
- Bumped the "ora" package to the latest version, to pick up bug fixes
- Removed deprecated Node 18 from test runs
- Refactored the code in `workflow:run` that parses inputs, moving that code to a file in `commandUtils`
- Modified the Zod type for inputs to align with server side changes in https://github.com/expo/universe/pull/21950
# Test Plan
- Testing with different workflows
- CI should pass
# Why
Build and repack jobs do not have logs at the same URL as other workflow jobs, so no logs were showing for these job types.
# How
- Update BuildFragment to include the log file URL
- Check for build jobs, and add the correct queries and fetch calls for those
- Update and fix tests
- Bump `@expo/eas-build-job` to 1.0.239 to fix TS error in environment type
# Test Plan
- Tested with various workflow runs, including ones with custom, build, repack, and update jobs.
- CI should pass.
* incorporating feedback
* small cleanup
* moved some files around
* moved tests
* remove unused line
* tweak one line
* unit tests for all the helper functions
* more tests pass
* last batch of tests for now
* update changelog
* fix changelog
* move src/new to src/commandUtils/new
* pr feedback
* update changelog
* update path in copy-new-templates command
* fix test import
* Update packages/eas-cli/package.json
Co-authored-by: Douglas Lowder <[email protected]>
* feat: add --package-manager flag to project:new command
- Add --package-manager (-p) flag with options: npm, yarn, pnpm, bun
- Default to npm when flag not provided
- Remove promptForPackageManagerAsync call
- Add corresponding tests
* feat: add --no-install flag to skip dependency installation
- Add --no-install flag to skip installing dependencies
- Update README with installation instructions when --no-install is used
- Pass skipInstall flag through to updateReadmeAsync
- Add corresponding tests
* feat: add hideOutput option to suppress dependency installation logs
- Add hideOutput parameter to runCommandAsync to use stdio: 'ignore'
- Update installDependenciesAsync to hide npm/yarn/pnpm/bun output
- Show only spinner during installation instead of verbose logs
- Apply hideOutput to all dependency installation steps
- Update tests to reflect flag definition changes
* revert: remove --no-install flag
Remove the --no-install flag and related skipInstall functionality as requested
* feat: remove prompts and use smart defaults for project name and directory
- Remove project name prompt, use smart fallback logic:
- Default: new-expo-project
- If exists: new-expo-project-USERNAME-DATE
- If exists: new-expo-project-SHORTID (using nanoid)
- Remove target directory prompt, use cwd/projectName as default
- Refactor naming to reflect generation vs prompting:
- Rename prompts.ts → configs.ts
- Combine generateDefaultProjectNameAsync + promptForProjectNameAsync → generateProjectNameAsync
- Rename promptForTargetDirectoryAsync → generateDirectoryAsync
- Rename promptForConfigsAsync → generateConfigsAsync
- Rename promptedConfigs → initialConfigs
- Add nanoid and fs-extra dependencies for smart defaults
- Update all tests to reflect new behavior (11 tests in configs.test.ts passing)
- All existing tests continue to pass
* refactor: simplify CLI args for project:new command
- Remove --name flag, always use smart generation logic
- Change --directory flag to positional 'path' argument
- Defaults to current working directory
- If no slashes: treated as subdirectory of cwd
- If relative path with slashes: resolved from cwd
- If absolute path: used as-is
- Update generateProjectNameAsync to remove optional name parameter
- Update generateDirectoryAsync to handle path logic
- Add 4 new tests for path handling scenarios
- Remove 1 test for name arg (no longer supported)
- All 17 tests passing
* more feedback
* one more big refactor
* more cleanup
* one last round of cleanup
* one last round of cleanup
* fix changelog
* fix tests
---------
Co-authored-by: Douglas Lowder <[email protected]>
# Why
The existing `workflow:create` command simply creates a very bare-bones workflow, that is not very useful to developers who need to know how to fully use workflows for managing builds, updates, and other EAS operations.
# How
- Define four different workflow templates, initialized as JSON objects.
- After the user selects which type of workflow (build, update, deploy, custom), sanity checks are made, EAS build and EAS update are configured if needed, and any missing build profiles are created in `eas.json`.
- Once the user has made their selections, the final workflow YAML is dynamically generated and written to disk with an explanatory header.
- After writing the workflow, next steps are provided for any further configuration that may be needed, especially if build credentials or app store credentials are needed.
In future, we can easily add more templates that use other workflow job types (fingerprint, repack, etc.).
# Test Plan
- Tested against different projects
- CI should pass
# Why
Add a `--ref` flag so that `eas workflow:run` can initiate a workflow run from an existing ref in the project's GitHub repository.
- Avoids the need to upload the entire project from a local machine
- Ensures that the workflow starts from a known reference point in the project's source control, with no unexpected local changes
# How
- If the ref flag is set, the run command will ensure that the ref is valid, and that the workflow can be used for that ref (using the new mutation for this from https://github.com/expo/universe/pull/22132)
- If the ref flag is set, the run command starts the run from that ref (using https://github.com/expo/universe/pull/20161)
- If the user chooses ref = HEAD, `git rev-parse` is called to convert that to a commit
- The flow is designed to work the same for running from GitHub ref as running from local, so inputs and waiting for results are supported
# Test Plan
- Tested in an existing project with workflows with and without inputs
- CI should pass
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
In https://github.com/expo/eas-build/pull/604 I removed `fingerprintSource` from metadata passed to a build (1). It was previously used to inform the build process of, well, the fingerprint source so it can optionally diff current fingerprint and fingerprint calculated by the `eas build` command.
In `eas build`, the fingerprint would get calculated and uploaded. Then it was included in the build mutation as `{ type: GCS, bucketKey }` (2). Worker expected that somewhere in the process of starting a job, something (`www` or `turtle-v2`) would swap out the persisted `fingerprintSource` to `{ type: URL, url }` (because worker can't download arbitrary GCS objects).
In https://github.com/expo/eas-build/pull/587 I changed the flow so that now worker does not expect any changes to the job or metadata and instead fetches the fingerprint sources straight from `www`.
This made `fingerprintSource` in `metadata` obsolete (see (1)). However, we still need to be able to send fingerprint sources information to `www` (see (2)).
# How
This pull request:
- bumps `@expo/eas-build-job` (removing `FingerprintSource` type)
- `FingerprintSource` gets replaced with `FingerprintSourceInput` generated by GraphQL schema
- this lets us remove `transformFingerprintSource` (it's being passed around in its final form)
# Test Plan
Set up my staging test app to use runtime version policy = fingerprint, installed and configured `expo-updates`, [ran a build](https://staging.expo.dev/accounts/sjchmiela/projects/staging-app/builds/7a44f4c3-e448-4657-a8f3-71e24a2a29c8).
I had a few `console.log`s in place:
<img width="943" height="779" alt="Zrzut ekranu 2025-09-30 o 17 39 14" src="https://github.com/user-attachments/assets/2b117a17-8c0a-4445-bf56-27f93a590f87" />
and the build has fingerprint:
<img width="1256" height="161" alt="Zrzut ekranu 2025-09-30 o 17 39 33" src="https://github.com/user-attachments/assets/b6133402-9910-42d2-b351-836ae9c10c95" />
Before I installed node dependencies, fingerprint was being set to `file:fingerprint` (probably from https://github.com/expo/expo/pull/26901, see https://github.com/expo/eas-cli/blob/b447194c8521270ba8b551296c4329c3edb7aa1c/packages/eas-cli/src/project/resolveRuntimeVersionAsync.ts#L88).
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Replaces internal FingerprintSource with GraphQL FingerprintSourceInput across build/update flows, removes transformFingerprintSource, adjusts metadata wiring, and bumps related packages.
>
> - **Build & GraphQL**:
> - Replace `Metadata.fingerprintSource` usage with GraphQL `FingerprintSourceInput`; update builders to accept `BuildMetadataInput` and pass pre-transformed metadata.
> - Remove `transformFingerprintSource` and associated imports/usages; simplify `transformMetadata` to accept `{ metadata, fingerprintSource }`.
> - Update types for fingerprint source across build paths (`computeAndMaybeUpload*`, `sendBuildRequestAsync`, Android/iOS build senders).
> - **Update/Publish**:
> - Stop transforming fingerprint source in `update publish`; pass through GraphQL `FingerprintSourceInput`.
> - Adjust runtime fingerprint computation/assembly to use `FingerprintSourceInput`.
> - **Fingerprint upload**:
> - `maybeUploadFingerprintAsync` now returns `FingerprintSourceInput`; use GraphQL enum casing (`Gcs`).
> - Mutation `createFingerprintAsync` accepts `FingerprintSourceInput`.
> - **Dependencies**:
> - Bump `@expo/eas-build-job` and `@expo/steps`; update yarn.lock accordingly.
>
> <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5a61fdee68f3b0bbda043b8f3160c4c2f1ea3a71. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
* incorporate pr feedback
* playing around with adding build
* create expo project
* clean up getAccountChoices
* update unit test
* removed some unused code
* wip
* working on test files
* fix previews, add more end comments
* small tweaks to tests
* update changelog
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
See https://github.com/expo/universe/pull/22108.
# How
- Updated GraphQL code.
- Adjusted code to the updated GraphQL code (no `isGlobal`).
- Updated types in `EnvironmentVariableMutation` so they don't re-implement what GraphQL is generating for us.
- Updated types in `env:push`.
# Test Plan
Adjusted tests.
* scaffolding out new command
* remove a newline
* incorporate pr feedback
* add unit test for package manager functions
* get rid of unnecessary lockfile git add
* remove unused test
# Why
Improve the validation of workflow files:
- Add client-side checks for valid syntax, and compatibility with the user's EAS build profiles
- Make validation usable with future improvements to `workflow:create`
# How
- New `validation.ts` in `commandUtils` with the various validation checks separated cleanly into different functions
- `workflow:validate` command refactored to use the new utility and wrap errors
- The new code reads the workflow schema from `<ExpoAPIBaseURL>/v2/workflows/schema`
- For testing purposes only, a local copy of the schema can be used by setting EXPO_TESTING_WORKFLOW_SCHEMA_PATH
- An existing check in `workflowFile.ts` has been modified to remove the requirement for a Github repository, as that is no longer required to run workflows
# Test Plan
- Tested against different workflow templates, and against workflows in a real project.
- Tested against the www server from the main branch running locally, to verify recent server side changes (e.g. https://github.com/expo/universe/pull/21950)
# Why
To allow CLI users to get artifacts of builds or workflow jobs directly using the CLI, and make the URLs available in JSON output also (for easier use by automation scripts).
# How
- Add artifact info to WorkflowJobFragment
- Add this info to the results of `workflow:view`
- For workflow jobs that are of type=BUILD, use the existing build query to get the build artifact URLs for the build and show those as well
- Make some improvements to the formatting of workflow job outputs
# Test Plan
- Tested against different EAS projects
- CI should pass
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Unify packages versions across the Expo package ecosystem (Zod, eas-build-job)
# How
Copied Zod definitions from `www` to `run.ts` where we are parsing workflow to get inputs definitions.
# Test Plan
There are, fortunately, tests for this part of the code.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[exponent-internal.slack.com/archives/C011ZMXQ6SZ/p1755530483378679](https://exponent-internal.slack.com/archives/C011ZMXQ6SZ/p1755530483378679)
# How
Updated GraphQL code which removed `SubmissionAndroidTrack` enum (it's a scalar now). Adjusted code to pass track around as string.
Removed `AndroidReleaseTrack` from `eas-json`. Updated `eas.schema.json` to allow any string as `track`.
Technically, to support `track: string` we'll need to update `eas-json` in `www`. I think it's ok to merge this, publish releases and then update `eas-json` in `www`. Alternatively we could publish `eas-json` from this branch as prerelease, bump in `www` and then merge this. This would be more _correct_, but I think it's ok to have this 1 hour of unannounced discrepancy between `www` and `eas-cli` (users not being able to use custom tracks _yet_).
# Test Plan
Tested along with all the pull requests in the mix.
<img width="372" height="90" alt="Zrzut ekranu 2025-09-9 o 17 03 38" src="https://github.com/user-attachments/assets/0b260ad2-2379-4597-aa1c-dae8bf86446d" />
<img width="243" height="72" alt="Zrzut ekranu 2025-09-9 o 16 59 37" src="https://github.com/user-attachments/assets/4eef353d-ac7e-4b16-9413-a304a574b685" />
<img width="449" height="110" alt="Zrzut ekranu 2025-09-9 o 17 00 40" src="https://github.com/user-attachments/assets/58a44b7a-16bb-46b4-8d98-f233c196406a" />
<img width="366" height="85" alt="Zrzut ekranu 2025-09-9 o 17 00 35" src="https://github.com/user-attachments/assets/71013cd6-5f5e-4e38-951c-008642fbee8c" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Preparation for merging the rest of `track`-related pull requests.
Currently, the only place fetching `track` from `www` for display is `submit:internal` command. There, we fetch the submission config to know what parameters to supply to `fastlane supply` in the Submit workflow job.
Currently, we're using a mapping of `{ PRODUCTION: production, INTERNAL: internal, ... }` to transform the GraphQL value (enum key) to config value ("enum value").
# How
Since we're planning to make `androidConfig.track` be a plain string (e.g. `internal`), we should fall back to the actual value if the mapping does not produce a match.
This currently should not change anything (`track` is guaranteed to be a GraphQL enum value). This is a preparation for landing of https://github.com/expo/universe/pull/21827 which (somewhat breakily, but we expect to be the only consumers of our GraphQL API) changes `track` to be any string.
This `track` value is being used [here](https://github.com/expo/universe/blob/2f143aa8d51821c7e1c306768787c46b18bdd544/server/www/src/data/entities/workflow/job/WorkflowSubmitJob.ts#L399-L403).
# Test Plan
This is currently a no-op. Tested along with all the pull requests in the mix.
<img width="372" height="90" alt="Zrzut ekranu 2025-09-9 o 17 03 38" src="https://github.com/user-attachments/assets/0b260ad2-2379-4597-aa1c-dae8bf86446d" />
<img width="243" height="72" alt="Zrzut ekranu 2025-09-9 o 16 59 37" src="https://github.com/user-attachments/assets/4eef353d-ac7e-4b16-9413-a304a574b685" />
<img width="449" height="110" alt="Zrzut ekranu 2025-09-9 o 17 00 40" src="https://github.com/user-attachments/assets/58a44b7a-16bb-46b4-8d98-f233c196406a" />
<img width="366" height="85" alt="Zrzut ekranu 2025-09-9 o 17 00 35" src="https://github.com/user-attachments/assets/71013cd6-5f5e-4e38-951c-008642fbee8c" />
# Why
It would be great if we could use the environment setting `DEBUG=eas:*` to enable debug logs when running the EAS CLI, similarly to the way `DEBUG=expo:*` is used in the Expo CLI.
This is a first step towards implementing that. Ideally, different commands and utility modules would set different tags for the debug log messages, but this will at least allow the debug logs to appear for existing `Log.debug()` calls.
# How
Modify `src/log.ts` to write debug logs if DEBUG is set to a regex that matches `eas:log:debug`.
# Test Plan
CI should pass.
# Why
Sync up the schema to reflect recent additions to the server GraphQL schema
# How
`yarn --cwd packages/eas-cli verify-graphql-code`, then inspect changes in schema and generated code.
# Test Plan
CI should pass
# Why
Make it easier for customers to use `eas update:rollback` in CI.
# How
Add description text on the underlying commands that do support the non-interactive flag.
# Why
The existing release trigger workflow does not obtain the GItHub history and tags, so that Lerna cannot correctly determine which package versions to bump.
# How
Set `fetch-depth: 0` in the checkout action, and do an explicit fetch of all tags.
# Test Plan
- After merge, a dry run of the release trigger should correctly bump only changed packages.
# Why
The new release GitHub workflow has an error because the release script needs to be run without prompts:
```
Checking if eas-cli-local-build-plugin upgrade is available
eas-cli-local-build-plugin is already on the latest version - 1.0.171
lerna notice cli v8.2.3
lerna info ci enabled
lerna info current version 16.17.3
lerna info Assuming all packages changed
Changes:
- eas-build-cache-provider: 16.4.2 => 16.17.4
- eas-cli: 16.17.3 => 16.17.4
- @expo/eas-json: 16.13.2 => 16.17.4
error Command failed with exit code 130.
? Are you sure you want to create these versions? (ynH) info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Error: Process completed with exit code 130.
```
# How
- Added the `--yes` flag to the script commands
- Instead of failing when run locally, the script now executes the release flow in "dry run" mode, without committing, tagging, or pushing changes.
- Add workflow input for dry run mode (true by default, must be manually set to false to actually release)
- Get full Git history before running release script, as required for correct Lerna version check
# Test Plan
- Test locally
- Run the workflow in dry run mode after merging
- Attempt a release after this PR is merged
# Why
The current release script requires that the user executing the script have permission to push changes to main without any PR requirement or checks.
# How
To allow us to add PR requirements and checks, I have added a manual GitHub workflow so that the existing script is executed by the expo-bot user, which is exempted from PR requirements.
I have also made a few adjustments to the `release.yml` workflow (remove incorrect release name, update Node version to 22).
# Test Plan
- CI should pass
- Try a release after this PR is merged
Summary:
I'm working in a weird setup where the browser won't launch from cli.
This required me to visit the url manually from my browser.
To get the url, I had to add a `console.log` to the cli's code directly.
Figured this change will make it easier for similar users to login, without exposing sensitive data
Test Plan:
Tested manually on the compiled code, not the best
* Workaround early stream termination using filehandle.read
* Add length check to createReadStreamAsync
* Align asset and multipart entry file types
* Recalculate and check hash during upload
* Update error messages and add comment
* Emit errors earlier and refactor loop
* Use same reader function and disable objectMode
* Add CHANGELOG entry
* Apply lints
# Why
Adding the new `workflow:logs` command (see the [workflow CLI design document](https://www.notion.so/expo/EAS-CLI-workflow-commands-8bc5ccc4f9f949c8adfec1347817113c)) and the related command `workflow:view`, to provide more details on workflow runs, jobs, and their associated logs.
```bash
$ eas workflow:view --help
view details for a workflow run, including jobs. If no run ID is provided, you will be prompted to select
from recent workflow runs for the current project.
USAGE
$ eas workflow:view [ID] [--json] [--non-interactive]
ARGUMENTS
ID ID of the workflow run to view
FLAGS
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
view details for a workflow run, including jobs. If no run ID is provided, you will be prompted to select
from recent
workflow runs for the current project.
```
```bash
$ eas workflow:logs --help
view logs for a workflow run, selecting a job and step to view. You can pass in either a workflow run ID or a job ID.
If no ID is passed in, you will be prompted to select from recent workflow runs for the current project.
USAGE
$ eas workflow:logs [ID] [--json] [--non-interactive] [--allSteps]
ARGUMENTS
ID ID of the workflow run or workflow job to view logs for
FLAGS
--allSteps Print all logs, rather than prompting for a specific step. This will be automatically set when in
non-interactive mode.
--json Enable JSON output, non-JSON messages will be printed to stderr.
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
view logs for a workflow run, selecting a job and step to view. You can pass in either a workflow run ID or a job ID.
If no ID is passed in, you will be prompted to select from recent workflow runs for the current project.
```
# How
Implemented the new commands. New queries and and a new fragment for workflow jobs have been added.
A state machine has been implemented to ensure correct flow for the `workflow:logs` command, allowing the user to drill down from workflow runs, to jobs, to viewing logs for an individual step. Where it makes sense, the selection prompts allow backtracking to search for a different run, job, etc.
# Test Plan
- CI should pass
- Tested locally with different inputs, and with different flag values
- New unit tests added for `workflow:logs`
# Why
The current implementation of capabilities syncing can lead to provisioning profiles becoming invalid. This PR refactors the syncing process to avoid this issue by making the following improvements:
1. Preventing unnecessary creation of capability identifiers that already exist
2. Only updating bundle capabilities when necessary
closes https://github.com/expo/eas-cli/issues/1069
closes https://github.com/expo/eas-cli/issues/1445
# How
I refactored the capability syncing logic to:
- Add test coverage for faulty behaviors. More tests are [up the stack](https://github.com/expo/eas-cli/pull/3086/files#diff-09c5aad6e72a7a336e9783710d3899ff2ea432146929bc07ba8bfec7c7bbd2a8).
- Only create capability identifiers that don't already exist on the server
- Skip updating bundle capabilities when no changes are needed
# Test Plan
`easd` command below is from https://github.com/expo/eas-cli/blob/main/CONTRIBUTING.md#development.
To best test this locally, have an iOS app with
(1) no capabilities enabled. Enable some capabilities in `app.json` and run prebuild. [iCloud](https://docs.expo.dev/versions/latest/sdk/document-picker/#example-appjson-with-config-plugin), Apple Sign In, app groups, or `"com.apple.developer.default-data-protection": "NSFileProtectionComplete / ..."` are of special interest, but any will do.
OR
(2) a buch of capabilities already enabled
using this app, run `easd build -p ios` TWO times. Confirm that the first build creates new capabilities on your app bundle (https://developer.apple.com/account/resources/identifiers/list) and provisioning profiles (if any). Confirm the second build passes and doesn't require any provisioning profile changes.
Finally, change the capabilities, and again run `easd build -p ios` twice to confirm no capabilities / provisioning profiles are changed on the second run (that's what should happen on the first run).
- green CI
- local tests
# Why
This PR refactors the iOS capability synchronization logic to make it more "linear" and easier to maintain
# How
- Encapsulating capability-specific logic with the capability definition
- Making the operation decision process more explicit and easier to follow
# Test Plan
- green CI
- local tests
# Why
This PR refactors the iOS bundle ID capabilities management to improve handling of capabilities with complex settings. The current implementation doesn't properly handle capabilities that have settings - Sign In with Apple, iCloud, and Data Protection.
# How
- Added test cases that would previously fail
- Extracted capability list to a separate file (`capabilityList.ts`) to improve code organization
- Fixed synchronization logic to make tests pass (in a dirty way, refactored later)
- Fixed handling of MDM Managed Associated Domains to prevent disabling when Associated Domains is enabled
- Improved test assertions to use non-deprecated matchers (`toHaveBeenCalledWith` instead of `toBeCalled`)
# Test Plan
- green CI
- local testing
* Add custom multipart format
* Reuse list of files for upload params
* Remove unused gzip compression
* Clean up UploadParams
* Update file crawling to include size and mime type
* Move file-size check to assets.ts
* Refactor upload functions
* Update upload API function to support multipart uploads
* Update uploadAsync params usage in deploy command
* Upload as multipart batches, if instructed
* Count batch length against total
* Add CHANGELOG
* Fix signal not being used
* Add new assets.json format
* Skip empty assets
* Fix lint error
* Adjust concurrency
Beyond 10 we do risk some CPU contention in rare cases for small files
(especially on Windows)
However, we can now run more requests concurrently, since they're slower
each and hence are less likely to run into network issues due to lower
rate.
* Revert "Skip empty assets"
This reverts commit 18434cdb48.
* feat(eas-cli): Implement new asset upload progress bar for `deploy` command (#3099)
* Update comment
* Add CHANGELOG entry for progress bar change
* [eas-cli] update apple team info as needed
* Temporary Commit at 7/7/2025, 2:01:08 PM
* Temporary Commit at 7/7/2025, 2:12:28 PM
* Temporary Commit at 7/8/2025, 11:28:08 AM
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
While creating a previous PR, I moved a graphql query into a directory not explicitly specified in `graphql-codegen.yml`. It took me a while to figure out what was going on (only error was `tsc`).
To avoid other devs running into this, just generate it for all files in src.
# How
1. Update paths
2. Fix `fetchUserAsync` to be typed and have a unique query name.
# Test Plan
```
neas logout
neas login
neas whoami
```
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
The docs for ending an update-based rollout are incorrect: https://docs.expo.dev/eas-update/rollouts/#ending-a-rollout
In order to revert a update-based rollout, it currently says:
> To accomplish this end state, republish the previous update by using the `eas update:republish` command.
But this is incorrect since one is not allowed to publish a new update until the control update is finished (can't have multiple roll-outs).
What actually needs to happen under the hood is one of two options:
- When on a branch with a rollout with a control update
1. Delete the rollout update
2. Republish the control update
- When on a branch with a rollout with only a rollout update
1. Delete the rollout update
2. Publish a roll-back-to-embedded (after warning since this may not be intended behavior).
This PR adds a new command, `eas update:revert-update-rollout` that does this.
# How
Add command, refactoring shared code where necessary.
This handles a ton of cases. Essentially the cross product of:
- Rollout published on empty branch or branch with existing updates. (rollout has control)
- Rollout published per-platform or single group with both platforms,
- Control published per-platform or single group with both platforms.
So, 8 total cases.
# Test Plan
Tested most of the 8 cases.
Normal update group rollout (both platforms), normal control on same update group:
```
(branch with an existing notmal update group)
$ neas update --rollout-percentage=50
$ neas update:revert-update-rollout
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Select a target runtime › 1.0.0
✔ Are you sure you want to revert the rollout update group with ID "b0db8e15-d3d0-41db-985a-d74f0bd8fb00"? This will delete the rollout update group and republish the control update group (ID: "7df732c7-ccad-4755-8b80-acd1c03c5a81"). … yes
✔ Provide an update message. … watwatrep
✔ Republished update group
```
Normal update group rollout (both platforms), controls in different update groups (latest updates for each platform at time of rollout publish were in different groups):
```
$ neas update --platform android
$ neas update --platform ios
$ neas update --rollout-percentage=50
$ neas update:revert-update-rollout
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Select a target runtime › 1.0.0
✔ Are you sure you want to revert the rollout update group with ID "47ef8fe7-6f9b-4c59-bdd5-cdcc12eef0f2"? This will delete the rollout update group and republish the control update groups (IDs: "a821e0be-04af-455b-8b75-ceabea3afc09", "5a07a994-7a71-4d4e-a188-83df9e456e2c"). … yes
✔ Provide an update message. … Republish "ioswat" - group: a821e0be-04af-455b-8b75-ceabea3afc09
✔ Provide an update message. … Republish "watandroid" - group: 5a07a994-7a71-4d4e-a188-83df9e456e2c
✔ Republished update group
Branch main
Runtime version 1.0.0
Platform ios
Update group ID c1d05402-4391-4cd8-9eb0-ab0c7958bce5
iOS update ID 06b57ea9-4016-40b7-962b-756d463f2ba9
Message Republish "ioswat" - group: a821e0be-04af-455b-8b75-ceabea3afc09
EAS Dashboard https://staging.expo.dev/accounts/wschurman/projects/test-ojdasksajajaja/updates/c1d05402-4391-4cd8-9eb0-ab0c7958bce5
✔ Republished update group
Branch main
Runtime version 1.0.0
Platform android
Update group ID 56d10192-9bbd-4557-ab25-44250b3ccf6b
Android update ID eb5b1a25-cbba-4f2a-afe9-d698068369ed
Message Republish "watandroid" - group: 5a07a994-7a71-4d4e-a188-83df9e456e2c
EAS Dashboard https://staging.expo.dev/accounts/wschurman/projects/test-ojdasksajajaja/updates/56d10192-9bbd-4557-ab25-44250b3ccf6b
```
Two single platform rollouts:
```
$ neas update --platform android
$ neas update --platform ios
$ neas update --rollout-percentage=50 --platform android
$ neas update --rollout-percentage=50 --platform ios
$ neas update:revert-update-rollout
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Select a target runtime › 1.0.0
✔ Which rollout update group would you like to revert? › Rollout update group ID: 38369dcd-fe24-40c5-a85d-c7d4c03c9230, Platform: android, Rollout Percentage: 50
✔ Are you sure you want to revert the rollout update group with ID "38369dcd-fe24-40c5-a85d-c7d4c03c9230"? This will delete the rollout update group and republish the control update group (ID: "5a07a994-7a71-4d4e-a188-83df9e456e2c"). … yes
✔ Provide an update message. … Republish "watandroid" - group: 5a07a994-7a71-4d4e-a188-83df9e456e2c
✔ Republished update group
$ neas update:revert-update-rollout
(node:96817) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Select a target runtime › 1.0.0
✔ Are you sure you want to revert the rollout update group with ID "ae7aaa74-06cc-43b1-98dd-63e019cb4a64"? This will delete the rollout update group and republish the control update group (ID: "a821e0be-04af-455b-8b75-ceabea3afc09"). … yes
✔ Provide an update message. … Republish "ioswat" - group: a821e0be-04af-455b-8b75-ceabea3afc09
✔ Republished update group
```
Empty branch rollout (both platforms), no control:
```
(empty branch)
$ neas update --rollout-percentage=50
$ neas update:revert-update-rollout
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Select a target runtime › 1.0.0
✔ Are you sure you want to revert the rollout update group with ID "1797d1fe-cf58-4134-abe1-b0333250da55"? This will delete the rollout update group and publish a new roll-back-to-embedded update (no control update to roll back to), whose behavior may not be a true revert depending on the previous state of the branch. … yes
✔ Provide an update message: … geageawga
✔ Published!
```
Empty branch rollout (just one platform), no control:
```
(empty branch)
$ neas update --rollout-percentage=50 --platform android
$ neas update:revert-update-rollout
(node:87664) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Select a target runtime › 1.0.0
✔ Are you sure you want to revert the rollout update group with ID "b2115695-ba9f-4f2d-a901-9f147d09e113"? This will delete the rollout update group and publish a new roll-back-to-embedded update (no control update to roll back to), whose behavior may not be a true revert depending on the previous state of the branch. … yes
✔ Provide an update message: … dwada
✔ Published!
Branch main
Runtime version 1.0.0
Platform android
```
# Why
Now that #3091 is resolved, we need to add some CI to guard against similar future issues with GraphQL breakage.
# How
Add a new workflow that
- Executes GraphQL generation, and fails if there is an error.
- Verifies that for a given PR, any changes in GraphQL generated code or schema files have been checked in as part of the PR. If not, the workflow fails.
The new workflow will execute on pushes, and on a daily schedule to guard against breakage due to changes on the server side.
# Test Plan
- CI should pass
- Push a source change in the GraphQL code, but do not regenerate GraphQL, and verify that the new workflow fails
Why
===
The message about queuing builds faster mentions the Production and Enterprise plans. The Starter plan is also a good choice.
How
===
This PR changes the message just to say "paid plan" which is simple and understandable.
Test Plan
===
Just automated tests since this is a copy change.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
The previously recommended xcode-select command which was `sudo xcode-select -s /Applications/Xcode.app` did not work. Updated to suggest the correct fix which is running `sudo xcode-select -s /Applications/Xcode.app/Contents/Developer`
# How
Attempted to use `eas build:dev` after installing Xcode beta to use iOS 26, got error message which suggested the `sudo xcode-select -s /Applications/Xcode.app` command. It didn't work, but `sudo xcode-select -s /Applications/Xcode.app/Contents/Developer` did.
# Test Plan
Not quite sure how to reproduce the scenario in order to test this, but I can verify that this is what the correct suggestion should be as it fixed the problem which triggered the error message, and that's the location where it should look for the Simulator.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Since https://linear.app/expo/issue/ENG-14634/add-support-for-groups-option-in-fastlane-pilot-call we support passing `--groups` parameter to `eas submit` and configuring submission profile with `groups` parameter ("undocumentedly").
I need to add support for this property to `submit:internal`. We're going to source the `groups` to pass to `fastlane pilot` from either:
- submit profile (this pull request adds this)
- or workflow config (in which case we'll don't use this output).
# How
Added `groups` output to the `submit:internal` JSON object. We're going to parse it in https://github.com/expo/universe/blob/5dcea35fb50bf9fc8e3ae4ffe445f958bb5789e6/server/www/src/data/entities/workflow/job/WorkflowSubmitJob.ts#L192-L200.
# Test Plan
Ran `easd submit:internal --id 60a2d86a-b6d8-4ba2-b7dd-bf05bdd78791 --platform ios` in a test project of mine after adding submit profile like
```
"submit": {
"production": {
"ios": {
"ascAppId": "6769090000",
"groups": ["family", "friends"]
}
}
}
```
<img width="253" alt="Zrzut ekranu 2025-06-25 o 17 39 22" src="https://github.com/user-attachments/assets/584e1bea-a905-4ba3-a68e-5df4a4d3477e" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Update group background job polling (and all background job polling in the CLI) is broken due to query caching in the client. Not sure why this worked when I added it as the caching has been present for a while.
# How
Disable cache for the poll request.
This also inverts the confirmation on `update:delete` to be affirmative as most of our other confirm questions are (default to yes). The reason for this change is that I found it non-intuitive while testing this to have "yes" cancel the command. I think the reason we use to have this inverted is it was dangerous, but IMO it's already enough intent by running the command to just have the default be yes. Happy to revert this back if reviewers disagree.
# Test Plan
```
eas update
neas update:delete <update_group>
```
See it now works.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Noticed this condition was inverted during creation of a new related command.
# How
Correct the if statement. It should warn when platform is not `all`.
# Test Plan
Run `neas update:republish --platform ios`, see logged message:
```
$ eas update:republish --platform ios
✔ Find update by branch or channel? › Branch
✔ Select branch from which to choose update › main
✔ Load more update groups? › [Jun 23 11:14 by wschurman, runtimeVersion: 1.0.0] Initial commit
Generated by create-expo-app 3.4.2.
You are republishing an update group that wasn't published for all platforms.
✔ The republished update group will appear on the same platforms it was originally published on: ios
✔ Provide an update message. … Republish "Initial commit
Generated by create-expo-app 3.4.2." - group: 8e1b11be-ef82-4ccd-8294-a4e7075849d1
✔ Republished update group
```
* [eas-cli] align text of messages from build and workflow:run
* Apply suggestions from code review
Co-authored-by: Stanisław Chmiela <[email protected]>
---------
Co-authored-by: Stanisław Chmiela <[email protected]>
# Why
I tried to use eas dev:build with --build-profile parameter, but I got eas build with different profile
# How
I tested locally that changes in this branch fixes the problem for my case
# Test Plan
I have run following command (easd linked to locally build eas-cli, as described in CONTRIBUTING.md)
```
EXPO_DEBUG=1 easd build:dev -e preview -p android
```
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
6636f76cff had a logical merge conflict in the changelog since a new version was released.
# How
Move the entry to the correct release.
# Test Plan
Inspect.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
This is the eas-cli component of https://github.com/expo/universe/pull/20493, which allows creating a rollout update on a branch with no existing updates.
# How
Remove error when no existing update exists.
# Test Plan
```
yarn create expo-app test-kjhsadjhkkjhafskjhjkhhhh
cd test-kjhsadjhkkjhafskjhjkhhhh
neas init
neas update:configure
neas update --rollout-percentage=60
```
View published update in db, see it has 60% rollout percentage but no control
# Why
since the onboarding repack is not available now, let's remove the code for onboarding repack. we can later use `BuildMode.Repack` for workflow repack job.
# How
remove repack relevant code
# Test Plan
ci passed
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C089ED313PV/p1748545207578949?thread_ts=1748543276.564549&cid=C089ED313PV
# How
Added support for `EAS_SKIP_CLI_VERSION_CHECK` environment variable.
# Test Plan
Added tests.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
As requested during feature review, these should live in the top-level "cli" key of eas.json.
Closes ENG-15925.
# How
Change location.
# Test Plan
`yarn tsc`
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
`eas.json` is not _required_ to run workflows. Builds will fail, but we can warn about it and also the workflow error makes sense.
# How
Check before uploading the non-required files.
# Test Plan
<img width="946" alt="Zrzut ekranu 2025-06-2 o 21 45 31" src="https://github.com/user-attachments/assets/b6b4aad1-608f-471c-b541-302850744062" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
These fields were missing in republished updates.
Closes ENG-15846.
# How
Copy these fields over as well when republishing.
# Test Plan
`neas update` with dirty working tree.
`neas update:republish`
Verify republished update has same dirty working tree status.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
CLI change corresponding to https://github.com/expo/universe/pull/20131.
This adds the ability to override the manifest and asset hosts for EAS Update such that a set of proxy hosts can be used.
Closes ENG-15804.
# How
Considered putting these in flags, but it turned out that many many commands need to detect EAS Update configuration so they need access to these as well. Therefore, I added the new fields to `eas-json`.
The fields are:
- `manifestHostOverride` - a host to replace `u.expo.dev` in the URL.
- `assetHostOverride` - a host to replace `assets.eascdn.net` in asset URLs in the generated update manifests.
Then, in every place in EAS CLI when we generate a manifest URL, instead use the overridden URL.
Then, supply the manifest URL and asset URL overrides when creating updates (or republishes).
# Test Plan
Lengthy, but here it goes:
1. Create two proxies, one for assets and one for manifests. All these proxies do is proxy the requests.
- https://github.com/wschurman/updates-test-proxy is a proxy for the manifest request built using expo router API routes and EAS Hosting. It is hosted at https://updates-test-proxy.expo.app and just fetches the URL input but at `u.expo.dev` and returns the response.
- https://github.com/wschurman/updates-test-asset-proxy is the same but for assets. https://updates-test-asset-proxy.expo.app
2. Create an app on staging
3. Add the following to eas.json:
```
"update": {
"assetHostOverride": "updates-test-asset-proxy.expo.app",
"manifestHostOverride": "updates-test-proxy.expo.app"
}
```
4. run `neas update:configure`, see overridden URL in app.json
5. run `neas update`, see update is published, visit overridden manifest URL, see an update!
6. Visit one of the asset URLs (supplying authorization header) and see it correctly proxies.
7. configure code signing
8. publish again, see code signing works (downloads from `manifestPermalink`)
9. republish the last update, see it works and sets the overrides correctly.
# Why
[ENG-15618: Support different suffixes of custom gradle commands](https://linear.app/expo/issue/ENG-15618/support-different-suffixes-of-custom-gradle-commands)
Currently when user specifies a custom gradle command that does not end with `*Release` or `*Debug` the command is not parsed correctly. Build type and flavour are not parsed, which causes problems with setting code version and app version down the line.
# How
- Changed the regexp that parses gradle command to be more flexible, allowing any suffix that starts with a capital letter.
# Test Plan
- add a custom gradle command to `eas.json`, for example
```
"development": {
"android": {
"gradleCommand": ":app:assembleAbcStaging"
}
},
```
- add a `buildType` and packageFlavor to `build.gradle` file:
```
productFlavors {
abc { // New flavor
versionCode 3
versionName "abc"
}
}
buildTypes {
staging {}
debug {... }
release {...}
}
```
- start an android build from cli.
- started build should not warn about invalid configuration
- on website, build version should be set to the value assigned in flavour.
# Why
When publishing updates, users need to know if there are compatible builds for their fingerprints. This PR prints this information at the end of `eas update` to warn users, if they have updates being published that don't have corresponding builds, causing potential compatibility issues.
<img width="1536" alt="Screenshot 2025-04-01 at 5 09 12 PM" src="https://github.com/user-attachments/assets/400ac0d9-c39e-4aee-9793-465c6acb634e" />
# How
Added functionality to check for compatible builds when publishing updates:
1. Enhanced `fetchBuildsAsync` to support filtering by `fingerprintHash`
2. Implemented `findCompatibleBuildsAsync` to find builds matching fingerprints
3. Added warnings in the update publish command when no compatible builds are found for fingerprints
4. Included links to the fingerprint details on the Expo website for easier debugging
# Test Plan
Run `eas update` with a fingerprint that doesn't have a compatible build
# Why
This PR refactors the `UpdatePublish` command to improve code readability and flow by removing a nested `else` block and using an early return pattern.
before
```
if (jsonFlag) {
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
} else {
// all the logic
}
```
after
```
if (jsonFlag) {
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
return;
}
// all the logic
```
# How
- Removed the large `else` block that contained most of the code in the `UpdatePublish` command
- Added an early return after handling the JSON flag case
- Kept all the existing functionality intact while making the code more maintainable
- Improved the logical flow by flattening the code structure
# Test Plan
Manually tested the `eas update` command to ensure the code path works correctly
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I'm going to move Workflow and GitHub builds to scoped token soon. If users depend on the automatically provided `EXPO_TOKEN` _and_ the action they're going to try to do has not been whitelisted with scoped rules yet, they're going to get an `UnauthorizedError` mentioning `ScopedAccountActorViewerContext`.
On top of logs annotations (working on them [here](https://github.com/expo/universe/pull/19494)) I think we can make the error message a bit better.
# How
Special-case `ScopedAccountActorViewerContext` error in `process.env.EAS_BUILD` and print message asking the user to contact us.
Alongside this, I think https://github.com/expo/universe/pull/19500 may be a good idea.
# Test Plan
With `readRules` in `UserPrivacyPolicy` cleared out:
<img width="1440" alt="Zrzut ekranu 2025-03-31 o 23 43 00" src="https://github.com/user-attachments/assets/89245ccc-21e7-4041-98ce-21a517f932d4" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
When we move Workflows to scoped token which has at most DEVELOPER permission, `type: deploy, prod: true` jobs will fail with an ominous
```
You don't have the required permissions to perform this operation.
This can sometimes happen if you are logged in as incorrect user.
Run eas whoami to check the username you are logged in as.
Run eas login to change the account.
Original error message: Entity not authorized: AppDevDomainNameEntity[00000000-0000-0000-0000-000000000000] (viewer = ScopedAccountActorViewerContext[16d62ef3-a219-47ca-936b-89958f6cb1f8], action = CREATE, ruleIndex = -1)
Request ID: 863a1317-882b-4cab-b8f2-c5f5d63b6f29
```
# How
Special-cased the `--prod` && `AppDevDomainEntity` && `CREATE` && `UNAUTHORIZED_ERROR` error.
Not sure if we should call out "as an app admin" in the error message. Open to suggestions.
# Test Plan
Ran `eas deploy --prod` as a developer-permission-only user. I've updated message in code since taking the screenshot.
<img width="836" alt="Zrzut ekranu 2025-03-28 o 21 21 02" src="https://github.com/user-attachments/assets/fc3a8b08-ae2f-4630-9e88-ccb48151d3e2" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Closes https://github.com/expo/eas-cli/issues/2401
# How
Add `corepack` field to `eas.json`
# Test Plan
Tests, tested manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I was thinking we can offer `EAS_NO_VCS=1` as a simple escape hatch for people that are getting weird Git-related issues. One of them may be an old version of Git that does not support our `git clone` properly.
# How
In `getRootPath` of no-VCS mode, return first of those values (in order):
- `EAS_PROJECT_ROOT`
- Git root path
- `process.cwd()`
# Test Plan
Added a basic test.
Co-authored-by: Szymon Dziedzic <[email protected]>
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Thanks to [a conversation on Bluesky](https://bsky.app/profile/sjchmiela.bsky.social/post/3lj6k2xo7rk2g) it turned out [this check](https://github.com/expo/eas-cli/blob/3a434940eb44dfa8dddc42af055793134ca9016f/packages/eas-cli/src/vcs/clients/git.ts#L255-L257) is invalid (always true), because `Ignore` has `DEFAULT_IGNORE`, so even if a user had no `.git` in `.easignore`, especially if they had `requireCommit: true`, `.git` would be removed.
# How
- Added a check to disallow `.easignore` if one has `requireCommit: true`.
- Changed logic around `Ignore` so we have separate `createForCopying` (ignores `.git` and `node_modules` always) and `createForChecking` (does not ignore anything by default). I don't like it, but it should work and is the best of what I could come up with without further refactoring.
# Test Plan
Added more tests.
* [eas-cli] skip creation of testflight group when there are already exisitng testflight groups + allow to opt out of the behavior by setting env var
* rename env var
* add changelog
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I struggled with adding a new workflow within `.eas/build` since I had `build/` in my `.gitignore`. I removed the line but it was still an issue. Turns out I had the same thing in `.easignore`. I think adding this to the error message could be helpful for others
# How
Not tested
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
When we `git clone` the source repository and then copy worktree changes over, we add and modify files. However, we do not _delete_ files that have been deleted in worktree.
# How
When we operate in `requireCommit: false` mode, we add `--no-checkout` to the `git clone` command. This way the destination directory only has `.git` directory when we start copying files over. Thus, files deleted from worktree will not suddenly appear in tarball.
In `requireCommit: true` mode we don't add `--no-checkout`, because we don't copy files.
# Test Plan
Added test. Tested manually.
Side effect of this is that `git status` reports that all files have been deleted and there's a bunch of untracked files (which, `git add`-ed, make the repository appear as the source repo). I don't know how to copy the Git index 1-1…
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
With `toNamespacedPath` I was finally able to make ignoring files work properly.
# How
Removed `if (__NORMALIZE)` checks.
# Test Plan
Ran `eas build:inspect` on Windows, confirmed no `node_modules` was copied. Also ran `eas build:inspect` on macOS, worked too.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
`fs` adds a [Win32 File Namespace](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-file-namespaces) to the beginning of the path which breaks `path.relative` if `src` does not have the namespace.
<img width="899" alt="Zrzut ekranu 2025-02-9 o 12 15 45" src="https://github.com/user-attachments/assets/942b28d1-881f-4e5d-861e-297bb5eddbf2" />
# How
Ensured that running `toNamespacedPath` on an already namespaced path does not add a _second_ namespace:
```
> path.win32.toNamespacedPath("D:\\abc")
'\\\\?\\D:\\abc'
> path.win32.toNamespacedPath(path.win32.toNamespacedPath("D:\\abc"))
'\\\\?\\D:\\abc'
```
Wrapped `src` and `srcFilePath` (two arguments to `path.relative`) with `path.toNamespacedPath` so `path.relative` works.
# Test Plan
Will release and test.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Since v15 files that should be ignored get added to the tarball on Windows.
# How
After adding some debugging I was able to find that `src`, `srcFilePath` don't match on path separators which breaks `ignore.ignores`.
<img width="827" alt="Zrzut ekranu 2025-02-7 o 21 57 02" src="https://github.com/user-attachments/assets/9ed3b166-dbc0-4287-87a1-0009769e0d4d" />
Added `path.normalize` if `__NORMALIZE` is `1`.
---
Also noticed we used wrong `cwd` for is-tracked check.
# Test Plan
Going to release this and test.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
`requireCommit: true` setups expect worktree to be clean (e.g. encrypted files to be locked).
# How
Made it so if `requireCommit` is true we don't copy files over.
# Test Plan
I have enabled `git-crypt` in my test repository, added a secret file, ran `easd build:inspect -p android -s archive -o ~/test-production --force`. The clone did contain secret file in plaintext.
Then I enabled `requireCommit: true` and repeated the command. The clone did contain the file encrypted.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
`git ls-files` returns submodules as a single filepath entry, so `rm` must remove it with `-rf`. Fixes https://github.com/expo/eas-cli/issues/2883.
# How
Added `{ recursive: true, force: true }` to `fs.rm`.
# Test Plan
I tried `easd build:inspect -p android -s archive -o ~/testtest --force` on a repo with a submodule in `.easignore`. It succeeded and the submodule was not included in the folder.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Adding `.git` directory to the tarball makes it bigger. Users notice this warning and want it to be actionable, but currently adding `.git` to `.easignore` does nothing.
# How
For now, raise threshold for warning from 100 MiB to 150 MiB. In the next pull request I'm going to fix `.git` exclusion via `.easignore`.
# Test Plan
CI should pass.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Currently it's not possible to exclude `.git` from being uploaded in project tarball.
# How
In `makeShallowCopyAsync()` we first clone the repository, then we delete files ignored by `.easignore` and then we copy working directory over.
The "delete files ignored by `.easignore`" step is governed by `git ls-files --exclude-from=.easignore`. `git ls-files` is never going to consider `.git` directory to be excluded, even if specified in `.easignore`, so we need to special-case the `.git` directory and remove it manually if specified.
# Test Plan
Added `.git` to a test `.easignore`, ran `eas build:inspect` and confirmed the copied directory did _not_ contain `.git` folder.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
`fs-extra` fails to copy symbolic links as one would expect. https://github.com/jprichardson/node-fs-extra/issues/708
# How
We could:
- copy and dereference symbolic links — make it so that the clone of the original directory has two copies of the files -- original and linked
- copy symbolic links without re-resolving, assuming any links will be relative and should work when unpacked on a different machine.
I think we can count on the latter.
# Test Plan
Created a link in my test repository
```
drwxr-xr-x 7 sjchmiela staff 224B Jan 28 16:14 assets
lrwxr-xr-x 1 sjchmiela staff 6B Feb 4 22:12 assets-linked -> assets
```
ran
```
easd build:inspect -p android -s archive -o ~/testtest --force
```
confirmed I see
```
drwxr-xr-x 7 sjchmiela staff 224B Feb 4 22:20 assets
lrwxr-xr-x 1 sjchmiela staff 6B Feb 4 22:20 assets-linked -> assets
```
in the result directory.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
`[email protected]` doesn't interpret `.easignore` right because I haven't initialized the `Ignore` class properly.
# How
Make it so it's not possible to use `Ignore` without initializing it.
# Test Plan
Tests should pass.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
If you had an `.easignore`, `isFileIgnoredAsync` was always thinking all files are NOT ignored which was causing it to think all builds are in `.GENERIC` mode (with native code) which was not true, because ACTUALLY the files WERE ignored.
All mostly because of forgotten `ignore.initIgnoreAsync()`…
# How
Added `ignore.initIgnoreAsync()`. Also realized whether the file is tracked / not-tracked may affect how actually is it going to behave, so added it to the mix.
# Test Plan
Added tests that I think test all cases.
# Why
receiving an issue for a customer who uses eas environment and continuous-deploy-fingerprint github action. they have build variants setup in their app.config.ts. the app id, scheme and some other properties are determined by their `APP_VARIANT` variable. the `APP_VARIANT` is from eas server environment.
when continuous-deploy-fingerprint first calculates fingerprint, it uses `eas env:exec` for the `npx expo-updates fingerprint:generate` call. the `APP_VARIANT` is correctly passed.
then for `eas update` call, it doesn't pass the `APP_VARIANT` env and generates an inconsistent fingerprint.
# How
pass server env to the `getRuntimeVersionInfoObjectsAsync()` (`npx expo-updates runtimeversion:resolve`)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We don't need to redownload app every single time in `eas build:dev`. We can cache it locally. This functionality already exists for `eas build:run`.
# How
Use caching the same way we do for `eas build:run`
# Test Plan
Tested manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
@brentvatne suggested that it would be useful to let people know how long the previous build took when rebuilding in `eas build:dev`
# How
Get the information about how long previous build took and show it to the user
# Test Plan
Tested manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Currently, when `eas-cli` create a project tarball for EAS Build or Workflows, unless the user has `requireCommit: true` in `eas.json`, the project is being packed with a plain `makeShallowCopyAsync` which copies all the files that are deemed ignored by `ignore` package and `.easignore` or `.gitignore` files.
This is suboptimal for `eas workflow:run` experience — a developer with a project with Git expects the repository to exist on EAS.
# How
This was a big pain.
Previously, we had `GitClient` which required commit and its subclass, `GitNoCommitClient` which overrode some functions to allow uncommitted changes. On top of that, `GitClient` copied project with `git clone`, while `GitNoCommitClient` copied it with `makeShallowCopyAsync`. This meant `GitClient`'s copy would include `.git`, whereas `GitNoCommitClient` would not. Moreover, thus, `GitClient` would adhere to `.gitignore` and `GitNoCommitClient` would _not_ — only to `.easignore`.
This pull request:
- merges the two Git clients into one with `requireCommit` option
- this causes `.git` directory to exist in copies with `requireCommit = false`
- changes how we log changes caused by Git case sensitivity change (we need to handle the case where there is a preexisting dirty tree)
- after we clone the repository, we delete files that should have been ignored according to `.easignore`
- afterwards, we make a shallow copy of all the files over to the clone. This copies live changes to the working tree over to the clean clone. (They may only exist in `requireCommit = false` situation.)
- adds better support for `.easignore` to `isFileIgnoredAsync`.
As far as I can see the behavior looks like this:

The breaking change in here is that we're going to start adhering to `.easignore` even if someone has `requireCommit = true`.
# Test Plan
I used `easd build:inspect` a bunch to verify it works like I expect. I encourage fellow reviewers to do the same.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C017N0N99RA/p1738630158821649
# How
Print warn message only once
# Test Plan
Tests
# Why
Add support for users accidentally passing in update group id into `fingerprint:compare` instead of update id.
# How
Added support for handling update group IDs in the fingerprint comparison command by:
- Attempting to fetch updates using the provided ID as an update group ID
- If successful and there's only one update, using that update directly
- If multiple updates exist in the group, prompting the user to select the specific platform/update
- Falling back to the original update ID logic if the group ID lookup fails
- Adding helpful error messages that include the direct URL to find the correct update ID
# Test Plan
- [ ] `EXPO_STAGING=1 ~/Documents/eas-cli/packages/eas-cli/bin/run fingerprint:compare --update-id ed36a46b-6cc7-4f49-88df-e6ffb66f22d2`
- [ ] `EXPO_STAGING=1 ~/Documents/eas-cli/packages/eas-cli/bin/run fingerprint:compare --update-id ed36a46b-6cc7-4f49-88df-e6ffb66f22d2 --non-interactive`
# Why
Add support for comparing fingerprints between updates using the `--update-id` flag in the `eas fingerprint compare` command. This allows developers to compare fingerprints between updates, similar to how they can already compare fingerprints between builds.
# How
- Added `updateId` flag to the `FingerprintCompare` command
- Extended the fingerprint comparison logic to handle updates as a fingerprint source
- Added `UpdateQuery.viewByUpdateAsync` to fetch update details including fingerprint information
- Updated the fingerprint origin type system to include updates as a source
- Enhanced the pretty printing of fingerprint sources to show platform information for updates
# Test Plan
- [ ] `EXPO_STAGING=1 ~/Documents/eas-cli/packages/eas-cli/bin/run fingerprint:compare --update-id 087ccb84-5b64-4285-aebf-e890cb95cd20`
* [eas-cli] add eas dev command
* update logs
* rename command do `build:dev`
* filter by dev client
* apply suggested changes
* use real vs virtaul build profiles
* make it hidden
* prompt to commit after adding new build profile
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-14307: move environment to job object from metadata](https://linear.app/expo/issue/ENG-14307/move-environment-to-job-object-from-metadata)
`Environment` should be considering a first class citizen in job object instead of being stored in the metadata.
# How
* Pass `environment` in `job` object
* remove `environment` from `metadata`.
# Test Plan
1. Start a build specifying `environment` in `eas.json`.
2. Build should use the specified environment (check on website in `Build details`)
* Replace preview with help
* Remove redundant alias
* Update description
* Rename top level command from worker -> deploy
* Add changelog
* End sentence with a .
* Add worker:deploy as an alias to deploy
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Allow filtering by `--fingerprint-hash` in the `eas build:list` command
# How
Update GQL schema to add a new filter field, and add a new flag to use it.
# Test Plan
Test locally
* Allow env vars to be loaded from .env and EAS env simultaneously
* Add CHANGELOG entry
* Apply lints
* Switch to new @expo/[email protected] API
* Update packages/eas-cli/src/commands/worker/deploy.ts
Co-authored-by: Kadi Kraman <[email protected]>
---------
Co-authored-by: Kadi Kraman <[email protected]>
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-14518: Add `keystoreName` field to build profile to allow selecting/creating named keystore to use for a build](https://linear.app/expo/issue/ENG-14518/add-keystorename-field-to-build-profile-to-allow-selectingcreating)
Allow specifying keystore name of credentials to be used with a build.
# How
* Added `keystoreName` to eas.json schema
* Pass `name` option to `AndroidCredentialsProvider`
# Test Plan
Added test, tested manually.
1. Create a new android credentials with `eas credentials`
2. Specify `keystoreName` in build profile in `eas.json`
3. Ensure that it works only for android builds
4. Ensure it works only for `remote` `credentialsSource`
5. Ensure that the correct credentials are used
<img width="326" alt="image" src="https://github.com/user-attachments/assets/1245c459-5fa1-4253-b5fc-bdf7a68b814a" />
<img width="628" alt="image" src="https://github.com/user-attachments/assets/5bca4cf7-c895-462c-b527-ef37ce659aca" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Thanks to @szdziedzic's changes to `www`, if we send a `package.json` along with `eas.json` when setting up a workflow run, EAS will pick the right images based on SDK and RN versions as `eas build` would.
# How
Added uploading `package.json` after uploading `eas.json`, added the new argument to the mutation.
# Test Plan
Tested manually.
<img width="874" alt="Zrzut ekranu 2024-12-20 o 22 27 20" src="https://github.com/user-attachments/assets/383c4a19-17a1-4f46-8113-bc6dc8aaba2e" />
<img width="833" alt="Zrzut ekranu 2024-12-20 o 22 27 58" src="https://github.com/user-attachments/assets/be9e2396-0779-4043-925f-d784b5168764" />
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-14328: store `environment` info on update entity](https://linear.app/expo/issue/ENG-14328/store-environment-info-on-update-entity)
Pass `environment` to `PublishMutation.publishUpdateGroupAsync` to store in the db.
Waits for changes on the `www`. https://github.com/expo/universe/pull/17921
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
It seems like this file includes redundant entries + is not up to date
# How
Remove redundant entries, add @radoslawkrzemien to global codeowners, make @wschurman and @quinlanj codeowners of everything EAS Update related (including channel commands), remove @byCedric and @EvanBacon from EAS Update codeowners
# Test Plan
Review
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://discord.com/channels/695411232856997968/1309202098591633458/1311040361040183429
# How
Make warning up to date after recent env vars changes
# Why
Update `@expo` packages to SDK 52 versions
# How
Update `@expo` packages to SDK 52 versions
Fixes#2696
It seems like the `privacy` field was removed from the expo config in the SDK 52 update: https://expo.dev/changelog/2024/11-12-sdk-52.
I used `AppPrivay.Unlisted` for the `createApp` mutation input for which this is still required. It was an option selected for an app when `exp.privacy` was undefined.
It also seems that `findWorkspaceRoot` function in `@expo/package-manager` was changed to `resolveWorkspaceRoot`.
# Test Plan
Tests, test commands manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C06FK950085/p1732258126230829
# How
Improve logs
# Test Plan
Tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Add environment to `eas.schema.json`
# How
Add environment to `eas.schema.json`
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C06FK950085/p1729212611408479?thread_ts=1729186741.835629&cid=C06FK950085
# How
Resolve the default (if not set in the build profile) `environment` to use for a build based on its configuration.
Store build -> `production`
Dev client -> `development`
Other (`internal`) -> `preview`
# Test Plan
Test manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Make `eas env` commands visible
# How
Make `eas env` commands visible
# Test Plan
Tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Deprecate old secret commands
# How
Mark as hidden + print warn when used
# Test Plan
Tests
# Why
This PR computes a fingerprint for each update.
- If the update does not use the fingerprint policy, it calculates the fingerprint using the exported cli in the `expo` package for projects SDK 52+.
- If the update uses the fingerprint policy, it just uses the fingerprint that was previously calculated using `expo-updates`.
# How
- Modified fingerprint computation to handle platform-specific cases
- Updated the fingerprint data structure to use `fingerprintHash` instead of the full fingerprint object
- Added support for computing fingerprints for projects without expo-updates
- Introduced new types and interfaces for handling fingerprint information groups
- Created utility functions for async map operations and fingerprint calculations
- Updated GraphQL schema to support new fingerprint-related fields
# Test Plan
- [x] on build: verify fingerprints till work
- [x] on update: verify fingerprint is calculated for new project with SDK 52
- [x] on update: verify no fingerprint is calculated for old project (< SDK 52)
- [x] on update: verify fingerprint is reused for project with fingerprint runtime policy
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Make class names more consistent with other commands
Improve descriptions
# How
Make class names more consistent with other commands
Improve descriptions
# Test Plan
Tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Stick to account-wide everywhere for now
# How
Rename shared to account-wide, fix some bugs and type issues
# Test Plan
Tests
# Why
Adds `eas workflow:create` to make it faster to create workflow files in a project. This command creates a file like **.eas/workflows/workflow.yml**. The user can choose the file name or can provide it as an arugment.
# Screenshots
<img width="552" alt="Screenshot 2024-11-08 at 8 50 58 AM" src="https://github.com/user-attachments/assets/5cf82e7e-cce6-4098-b291-fccdac25f103">
<img width="584" alt="Screenshot 2024-11-08 at 8 51 27 AM" src="https://github.com/user-attachments/assets/d6f6e7cb-18c1-420e-b52a-5bdd42446715">
<img width="617" alt="Screenshot 2024-11-08 at 8 52 04 AM" src="https://github.com/user-attachments/assets/81cc79cf-afb7-4855-bfce-0679f98655fa">
# Test Plan
Make sure that you can run the command as pictured above and that it correctly creates the workflow file. Also make sure that the unit tests pass.
# Future
Once we have docs for workflows that are public, I'd like to put a link to the docs in the default file this command creates. For now, I am just putting Hello World as a reasonable placeholder.
Co-authored-by: Szymon Dziedzic <[email protected]>
Co-authored-by: Stanisław Chmiela <[email protected]>
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Going to release soon.
# How
Removed `hidden = true` overrides.
# Test Plan
`easd --help` printed out information about workflow commands.
```
~/Developer/test-local (main [$!]) easd --help
EAS command line tool
VERSION
eas-cli/13.1.1 darwin-arm64 node-v22.4.0
USAGE
$ eas [COMMAND]
TOPICS
...
workflow manage workflows
```
```
~/Developer/test-local (main [$!]) easd workflow --help
manage workflows
USAGE
$ eas workflow:COMMAND
COMMANDS
workflow:run Run an EAS workflow
workflow:validate validate a workflow configuration yaml file
```
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
- running workflows requires GitHub connection
- workflow config may be a valid YAML, but invalid config
We want to check both of these:
- in `workflow:validate`
- before we upload project sources to GCS in `workflow:run`.
# How
I added a `validateWorkflowRevisionYamlConfig` mutation I'm using here to validate the config _and_ GitHub connection. The GitHub requirement is checked dynamically in `www` so we can later remove it without having users upgrade to a newer `eas-cli`.
Brent also wished `eas workflow:run test.yml` resolved `test.yml` to `.eas/workflows/test.yml` automatically, so added this too.
# Test Plan
I tried validating and running invalid YAMLs, workflows and valid configs. Things seemed to work ok.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
During dogfooding it came out that this flag is too long and confusing
# How
Just use `environment`
# Test Plan
Tests, types
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Counterpart of https://github.com/expo/eas-cli/pull/2677, applied to `submit:internal`.
# How
Copied the solution from `build:internal`.
# Test Plan
None.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We need to use `build:internal` to resolve build configuration in GCS workflow jobs which have no Git repository.
# How
I'm going to be adding `EAS_NO_VCS=1` to GCS workflow jobs. This should prevent `build:internal` from requiring Git repository.
# Test Plan
I have verified `EAS_BUILD_ID=d7fb9f5c-dce0-40e2-b459-cbc05ba1ed77 EAS_NO_VCS=1 easd build:internal -p android` prints the JSON output on my computer.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We want to allow users to start workflows manually.
# How
I added a `createRunMutation` to GraphQL and used it here. We upload project archive, `eas.json` and use to start a new workflow run.
# Test Plan
```
Workflows are in beta and subject to breaking changes.
Compressing project files and uploading to EAS. Learn more: https://expo.fyi/eas-build-archive
✔ Uploaded eas.json to EAS
✔ Uploaded project archive to EAS 1s
✔ Workflow started successfully. https://staging.expo.dev/accounts/sjchmiela/projects/staging-app/workflows/019301f1-b1b4-700d-9e3b-82dc97d76a32
```
Co-authored-by: Szymon Dziedzic <[email protected]>
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
update expo packages to SDK 51 versions
revert https://github.com/expo/eas-cli/pull/2524
# How
update expo packages to SDK 51 versions
# Test Plan
tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C02123T524U/p1724970663050089?thread_ts=1724924614.773089&cid=C02123T524Uhttps://exponent-internal.slack.com/archives/C5ERY0TAR/p1725002816077089
Generally `@expo/config`, `@expo/prebuild-config`, and `@expo/config-plugins` are per SDK concept. Currently, in EAS CLI, we rely on one version of the `@expo/...` package to work well globally for all SDKs. It seems to sometimes bite us like in the case of https://exponent-internal.slack.com/archives/C02123T524U/p1724909908574979, because SDK 51 config wasn't compatible with SDK 50.
It's better to switch to using config-related functions shipped with `@expo/config`, `@expo/prebuild-config`, and `@expo/config-plugins`. I believe we can assume that `getConfig`, `getPrebuildConfig`, and `compileModsAsync` shipped with these packages have stable API https://exponent-internal.slack.com/archives/C5ERY0TAR/p1725293002128849?thread_ts=1725002816.077089&cid=C5ERY0TAR.
# How
Use `getConfig`, `getPrebuildConfig`, and `compileModsAsync` from `@expo/config`, `@expo/prebuild-config`, and `@expo/config-plugins` shipped with Expo SDK installed in the user's project. If not available, fallback to versions installed per SDK. If we can assume that these guarantee stable API we can use types of these functions from packages installed for EAS CLI as well.
# Test Plan
Run builds for repro case of https://exponent-internal.slack.com/archives/C02123T524U/p1724909908574979 with SDK 51 config packages installed for EAS CLI (that previously broke it), see that it works and capabilities are correctly synced.
Initiate a new bare RN project using community CLI, and check that it works as well using fallback config loading.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Add support for `with-eas-environment-variables-set` flag in `eas update:configure` command
# How
Use the flag the same way we do for `eas update`.
# Test Plan
Run command.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Make the `with-eas-environment-variables-set` flag reusable and improve type safety and description.
# How
Extract `with-eas-environment-variables-set` to separate file. Improve validation and type safety.
# Test Plan
Run command locally.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Add new Xcode 16.1 image and `sdk-52` tag to `eas.schema.json`
# How
Add new Xcode 16.1 image and `sdk-52` tag to `eas.schema.json`
# Test Plan
Tests
# Why
[ENG-13930: Allow passing environment without the flag](https://linear.app/expo/issue/ENG-13930/allow-passing-environment-without-the-flag)
Added capability to pass `environment` without `--environment` flag to `eas env:*` commands. This is often more intuitive.
This works only for a single environments. In case user wants to pass more than one, `--environment` flag should still be used.
# Changed commands
## `env:create`
* was only `env:create --name thisisvar --value thisinew --visibility plaintext --environment production`
* now also `env:create production --name thisisvar --value thisinew --visibility plaintext`
## `env:delete`
* was only `env:delete --variable-environment production --variable-name NEW_VAR`
* now also `env:delete production --variable-name NEW_VAR`
## `env:exec`
* was only `env:exec --environment development 'echo lol'`
* now also `eas env:exec development 'echo lol'`
## `env:get`
* was only `env:get --variable-environment development --variable-name HELLO`
* now also `env:get development --variable-name HELLO`
## `eas env:link`
* was only `eas env:link --environment preview --variable-name NAME`
* now also `eas env:link preview --variable-name NAME`
## `eas env:list`
* was only `eas env:list --environment preview`
* now also `eas env:list preview`
## `eas env:pull`
* was only `eas env:pull --environment production`
* now also `eas env:pull production`
## `eas env:push`
* was only `eas env:push --environment production`
* now also `eas env:push production`
## `eas env:unlink`
* was only `eas env:unlink --environment production --variable-name NAME`
* now also `eas env:unlink production --variable-name NAME`
## `eas env:update`
* was only `eas env:update --variable-environment production --variable-name HELLO --environment development`
* now also `eas env:update production --variable-name HELLO --environment production`
# Test Plan
Updated tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
As suggested in the base PR we need a simple context focused on only getting the project ID, without specifying the server-side environment and resolving Expo config with it.
# How
Add such context. Make the `withServerSideEnvironment` argument required for standard project config context.
# Test Plan
Tests, test manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C013ZK4SA12/p1725644220583309
We are planning to introduce enhancements to our env vars system soon. Currently, we only allow people to keep secrets on EAS servers. Secrets are not readable outside of EAS servers so of course EAS Update doesn't work with them. In a new system, people can also store readable env vars on our servers, which opens new possibilities about how EAS Update can interact with env vars!
In this PR I'm adding support for the `--with-eas-environment-variables-set production|preview|development` flag. If used, we use the flag's value to fetch readable env vars from our servers and use it in the `expo export` command to produce an update bundle based on these env vars. If the flag is used I'm using the `EXPO_NO_DOTENV` flag to disable Expo CLI from loading env vars from `.env` files and potentially unwillingly overwriting env vars fetched from our servers for a given environment.
Users seem to face big issues with using env vars with EAS Build & Update at the moment, originating from the fact that these 2 handle different, non-compatible ways of using env vars. Env vars in the build profile and server-side secrets vs local env vars + `.env`. With this flag it will be easy to avoid envs mismatch by doing `eas update ----with-eas-environment-variables-set environment` and `eas build` with `{ ..., environment: environment, ...} in the build profile!
# How
Add a new hidden (for now) flag `--with-eas-environment-variables-set` that indicates which environment to use. If used fetch env vars from server. Merge and overwrite `process.env` with newly fetched env vars. Use them to resolve the expo config. Don't use `.env` env var loading from Expo CLI if server-side env vars are used.
# Test Plan
Test manually. Run `eas update` with and without a new flag. Check that the expo config is resolved correctly.
# Why
File variables were not handled by the `env:pull` command. They should be downloaded just like the other values.
# How
* `env:pull` saves file type variables to `.eas/.env` directory and sets its value in `.env.local` file to its file path
* `env:push` skips file type variables
# Test Plan
Tested manually
# Why
We want to allow developers to prevent updates from being served to certain builds by "pausing" update channels.
# How
- I added two new CLI commands to toggle the channel pausing state
- I added the pause status to the channel details output in the `view` and `list` commands
# Test Plan
Build the CLI locally under the `neas` alias, and run `neas channel:pause development && neas channel:view development && neas channel:resume development && neas channel:view development`:
<img width="1364" alt="Screenshot 2024-10-17 at 05 33 36" src="https://github.com/user-attachments/assets/fd557e57-bbf7-463c-8cec-1febcb2fdde8">
# Why
[ENG-13853: Prompt user to enter the environment when not provided vs fail and rerun when using `eas env:push`](https://linear.app/expo/issue/ENG-13853/prompt-user-to-enter-the-environment-when-not-provided-vs-fail-and)
If the environment is not provided, we ask the user about it in other commands, I think we can do the same here for consistency vs throwing an error and having the user rerun it
# Test Plan
Tested manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Rely on ExpoConfig type from the `@expo/config` package in all places for consistency
# How
Rely on ExpoConfig type from the `@expo/config` package in all places for consistency
# Test Plan
Tests
# Why
User should be able to upload files to environment variables and read content of those files
# How
* When an envvar is created with flag `--type FILE`, selected file is encoded to base64 and sent to www.
* EnvVarQueries return file contents when `includeFileContent` file is passed
* `env:get` automatically include file content, `env:list` requires `--include-file-content` flag
* Updated environment display - added `environments`, `type` and `visibility`
# Test Plan
tested manually, updated tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Update command to use multiple environments, polish the interface.
# How
* use `variable-name` and `variable-environment` to select the variable
* Use `multiselect` and multiple `environment` parameters to allow unlinking multiple envs
All commands that were using name parameter to identify a single variable will use variable-name and variable-environment instead. This change will enable user to distinguish between name and environment that is identifying variable that is acted upon, and name and environment that is a parameter for command.
For example, when the user wants to update variable TEST that has environment production and change its name and change its environment, they can use:
eas env:update --variable-name TEST --variable-environment production --name TEST-update --environment production --environment preview
# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Allow selecting multiple environments to display variables from.
# How
* Use `multiselect`, allow specifying multiple `environment` parameters
* List variables from all environments
# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Add tests, polish the interface
# How
* Use `variable-name` and `variable-environment` to select the variable
* More robust selector of variable to remove ambiguity
* Use multiselect to clearly indicate which environments are linked and which are not
* Automatic `link` and `unlink` action
All commands that were using name parameter to identify a single variable will use variable-name and variable-environment instead. This change will enable user to distinguish between name and environment that is identifying variable that is acted upon, and name and environment that is a parameter for command.
For example, when the user wants to update variable TEST that has environment production and change its name and change its environment, they can use:
eas env:update --variable-name TEST --variable-environment production --name TEST-update --environment production --environment preview
# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Rework the EnvironmentVariableUpdate function - user is able to alter name, and environments.
# How
* Added `--variable-name` and `--variable-environment` parameters to identify the variable to update
* Using parameters from `--name` and `--environment` to update the variable using the new `updateEnvironmentVariable` method.
All commands that were using name parameter to identify a single variable will use variable-name and variable-environment instead. This change will enable user to distinguish between name and environment that is identifying variable that is acted upon, and name and environment that is a parameter for command.
For example, when the user wants to update variable TEST that has environment production and change its name and change its environment, they can use:
eas env:update --variable-name TEST --variable-environment production --name TEST-update --environment production --environment preview
# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Improve the selector for the variable to delete, rename parameter `name` to `variable-name`.
All commands that were using name parameter to identify a single variable will use variable-name and variable-environment instead. This change will enable user to distinguish between name and environment that is identifying variable that is acted upon, and name and environment that is a parameter for command.
For example, when the user wants to update variable TEST that has environment production and change its name and change its environment, they can use:
eas env:update --variable-name TEST --variable-environment production --name TEST-update --environment production --environment preview

# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Polished the interface:
- user is prompted for environment only when the name is ambiguous.
- changed `name` parameter to `variable-name`.
All commands that were using `name` parameter to identify a single variable will use `variable-name` and `variable-environment` instead. This change will enable user to distinguish between `name` and `environment` that is identifying variable that is acted upon, and `name` and `environment` that is a parameter for command.
For example, when the user wants to update variable `TEST` that has environment `production` and change its name and change its environment, they can use:
`eas env:update --variable-name TEST --variable-environment production --name TEST-update --environment production --environment preview`
# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Update `eas env:create` to accept multiple `--environment` parameters.
# How
* Use `EASMultiEnvironmentFlag` in `EnvironmentVariableCreate`
* Update variable display with `environment` and `updatedAt` fields
# Test Plan
Added tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525: Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
EnvVar will support having multiple environments, CLI should support this.
# How
* Add an optional parameter `multiple` to `promptVariableEnvironmentAsync`
* Update commands using `promptVariableEnvironmentAsync`
* Add a new flag `EASMultiEnvironmentFlag`
# Test Plan
Tested manually, tests will be added in the following PRs
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525 Update EAS-CLI for new EnvVar features](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Bring up to date `create` and `update` EnvVar mutations.
# How
* Use `updateEnvironmentVariable` operation instead of `createEnvironmentVariable` with an 'overwrite' option.
* Add `type` parameter
* Add `environment` parameter for shared variables
# Test Plan
Tested manually, tests will be added in the following PRs
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
[ENG-13525 Update EAS-CLI for new EnvVar features
](https://linear.app/expo/issue/ENG-13525/update-eas-cli-for-new-envvar-features)
Update EnvVar queries - allow quering using environments.
# How
* Added optional `environment` parameter to queries
* Fix typing of the `--environment` parameter
# Test Plan
Tested manually
* Update API functions for new upload endpoint and deploy result
* Fix listWorkerFilesAsync file type
* Add call to finalize deployment
* Update CHANGELOG
* Add retries to /deploy/finalize call
* Apply lints
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C017N0N99RA/p1726226230206999
Right now the only way to exit the `eas credentials` command is to kill the process by doing ctrl+c. Let's add an `exit` option to the interactive menu.
# How
Add exit option to menu.
# Test Plan
Test manually
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
On Friday's meeting, we agreed that having both a flag and a field in the build profile for setting the environment might be too much. Additionally, we already have a `--profile` flag that has a `-e` alias which makes it even more confusing. We decided to delete the flag to avoid confusion and make it as straightforward as possible.
# How
Delete the `--environment` flag for build-related commands, rely only on the `environment` field in eas.json.
# Test Plan
Tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Add the `eas env:exec` command. This command allows you to run any arbitrary bash command with env vars from a given environment.
# How
Add `eas env:exec` command
# Test Plan
Test manually

* refactor(eas-cli): split prompt from dev domain assignment and support it non-interactive
* docs: add changelog entry
* docs: fix changelog entry
* fix(eas-cli): use proper name in "already taken" prompt
* chore: resolve linting issue
# Why
Almost a year ago we've migrated from using a single file for submission logs to multi-file logs, accommodating need to display logs from both the worker and the scheduler that is starting the worker VM.
Companion to https://github.com/expo/universe/pull/16873.
# How
Replaced `logsUrl` with `logFiles`, adjusted code.
# Test Plan
Logs printed
<img width="1055" alt="Zrzut ekranu 2024-09-24 o 23 06 22" src="https://github.com/user-attachments/assets/6c9a45c0-6760-4629-82e3-a79d5ef99ebe">
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I want to add support for submissions as part of workflows, where, when we start the job, we don't have access to the repository. So, we need to resolve submission config _somewhere_, ideally where we are isolated, can easily clone project, install dependencies and resolve dynamic config.
As we do with `eas build:internal`, I expect it will make sense to do `eas submit:internal` which will do what `eas submit` does usually — resolve all the credentials, using local filesystem or Expo servers and then fetch the _actual_ keys from Expo servers.
# How
First, I changed structure of `SubmitCommand`/`Submitter` a bit — previously, `SubmitCommand` would create the `Submitter` and call `submitAsync` _inside_ `runAsync()`. After my changes `SubmitCommand` will create _and return_ the `Submitter` and the call site will need to call `submitAsync`.
By doing it this way I was able to add a `getSubmissionInputAsync` to `BaseSubmitter` which returns all-resolved submission input, as-it-would-have-been-used-in-submission-mutation. This ensures the same behavior for `eas submit` and `eas submit:internal`.
Once we have that, `eas submit:internal` is relatively straightforward:
1. create `SubmitCommand`, get `Submitter`.
2. `getSubmissionInputAsync`.
3. fetch necessary credentials by IDs from `www` (https://github.com/expo/universe/pull/16793).
4. validate that we have it all (https://github.com/expo/eas-build/pull/443) and print the JSON.
# Test Plan
I was able to run `easd submit:internal` locally and got the JSON output.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
In a submit job we're going to have an IPA/APK to submit. We don't want to resolve any bundle identifiers from the project, we can use one from that IPA/APK.
# How
Let the override env variable override bundle identifier resolution if the workflow is managed too.
# Test Plan
I used it to submit an IPA with workflows.
* refactor(eas-cli): enhance the `--environment` help description
* docs(eas-cli): add changelog entry
* docs(eas-cli): add missing periods to `eas worker:alias --help`
* refactor(eas-cli): enhance the `--environment` help description
* fix(eas-cli): hide project export date when not older than 1m
* fix(eas-cli): add back no export error
* docs(eas-cli): add changelog entry
* chore(eas-cli): add `--platform=web` to error command
* docs(eas-cli): fix changelog entry
* refactor(eas-cli): always default to static uploads and add modified time
* docs(eas-cli): add changelog entry
* chore(eas-cli): resolve linting issue
* fix(eas-cli): error when there are no deployments
* fix(eas-cli): remove unused `exp` var
* fix(eas-cli): fix json output again
* feature(eas-cli): add `worker:alias --prod` flag to promote existing deployments
This also includes some clean ups and log utility sharing
* feature(eas-cli): support `worker:promote --prod --id`
* refactor(eas-cli): rename `/serverless/deployments` -> `/hosting/deployments`
* docs(eas-cli): add changelog entry
* chore(eas-cli): resolve linting issues
* fix(eas-cli): disable ora when possibly asking for a dev domain
* chore(eas-cli): resolve typing issue
* feature(eas-cli): add `worker --export-dir` flag to select export folder
* docs(eas-cli): add changelog entry
* fix(eas-cli): use `path.join` instead of `path.resolve`
`path.resolve` throws when the path does not exist, `path.join` uses our own validation errors.
* docs(eas-cli): fix changelog entry
* refactor(eas-cli): reuse same working in `eas worker:alis` from `eas worker`
* refactor(eas-cli): reuse same result table from `eas worker`
* docs(eas-cli): update changelog entry
* refactor(eas-cli): use `Alias URL` instead of `Aliased URL`
* refactor(eas-cli): add support for both `--prod` and `--production` flags in `eas worker`
* chore: add changelog entry
* refactor(eas-cli): also tweak `--help` output
* refactor(eas-cli): move `--prod` before `--alias`/`--id` in usage
* refactor(eas-cli): clean up ora spinners and add table output
* refactor(eas-cli): simplify project type detection
* refactor(eas-cli): simplify alias and production spinners
* docs(eas-cli): update changelog entry
* chore: resolve linting issues
* refactor(eas-cli): use `Alias URL` instead of `Aliased URL`
* fix(eas-cli): mark `production` as bold in ora spinners
* fix(eas-cli): avoid adding `expo.extra` data from config plugins in `eas init`
Note that in the newer `@expo/config` package, modifying now also merges existing properties. Once thats released, we can use that instead of manually merging this data.
* docs(eas-cli): add changelog entry
* feature(eas-cli): add `worker:alias` command to assign aliases
* feature(eas-cli): add worker selection when assigning alias
* refactor(eas-cli): clean up comments and prompt for alias
* refactor(eas-cli): clean up command and flag descriptions
* chore: resolve linting issues
* docs: add changelog entry
* Add `@expo/env`
* Source env variables from ".env" via `@expo/env` to deployment
* Add CHANGELOG
* Increase requested range for `@expo/env`
* Apply lints
* Added --non-interactive and --force support when --id is not passed to eas init command
* Removed id dependency from init command flags
* Bump undici from 5.19.1 to 5.26.3
Bumps [undici](https://github.com/nodejs/undici) from 5.19.1 to 5.26.3.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.19.1...v5.26.3)
---
updated-dependencies:
- dependency-name: undici
dependency-type: indirect
...
Signed-off-by: dependabot[bot] <[email protected]>
* Revert "Bump undici from 5.19.1 to 5.26.3"
* Apply suggestions from code review
Co-authored-by: Szymon Dziedzic <[email protected]>
* Fixed initializeWithoutExplicitIDAsync not being used
* Require force flag to use default account when no account name is specified in non-interactive mode
* Changed error message when user has access to multiple accounts in non-interactive mode
* Added changelog entry
* Update CHANGELOG.md
Co-authored-by: Szymon Dziedzic <[email protected]>
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ryan Button <[email protected]>
Co-authored-by: Szymon Dziedzic <[email protected]>
* [fix]: correctly retrieve entitlements for extensions using their own target name
Fixed an issue where extensions were incorrectly retrieving the main app's entitlements instead of their own. Updated the code to use `dependency.name` for fetching the correct entitlements.
* update CHANGELOG.md
---------
Co-authored-by: Harris Han <[email protected]>
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
companion to https://github.com/expo/third-party/pull/104
# How
This is my first PR adding new capabilities so please double-check if I did everything correctly, I based it on 6389f52
I got new entitlements from https://developer.apple.com/documentation/bundleresources/entitlements?changes=latest_major and added all available capabilities corresponding to these.
# Test Plan
Run prod build manually, add new entitlements for new capabilities to app config, and verify that they were enabled on the provisioning profile
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://exponent-internal.slack.com/archives/C02123T524U/p1724909908574979
It seems like SDK 51 config-related packages update broke builds for older SDKs
# How
I believe we didn't add any new config-related features in SDK 51, so resolving the config using the package version for SDK 50 should be ok for now and shouldn't cause any trouble.
Revert #2498
# Test Plan
Tests
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
https://github.com/expo/eas-cli/issues/2519
I was able to reproduce the issue and it is indeed true. It seems like we mistakenly added a static project config definition to the `eas build` command context in https://github.com/expo/eas-cli/commit/56510f092527e458aa9dca19feac0b5d425dac56#diff-cd2e00f4d286a4714f8736e14c635f4c3b98c402367cd71a83e4cd743034bd79. The output from it wasn't really used anywhere, but adding it caused the app configs to be evaluated without `buildProfile.env` in the first pass when trying the resolve project ID and slug at the begging of command execution and our slug/project ID assertions to fail. It only affected people with dynamic project IDs and slug fields.
# How
Remove unnecessary static context from context definitions, therefore avoid resolving project ID and slug from app config without env vars as a first thing when the `eas build` command is executed.
# Test Plan
Tested manually
* Add fingerprint sources to build metadata
* Upload fingerprint to google cloud
* Rename fingerprintGCSLocation -> fingerprintGCSBucketKey
* Add fingerprint source in an object
* Update dependencies
* Add comment about fingerprintSources
* Add a changelog entry
* Add support for local build plugin
* Add safety check that a temp directory exists
* [eas-cli] make sure we filter out any comments in `build.gradle` file before passing to to `gradle-to-js` parser
* use trim
* add test
* add changelog
* chore: update node versions to test with to 18, 20, 22
* update CHANGELOG.md
* chore(eas-cli)!: bump minimum supported Node version to 18
This makes the PR a breaking change.
* docs(eas-cli): add breaking change(log) entry
* chore: update `engines.node` to 18 everywhere
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
We want to save the relationship between a job run and an update.
# How
See https://github.com/expo/universe/pull/15329.
# Test Plan
Tested with staging.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I noticed logs look off in CI when running `eas update --auto`.
<img width="1000" alt="Zrzut ekranu 2024-05-10 o 17 50 10" src="https://github.com/expo/eas-cli/assets/1151041/ed50d014-62f1-4342-bde2-0673f49d52b4">
# How
I pinpointed it to Ora being restarted on every log.
# Test Plan
Ran `CI=1 easd update --auto` and got ⬇️ which I think is much more readable.
```
CI=1 easd update --auto
- Exporting...
[expo-cli] Starting Metro Bundler
[expo-cli] Android Bundling complete 3492ms
[expo-cli] iOS Bundling complete 3493ms
[expo-cli] iOS Building Hermes bytecode for the bundle
[expo-cli] Android Building Hermes bytecode for the bundle
[expo-cli]
[expo-cli] Bundle Size
[expo-cli] ┌ index.ios.hbc 858 kB
[expo-cli] ├ index.android.hbc 864 kB
[expo-cli] ├ index.ios.hbc.map 3.45 MB
[expo-cli] └ index.android.hbc.map 3.48 MB
[expo-cli]
[expo-cli] 💡 JavaScript bundle sizes affect startup time. Learn more: https://expo.fyi/javascript-bundle-sizes
[expo-cli] Finished saving JS Bundles
[expo-cli] Dumping asset map
[expo-cli] Dumping source maps
[expo-cli] Preparing additional debugging files
[expo-cli] Export was successful. Your exported files can be found in dist
✔ Exported bundle(s)
- Uploading...
✔ Uploaded 2 app bundles
✔ Uploading assets skipped - no new assets found
ℹ 1 iOS asset, 1 Android asset (maximum: 20000 total per update). Learn more about asset limits: https://expo.fyi/eas-update-asset-limits
- Publishing...
✔ Published!
```
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Implementing @tchayen's suggestion.
# How
Changed wording
# Test Plan
None.
* [eas-cli] add eas onboarding flow
* mark command as hidden and prompt user before starting any action
* add gql queries
* regenerate gql schema
* fix type issues
* mark isCLIDone as true
* apply suggested changes
* improvements after cr
* more improvements
* [eas-cli] don't allow to specify custom global version of deprecated `expo-cli`
* update CHANGELOG.md
* update dependencies
* print a warning vs throwing an error
* mark as deprecated
* print warning nicer
* fix changelog entry
* fix changelog
* [eas-cli] don't prompt to set up push notifications if `promptToConfigurePushNotifications` is `undefined` and `expo-notifications` is not present
* update eas.schema.json
* update CHANGELOG.md
* [eas-cli] improve error message displayed when EAS CLI version doesn't satisfy minimal version required specified in `eas.json`
* fix typo
* update CHANGELOG.md
* [eas-cli] don't prompt user to set `android.package` and `ios.bundleIdentifier` value when runing in non-interactive mode
* update CHANGELOG.md
* rename test
* [ci] bump `@expo/eas-json` version in universe after the release
* Update .github/workflows/release.yml
* test
* edit eas.json
* Revert "edit eas.json"
This reverts commit 3979a1b1fb.
* Revert "test"
This reverts commit 69db39f548.
* [eas-cli] mark `default` image tag as deprecated
* add new image tags to `eas.schema.json`
* update CHANGELOG.md
* update CHANGELOG.md
* deprecate JDK 8 and NDK r19c images
* update CHANGELOG.md
* use better warn message for Xcode < 14 images and link to our changelog post
* update warn message
* don't deprecate Androdi images in this PR
* fix changelog
* use correct latest image
* [eas-cli] create new `init-build` command under the `credentials` topic
* get hacky version of cli command working
* add all option to flag
* extend the Manage<Platform> actions to reduce code duplication
* prompt user for platform if it doesn't exist
* prompt the user to choose a profile
* add a changelog entry
* call SetUpBuildCredentials for android
* [eas-cli] bump `@expo/apple-utils` to switch between `developer.apple.com` and `developer-mdn.apple.com` domains when one of them is not working
* update CHANGELOG.md
* bump version
* [eas-cli] send a path to custom build config to EAS Build server with posix separator for Windows
* add process.platform to if statement
* update CHANGELOG.md
* apply suggestions from cr
* remove unnecessary check
* apply suggested change
# Why
We want users to feel like they're adding something we support.
# How
Added `config` property to build profile level and platform-specific profile properties levels.
Also prettified the file according to my JSON Tools VS Code extension. Let me know if it should be deprettified.
# Test Plan
None.
* [fcmv1] Manage FCM V1 Google Service Account Key in CLI
# Why
NOTE: DO NOT LAND THIS UNTIL GRAPHQL CHANGES LAND IN WWW
We're adding support for FCM V1 credentials, as Google is shutting down
the FCM Legacy API for sending Android notifications in June.
# How
Add new prompts and refactor existing prompts to match this schematic:
# Test Plan
Verified all functionality e2e:
* update CHANGELOG.md
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
It is currently not possible to use `if: ${ always() }` in Custom Build workflows due to outdated `@expo/steps` dependency.
# How
Added a GitHub workflow, similar to the one we have in `turtle-v2`, which will automatically upgrade all dependencies from the `eas-build` repo.
# Test Plan
https://github.com/expo/eas-cli/pull/2220
* [ci] add update eas cli used on production for builds triggered with GitHub trigger once new version is published
* remove unnecessary docs from releasing
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Simplification, unification.
# How
Removed bare-specific template.
# Test Plan
None.
* test against node 20 and drop support for node 14
* update CHANGELOG.md
* update @types/node
* bump yarn version
* Revert "update @types/node"
This reverts commit 027e26b002.
* update @types/node
* try to debug
* Revert "try to debug"
This reverts commit 0d557d02f8.
* test sth
* update lock
* Revert "update lock"
This reverts commit 184b412655.
* Revert "test sth"
This reverts commit 77606cf5be.
* diff once again
* fix issues
* Revert "diff once again"
This reverts commit 526ab57453.
* Revert "[ENG-8956][eas-build] Improve EAS CLI tsconfig.json for local development (#1933)"
This reverts commit e963558ef6.
* add start-allow-unused option
* update CONTRIBUTING.md
* fix type error
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
x-ref https://github.com/expo/eas-build/pull/302
# How
Upgraded `@expo/eas-build-job` and fixed the only TS error.
# Test Plan
None.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
I've noticed tests ran for an old commit even though I pushed a new one.
# How
Added `concurrency` where I thought it was applicable.
# Test Plan
None.
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
It's nice to be able to download both application archive and "build artifact".
# How
Added `buildArtifactsUrl` to GraphQL query. It contains the thing I'm looking for.
# Test Plan
Ran `easd build:view 7bab0c66-d917-4873-9241-c5fa0b01dec1 --json` and confirmed it has the new field.
* [eas-cli] Add context fields for vcs clients
* [eas-cli] Replace vcs client helper with new context field
* [eas-cli] Pass instance of vcs client in helpers instead of re-calling vcs helper
* update CHANGELOG.md
* [FIX] Remove semver validation from node version read from .nvmrc
Node version can be specified as an alias (such as `iojs`, `lts/hydrogen` etc), so validating it as semver may cause errors for some users.
* update CHANGELOG.md
* fix(eas-cli): implement variadic `--platform` flag when creating EAS updates
* fix(eas-cli): finish todo and set minimum `@expo/[email protected]` version for multiple `--platform` flags during export
* update CHANGELOG.md
* fix(eas-cli): be verbose about `--platform=<flag>` in bundle script
* [eas-cli] handle server side defined error when `intel-medium` resource class is not available
* don't suggest using `intel-medium` in `eas.schema.json`
* update CHANGELOG.md
* update CHANGELOG.md
* [eas-cli] allow for `rollout` option when configuring submission
* update CHANGELOG.md
* add entry to `eas.schema.json`
* improve eas.schema.json
* make rollout default to 1 if not set
* Revert "make rollout default to 1 if not set"
This reverts commit 2ab689b02c.
* generate schema against staging
* update fragment
Changed noUnusedLocals and noUnusedParameters to false for easier local development and experimenting.
These checks do not run during local development. Instead, `yarn build` catches these cases on github.
Why
---
Fail fast with a clear message if the app config contradicts itself or the developer's behavior.
How
---
Throw if useClassicUpdates is set in the app config and the developer is running an EAS Update-related command or if the app config uses an EAS Update URL. If the developer is using a static app config (app.json), offer to modify the config file for them.
Test Plan
---
Added a unit test for ensureEASUpdateIsConfiguredAsync. Manually tested as wlel.
* added alias -m for --message
* align with the other messages
* updated README
* moving change in update/republish to a seperate PR
* removed README comment
* update CHANGELOG.md
---------
Co-authored-by: Steven Pu <[email protected]>
Co-authored-by: Steven Pu <[email protected]>
* added alias in republish
* reverted change in README
* update CHANGELOG.md
---------
Co-authored-by: Steven Pu <[email protected]>
Co-authored-by: Steven Pu <[email protected]>
* [eas-cli] validate that `expo-updates` are in project dependencies when somebody tries to run a build with channel set
* apply suggested changes
* remove unnecessary change
* fix warning
* improve validation logic
* improve insatlled message
* warn when expo-updates are in dev dependencies for update command
* impreve warn messsages
* improve warning messages
* one more warn message improvement
* update CHANGELOG.md
* [eas-cli][ENG-8763] Select default android keystore
- Add option to change default keystore from CLI (previously available only from dashboard)
- Streamline setting up new keystore
Instead of overwriting existing keystore, new one is created every time. Also, option to immediately set it as default is added, since it is also easier to change it from CLI.
* update CHANGELOG.md
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
# Why
Cleanup after https://github.com/expo/eas-build/pull/233.
# How
Upgraded `@expo/steps` package. It is the only `eas-build` package in here.
# Test Plan
It's a type-only change so CI success will be enough.
* [eas-cli] make large resource class only available for paid users
* update eas.schema.json
* Revert "update eas.schema.json"
This reverts commit 319d998b76a4c6c87d137174d6cf9f90d64b3886.
* apply suggested changes
* update CHANGELOG.md
* [eas-cli][bugfix] Fix ios version-test
Tests were passing, but were not testing the right thing, essentially always defaulting to 'managed' workflow. `projectDir` should be set to the same value as EAS_PROJECT_ROOT.
* [eas-cli][ENG-8571] Validate CFBundleShortVersionString
* update CHANGELOG.md
* [eas-cli][eas-json] add `large` resource class for iOS as allowed value in `eas.json`
* add deprecation warning for `m-large`
* add test
* update CHANGELOG.md
* [eas-cli] don't resolve default resource class for iOS based on metadata
* don't set m1-medium as default in `eas build:configure`
* pass sdkVersion and reactNativeVersion in buildParams
* convert it to sync function
* update gql schema
* update CHANGELOG.md
* [eas-cli] allow users to select app to run if multiple apps are found in the build tarball
* rename variable
* improve error message
* apply suggested changes
* add dot
* update CHANGELOG.md
* [eas-cli] throw error if somebody tries to run iOS with `large` resource class selected through deprecated `--resource-class` flag
* apply suggested changes
* improve error message
* update CHANGELOG.md
* [eas-cli] Update apple utilities to avoid the maintenance error
* [eas-cli] Add changelog entry
* [eas-cli] Dont change the eas-cli version
* [eas-cli] Fix changelog entry
* [eas-cli] fix it again
* Unify error display method
Overriden the `Command`'s `catch` method to catch all the errors thrown by the commands, log the error message there the same way as it was previously handled in `src/build/build.ts` and re-throw generic `Error` instance with predefined base error message.
To avoid duplication, old `Log.error()` calls have been removed from `src/build/build.ts`.
Also added tests to see if the `catch()` method works as intended.
* Adjust base error messages
Base error messages have been adjusted after @dsokal suggested that the error may be caused by something different from a request and displaying message about a failed request is misleading
* update CHANGELOG.md
* Add test for unclean error message
Checks if the `[GraphQL] ` prefix gets removed when logging the error message
* Update handling GraphQL errors
Post-review update to how graphQL errors are handled
* Print different message for graphQL errors
When a graphQL error is caught a different base error message is printed
* Print original error to debug
When a graphQL error is caught and the message is cleaned, an original message is printed to debug (or just the same message otherwise)
* Add custom error classes
Created some custom error classes for known server side defined errors
* Log the error, not the message
Changed the debug log to log the error object, not the error message
* Fix
Fixed testing leftover
* Change phrasing
Edited the phrasing in default messages related to EAS Build
* Update if condition
Changed the if condition after review comment
* Create error base class
Created a new base class for the errors expected in build.ts, so they can be handled separately in `catch()`
* Move EasCommand properties
Moved the class properties above the class methods
* Remove helper method
Removed the helper method after review comment
* Change const type
Updated the type of SERVER_SIDE_DEFINED_ERRORS constant
* Change default base error message
Set the default base error message to `<command_name> command failed.`
* Remove comments
Removed leftover comments
* Change optional property
Changed empty string to optional property
* Post-review tweaks
Self-explanatory
* Fix failing test
One of tests started failing after changing the coalescing operators (|| -> ??). This fixes that test
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Remove error class
Removed `GenericGraphQLError` class after @wkozyra95 comment, since atm there's no need to handle it differently than a generic `Error`
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Move `EasCommandError` base class
Moved `EasCommandError` base class after @wkozyra95 comment. The class is not specific to `Build` command and so it has been moved to `commandUtils` directory
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Make message mandatory
Made `message` parameter in `EasCommandError`s mandatory, to remove need for providing a fallback string and making the server the source of truth for the errors messages
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Update packages/eas-cli/src/commandUtils/EasCommand.ts
Co-authored-by: Wojciech Kozyra <[email protected]>
* Move `baseGraphQLErrorMessage` property
Made the property into a constant in a global scope, since atm it is not changed in any of the subclasses
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Suppress ESLint warning
ESLint erroneously complains about the constructor of `EasCommandError` to be useless, which is not true is the constructor of `Error` parent class allows for optional `message` parameter and the constructor of `EasCommandError` does not
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Add error handling tests
Added a bunch of new tests related to the `handleBuildRequestError` function
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
* Directly export `handleBuildRequestError`
Dropped the `testExports` convention after team discussion
See: https://linear.app/expo/issue/ENG-6945/improve-eas-cli-error-logging
---------
Co-authored-by: Wojciech Kozyra <[email protected]>
* [eas-cli] link to build phase in error message
* add better fallback
* use fallback for all links
* use terminalLink.isSupported
* improvements after code review
* use old fallback
* update CHANGELOG.md
* [eas-cli] display build message data when picking build in `submit`, `build:run` and `build:resign` commands
* display only 200 first characters of message if it exists
* print only defined values
* add '...' to message if trimmed
* use array instead of object
* update CHANGELOG.md
* [eas-cli] fix issue with `eas.json` envs not available when resolving local config
* fix type definitions to prevent it from happening again
* update CHANGELOG.md
* [eas-cli] set `m1-medium` resource class for builds which don't specify resource class for SDK 48 and RN 0.71
* refactor resolveBuildResourceClassAsync function
* apply suggested changes
* drop warning for ios large resource classes
* call getDynamicProjectConfigAsync in create context function
* update CHANGELOG.md
* Revert "Revert "[eas-cli] Add missing key information about updates in json outputs (#1611)""
This reverts commit d20db0fff4.
* [eas-cli] Fix missing update fragment in publish mutation
* [docs] Update changelog to reflect the revert and new entry
Why
---
This reverts commit e42031eaef. A customer reported an issue with publishing updates.
How
---
Ran `git revert` and then re-generated the GraphQL schemas due to merge conflicts using `yarn generate-graphql-code`.
Test Plan
---
Automated tests. Ran `easd update --auto` in a test project.
* [eas-cli][eas-json] handle new resource classes in EAS CLI
* show warning for large iOS resource classes
* don't deprecate resource class flag in this PR
* apply suggested improvements
* fix markdown description of top level resource class
* fix large resource class warning
* update CHANGELOG.md
* update eas.schema.json
* improve eas.schema.json
* add support for medium resource class and update eas.json
* fix error message for large resource classes
* temporary changes to solve issues with SSOUser being added to schema
* fix tests
* fix error message
* remove unnecessary dot
* update changelog
* [eas-cli] throw error when there are no emulator/simulator builds in `eas build:run` command
* handle missing build in correct place
* handle same error for latest flag
* add function to sanitize chosen build
* sanitize build selected by id
* improve build santization
* apply suggested improvements
* rename validation function
* update CHANGELOG.md
* [eas-cli] Use pagianted select prompt for eas build:run command
* apply suggestions from code review
* apply improvements from code review
* update CHANGELOG.md
* [eas-cli] Add test cases for republishing updates
* [eas-cli] Tweak the channel -> branch method errors to reuse in republish
* [eas-cli] Add support for --channel in update:republish
* [eas-cli] Add test cases to prevent using --group, --channel, or --branch together
* update CHANGELOG.md
* [eas-cli] Update the test case for resolving branch from channel
* [eas-cli] Add initial test cases for the update command
* [eas-cli] Add runtimeVersion option when mocking exports
* [eas-cli] Fix update flag validation for --branch and --channel
* [eas-cli] Add test case for --non-interactive, --channel, and --message
* update CHANGELOG.md
* [eas-cli] Fix linting issue
* [eas-cli] Reuse the input dir from the command
* [eas-cli] Explicitly mention the allowed flag combinations to avoid ambiguity
* [eas-cli] Move --auto to a distinct location in the error message
* [eas-cli] Fix linting issue
* Add --channel flag to eas update command
* use existing method
* adds undefined to return type
* move to getBranchNameFromChannelNameAsync.ts
* renames the function to singular "update"
* [eas-json] Make not recognized image error handler fire only if image is present under valid key with invalid value
* revert changes to error message
* update CHANGELOG.md
* fix(update): add code signing support to republish and block different branches
* refactor(update): move codesigning info into update fragment
* update CHANGELOG.md
* fix(update): add code signing support to republish and block different branches
* refactor(update): mark group and republish flags as deprecated
* refactor(update): drop republish and group flags
* refactor(update): drop republish flag from command
* refactor(update): remove last republish code from update command
* refactor(update): either use --group or --branch in deprecation warning
* refactor(update): drop old runtime version from update command
* refactor(update): move asset variables closer to populated area
* fix(update): fix republish typo in deprecation warning
* fix(update): correct a merge conflict error related to publish query changes
* refactor(update): split out republish to separate command
* fix(update): add code signing support to republish and block different branches
* test(update): add missing republish command tests
* test(update): add test case without codesigning
* refactor(update): move codesigning info into update fragment
* refactor(update): make branch and group exclusive and simplify code
* update CHANGELOG.md
* [eas-cli] add caching for `eas build:run`
* cache in tmp directory
* use path from `path` instead of `node:path`
* don't hide eas build:run command
* apply feedback from review
* improvements after code review
* update CHANGELOG.md
* [eas-cli] add build:run support for Android
* add assertions about android executables
* use spawnAsync instead of spawn
* minor refactor
* minor improvements to prompts
* improve download function name
* refactor code after the review
* apply suggestions from the review
* fix commit message formatting
* use progress tracker instead of progress bar
* improve formatting of build choices
* fix typo in function name
* requested improvements
* test using path.join for fast-lob
* fix windows glob issues
* fix glob on windows
* allow users to run ios builds only on apple device
* use path.join instead of interpolation
* address feedback
* auto select android for non mac users
* minor improvements
* improve error messages
* update CHANGELOG.md
* fix(update): only create a channel with branch name when branch is created
* refactor(update): rename branchIsCreated to createdBranch
* update CHANGELOG.md
* [eas-cli] change choice formatting when selecting build to submit
* fix typo
* use description with one line choice
* use eas update channel vs old release channel
* update CHANGELOG.md
* feat: support uploading web bundles
Expo Router defaults to shipping with universal Metro support (ios, android, web) which means eas update breaks by default if it asserts that web is not supported.
This PR also fixes the inability to upload single platforms.
* ensure platform filtering works
* Update publish.ts
* add tests
* update CHANGELOG.md
* style xits from PR feedback
* attempt to fix
* fix
* Update index.ts
* Update CHANGELOG.md
* Update publish-test.ts
* Update publish-test.ts
* refactor(update): auto configure EAS updates when running eas update
* fix(update): make sure eas update does what it needs to do
* refactor(update): drop obsolete eas update validation errors
* refactor(update): drop duplicate truncate update message
* refactor(update): drop duplicate install expo-update message
* fix(update): use the old truncated update message limit
* refactor(update): ensure the latest changes are integrated in the PR
* fix(update): use the EAS update configured expo config
* chore(update): make the EAS Update outage a bit more readable
* fix(update): remove _internal from merged manifest if defined
* fix(update): make sure people can run `eas update:configure` without project id
* update CHANGELOG.md
* refactor(update): skip setting the sdkVersion when configuring
* fix(update): only merge nested objects when configuring
* fix(update): refetch the config whenever projects are auto-setup
* refactor(update): simplify the config object merging
* refactor(update): change logging based on review input
Co-authored-by: Evan Bacon <[email protected]>
* refactor(update): drop fyi .md extension from logging
Co-authored-by: Evan Bacon <[email protected]>
* refactor(update): alawys reload the project config after ensuring eas updates
* fix(update): linting issue caused by logging changes
* refactor(update): drop unused exports from updates configure code
* refactor(update): split merge config to separate method for testing
* fix(update): show full install log when debugging is enabled
* fix(update): add back the missing <remove this key> instruction
Co-authored-by: Evan Bacon <[email protected]>
* refactor(update): remove default non-interactive value to rely on falsy values
Co-authored-by: Will Schurman <[email protected]>
* refactor(updates): make non interactive optional to rely on falsy values
* Revert "refactor(update): remove default non-interactive value to rely on falsy values"
This reverts commit 23ac36d36e35b7a87724229234d41dcac8cf02db.
* Revert "refactor(updates): make non interactive optional to rely on falsy values"
This reverts commit 94ae7cc039c94f28b74a5cfd9857f79e5a11e82c.
* refactor(update): move ensure methods outside the update command
* fix(update): add back log about channel pointing to branch
* refactor(branch): reuse query from shared utilsin `branch:create`
* refactor(channel): reuse query from shared utilsin `channel:create`
Co-authored-by: Will Schurman <[email protected]>
* [eas-cli] Add flag sanitization in updates command
* refactor(update): remove default non-interactive value to rely on falsy values
Co-authored-by: Will Schurman <[email protected]>
* refactor(updates): make non interactive optional to rely on falsy values
* Revert "refactor(update): remove default non-interactive value to rely on falsy values"
This reverts commit 23ac36d36e35b7a87724229234d41dcac8cf02db.
* Revert "refactor(updates): make non interactive optional to rely on falsy values"
This reverts commit 94ae7cc039c94f28b74a5cfd9857f79e5a11e82c.
Co-authored-by: Will Schurman <[email protected]>
* [eas-cli] Warn about outdated build deployment when configuring EAS Update
* update changelog with PR number
* print warning no matter what
* Update packages/eas-cli/src/commands/update/configure.ts
Co-authored-by: Will Schurman <[email protected]>
Co-authored-by: Will Schurman <[email protected]>
* create eas run command
* improve run command
* downaload and install iOS sim app
* add logic to select best avaliable simulator
* add not implemented android command
* use expo cli implementation of detecting if simulator is running
* support both archive and app paths in path argument
* better validate path argument
* refactor iOS code
* assert that Xcode and xcrun are installed
* rename ios and android run files
* assert simulator app is installed
* apply suggestions from code review
* improve select sim build prompt
* hide command
* minor fixes
* apply improvements suggested in code review
* update CHANGELOG.md
* refactor: update ajv, add human errors, and prepare lint command
* feature: add custom validation rules
* refactor: allow metadata context to be created without auth state
* refactor: update validation errors with new custom issues
* refactor: update existing code to use new features
* feature: add custom apple validation rules
* feature: implement validation command with json option
* chore: clean up outdated files
* refactor: update config schema type to improve human error message
* [eas-cli] Fix typo in ajv version
* [eas-cli] Use built-in context API to get project dir
* [eas-cli] Remove commented code
* [eas-cli] Load project without enforcing project id in metadata:lint
* [eas-cli] Guard against faulty config objects
* update CHANGELOG.md
* docs(cli): fix keyword length typo
* refactor(cli): use optional chaining over ternary
Co-authored-by: Dominik Sokal <[email protected]>
* refactor(cli): drop non-null assertion in config resolver
* refactor(cli): drop implicit coercion in expressions
Co-authored-by: Dominik Sokal <[email protected]>
* refactor(cli): only initialize ajv when used
* refactor(cli): simplify error logging
* refactor(cli): move coascle to expodash as filter
* fix(cli): use proper empty check on readable errors
* refactor(cli): support non interactive in metadata lint
* refactor(cli): remove metadata context from lint command
* refactor(cli): split up metadata context into different methods
* refactor(cli): use profile instead of metadata path in config resolve methods
* refactor(cli): rename context to auth and simplify usage
* refactor(cli): move json schema files to top-level imports
* refactor(cli): use predicates in expodash filter instead of filter functions
* test(cli): update config tests to use mocked profile isntead
* test(cli): fix issue in filter predicate test
* [eas-cli] Reimplement the analytics manager
Co-authored-by: Dominik Sokal <[email protected]>
* [eas-cli] Replace secret:list table with format fields
* update CHANGELOG.md
* [eas-cli] Replace created at with update in secrets list
Co-authored-by: Dominik Sokal <[email protected]>
* Revert updated at
Co-authored-by: Dominik Sokal <[email protected]>
* [eas-cli] use env variable to select M1 resource class
* [eas-cli] create `m1-experimental` option for `--resource-class` flag
* improvements after code review
* throw an error instead of using oclif/errors in resolveResourceClass function
* update CHANGELOG.md
* [eas-cli] provide suggestions for developers when archive size is large
* use learn more function
* apply suggestion from review
* apply suggestions from code review
* update CHANGELOG.md
* [eas-cli] add `-e` flag as a shortcut for `--profile` flag
* revert readme changes
* add description for profile flag on config command
* update CHANGELOG.md
* [eas-cli] warn users about EAS Build outages
* [eas-cli] warn users about EAS Submit outages
* [eas-cli] show warnings about EAS outages as a first thing when running build and submit commands
* [eas-cli] don't return null as a result of StatuspageServiceQuery
* [eas-cli] remove unneccessary if check
* [eas-cli] rename warnAboutEasOutagesAsync function to maybeWarnAboutEasOutagesAsync and remove please word from output
* [eas-cli] warn about outages when running `eas update` command
* [eas-cli] improve outage warning communicate
* [eas-cli] move maybeWarnAboutEasOutagesAsync call after flags and project dir validation
* [eas-cli] minor refactor after code review
* [eas-cli] change warning message on EAS outage
* [eas-cli] put platform selection and validation logic into ensurePlatformSelectedAsync function
* update CHANGELOG.md
* [eas-cli] use ensurePlatformSelectedAsync in submit command
* [eas-json] support `autoIncrement` at root of build profile
* [eas-json] Start `autoIncrement` markdown enum description with capital letter
* update CHANGELOG.md
* [eas-json] use interfaces instead of types
* [eas-json] fix issues with types and improve schema descriptions
* [eas-json] remove unneccessary comment
* [eas-json] make EasJsonBuildProfile interface again
* [eas-json] remove unneccessary semicolon
* [eas-json] use only boolean values for autoIncrement flag
* [eas-json] improve schema description for autoIncrement option
* [eas-json] remove change from changelog
* update CHANGELOG.md
* improve changelog entry
* [eas-cli] Swallow error when unable to track file in no commit workflow
* Include a warning when failing to track a file with GitNoCommitClient
* update CHANGELOG.md
* [eas-cli] Add version selector to store config for metadata
* [eas-cli] Add version snippet to emphasize on app version
* [eas-cli] Add the missing phased release nock endpoints
* fix: make sure we add a line when needed while runing commands
* chore: add instruction on how to upgrade + remove ending new line
* chore: don't make the * bold
* [eas-cli] Improve EAS metadata category configuration
* [eas-cli] Update category types for apple store configuration
* [eas-cli] Add tests for the behavior of the categories from store configuration
* [eas-cli] Update apple store config with new categories
* [eas-cli] Simplify parent vs normal categories in schema
* [eas-cli] Fix serialization issue with empty secondary sub category
* [eas-cli] Relax the apple category types to allow strings
* [eas-cli] Fix an issue in reader related to the category types
* [eas-cli] Add comments about string vs category enum
* update CHANGELOG.md
* [eas-cli] Avoid setting automaticRelease for manual releases in config
* [eas-cli] Use same default app name as schema
* [eas-cli] Prefer releaseNotes over whatsNew in apple info
* [eas-cli] Drop deprecated gamblingAndContest from schema
* [eas-cli] Use better defaults for advisory
* [eas-cli] Remove type from enum as its not required by spec
* [eas-cli] Remove $ref and description workaround for draft 6
* [eas-cli] Update kids age rating description
* [eas-cli] Remove default app title
* update CHANGELOG.md
* [1/1] Support build-resource-class flag in eas-cli
# Why
We want to add a flag to allow users to specify resource-class when they
run `eas build`. The flag is experimental for now, and we haven't
decided exactly how we'll incorporate the resource classes into plan
pricing. But this PR doesn't deal with that - it just makes the
necessary changes to eas-cli to support specifying a resource class when
running `eas build`.
# How
Add a new enum for BuildResourceClass that matches the enum created
for GraphQL in universe/server/www. Then create a new flag
`build-resource-class` whose options are the values of the
BuildResourceClass enum. Then add some validation to prevent resource
classes being used for incompatible platforms (e.g. prevent `-p ios
--build-resource-class=ANDROID_LARGE`). Finally, pass along the flag
value to the call to the WWW graphql mutations for BuildAndroid and
BuildiOS.
# Test Plan
```
yarn test
```
See test plan on this PR for more thorough e2e testing summary:
https://github.com/expo/universe/pull/9800
* Update packages/eas-cli/src/commands/build/index.ts
Co-authored-by: Dominik Sokal <[email protected]>
* Apply suggestions from code review
Co-authored-by: Dominik Sokal <[email protected]>
* Address PR comments
* Regenerate graphql from staging
* update CHANGELOG.md
Co-authored-by: Dominik Sokal <[email protected]>
* [eas-cli] Add metadata commands
* Add myself as codeowner to the metadata
* [eas-cli] Hide the metadata commands for now
* Add metadata changelog entry
* [eas-cli] Update metadata configure command description
* [eas-cli] Drop non-interactive due to limitations in AppStoreApi
* [eas-cli] Reimplement credentials context for metadata
* [eas-cli] Drop non-interactive flag in metadata command
* [eas-cli] Drop args from metadata:configure
Co-authored-by: Wojciech Kozyra <[email protected]>
* [eas-cli] Add retroactive code review changes (#1147)
* [eas-cli] Add public access modifiers to classes
* [eas-cli] Add specific types to date precision remover
* [eas-cli] Add try catch around writing json to always unsubscribe
* [eas-cli] Add async return await to uploadAsync log methods
* [eas-cli] Fix date precision type and test
* [eas-cli] Use submission profile bundle id if defined
* [eas-cli] Drop catch from IO try catch block
* [eas-cli] Move unique helper to global utils
* [eas-cli] Prefer nullish coalescing
* [eas-cli] Move metadata commands to pull and push
* [eas-cli] Drop the platform option from the push command
* [eas-cli] Remove alias and reword descriptions
* [eas-cli] Auto-configure eas.json with metadata when missing (#1156)
* [eas-cli] Polish the command output for release (#1159)
* [eas-cli] Finalize metadata logging output
* [eas-cli] Fix logging validation errors when store.config.json is not found
* [eas-cli] Make all localized entites bold
* [eas-cli] Make version string visible in logs
* [eas-cli] Add note about early beta
* [eas-cli] Remove hidden from meta commands
* [eas-cli] Add metadata topic
* [eas-cli] Rename eas metadata to eas metadata:push in logging
* [eas-cli] Remove unused arg flag from push
Co-authored-by: Wojciech Kozyra <[email protected]>
- add additional information to publish command output such as update ids and website links
- https://linear.app/expo/issue/ENG-4589/improve-publish-command
- add additional context to uploadAssetsAsync return type
- add real-time text to upload spinner showing upload progress
- remove ) from website link on unsupported terminals
* [eas-cli] lower page limit for UpdateQueries
- lower page limit from 10_000 to 300 to avoid timeouts on branches with many updates.
we do not fetch the full history of updates anymore for `--republish`, etc.
* [eas-cli] Add metadata context based on submission contexts
* [eas-json] Add submission meta property to config
* [eas-cli] Make exp optional in the metdata context
* [eas-cli] Fix misleading docblock on metadata context
* [eas-cli] Fix pass through exp config in metadata context
* [eas-cli] Import ios submission profile type through entrypoint
* [eas-cli] Rename metadata file to filename in context
* [eas-cli] Move credential context outside metadata context
* [eas-cli] Rename meta to metadataPath in profile config
* [eas-cli] Drop nonInteractive from metadata because of AppStoreApi limitations
* [eas-cli] Use singular store in bundle identifier doc
* update graphql
* show queue position progress + estimated wait time
* refactor
* update CHANGELOG.md
* hide estimated wait time when build is in progress
* add priority queue info
* chore: add annotations about functions that do not support App Store Connect API
* Update CHANGELOG.md
* Update CHANGELOG.md
* Update capabilityIdentifiers.ts
* ask user to select profile if release does not exist
* Apply suggestions from code review
Co-authored-by: Wojciech Kozyra <[email protected]>
* update CHANGELOG.md
Co-authored-by: Wojciech Kozyra <[email protected]>
* docs: fix broken links to all command source files in readme
They pointed to .js, but they're all .ts
* docs: fix command paths by adding typescript devdependency
* fix: add typescript devDependency to eas-json for consistency
Co-authored-by: Dominik Sokal <[email protected]>
* Revert "fix working with local api server (#747)"
Why
---
Make local development behave more closely to production and use the same API route paths. I made 127.0.0.1 behave the same way as api.expo.test and localhost. Another fix would have been to change 127.0.0.1 to localhost in EAS CLI, but it's a good idea to make the API server treat localhost and 127.0.0.1 similarly (look up PR 8542).
How
---
This reverts commit 5ba3cc6623.
Test Plan
---------
Started the API server locally, then started EAS CLI locally with `EXPO_LOCAL=1 yarn eas login`. Logged in with my staging credentials and saw the API server locally pring out that it had made new database connections in the log.
* update CHANGELOG.md
* update CHANGELOG.md
description:'You want to report a reproducible bug or regression in EAS CLI.'
body:
- type:markdown
@@ -14,6 +14,11 @@ body:
- type:markdown
attributes:
value:If you leave out sections there is a high likelihood your issue will be closed. If you have a question, not a bug report, please post it on our [forums](https://forums.expo.dev/) instead.
- type:input
attributes:
label:Build/Submit details page URL
description:If you're reporting an issue with EAS Build and/or EAS Submit, please provide the URL to the details page URL. The page can be only viewed by the Expo team members. Providing the URL is optional but it makes debugging the issue easier.
description:Describe the issue in 1 or 2 sentences
placeholder:Clearly describe what the expected behavior is vs. what is actually happening. This should be as short as possible, while still communicating all the necessary information. If your summary is just 'X library/method isn't working', then you need to continue debugging yourself and provide more information.
- type:input
validations:
required:true
attributes:
label:Managed or bare?
description:Is your project managed or bare? Bare - Android and/or iOS native projects exist in your repo; Managed - you don't have native code (custom or 3rd party) in your project. See the [Workflows](https://docs.expo.dev/introduction/managed-vs-bare/) page for more information.
- type:textarea
validations:
required:true
attributes:
label:Environment
placeholder:Run `eas diagnostics` and paste the output here
description:Run `npx expo-env-info` and `npx expo-doctor`, and paste the output here.
<!-- Thanks for contributing to _EAS CLI_! Before you submit your pull request, please make sure to check the following boxes by putting an x in the [ ] (don't: [x ], [ x], do: [x]) -->
# Checklist
- [ ] I've added an entry to [CHANGELOG.md](https://github.com/expo/eas-cli/blob/main/CHANGELOG.md#main) if necessary. You can comment this pull request with `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]` and CHANGELOG.md will be updated automatically.
- [ ] I've tagged the changelog entry with `[EAS BUILD API]` if it's a part of a breaking change to EAS Build API (only possible when updating `@expo/eas-build-job` package).
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->
message:${{ contains(github.event.pull_request.labels.*.name, 'no changelog') && '⏩ The changelog entry check has been skipped since the "no changelog" label is present.' || '✅ Thank you for adding the changelog entry!' }}
message-failure:|
❌ It looks like a changelog entry is missing for this PR. Add it manually to CHANGELOG.md.
⏩ If this PR doesn't require a changelog entry, such as if it's an internal change that doesn't affect the user experience, you can add the "no changelog" label to the PR.
if:"${{ contains(github.event.label.name, 'incomplete issue: missing or invalid repro') }}"
steps:
- uses:actions/github-script@v3
with:
github-token:${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script:|
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Hi there! It looks like your issue requires a minimal reproducible example, but it is invalid or absent. Please prepare such an example and share it in a new issue.
**The best way to get attention to your issue is to provide a clean and easy way for a developer to reproduce the issue on their own machine.** Please do not provide your entire project, or a project with more code than is necessary to reproduce the issue.
A side benefit of going through the process of narrowing down the minimal amount of code needed to reproduce the issue is that you may get lucky and discover that the bug is due to a mistake in your application code that you can quickly fix on your own.
### Resources
- ["How to create a Minimal, Reproducible Example"](https://stackoverflow.com/help/minimal-reproducible-example)
- ["How to narrow down the source of an error"](https://expo.fyi/manual-debugging)
### Common concerns
#### "I've only been able to reproduce it in private, proprietary code"
You may not have spent enough time narrowing down the root cause of the issue. Try out the techniques discussed in this [manual debugging guide](https://expo.fyi/manual-debugging) to learn how to isolate the problem from the rest of your codebase.
#### "I didn't have time to create one"
That's understandable, it can take some time to prepare. We ask that you hold off on filing an issue until you are able to fully complete the required fields in the issue template.
#### "You can reproduce it by yourself by creating a project and following these steps"
This is useful knowledge, but it's still valuable to have the resulting project that is produced from running the steps, where you have verified you can reproduce the issue.
body: `Hello! There isn't enough information provided in your issue description for us to be able to help you. The best way to get help is to provide information to enable other developers to understand the issue and reproduce it on their own machines.
Please create a new issue and fill out the entire issue template to the best of your ability. Refer to the following resources for more information on how to create a good issue report.
### Resources
- ["How do I ask a good question?"](https://stackoverflow.com/help/how-to-ask)
- ["How to create a Minimal, Reproducible Example"](https://stackoverflow.com/help/minimal-reproducible-example)
- ["How to narrow down the source of an error"](https://expo.fyi/manual-debugging)
`})
github.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed'
})
issue-accepted:
runs-on:ubuntu-20.04
if:github.event.label.name == 'issue accepted'
steps:
- uses:actions/github-script@v3
with:
github-token:${{ secrets.EXPO_BOT_GITHUB_TOKEN }}
script:|
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Thank you for filing this issue!
This comment acknowledges we believe this may be a bug and there’s enough information to investigate it.
However, we can’t promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If you’d like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.
body: `Hello! Our GitHub issues are reserved for bug reports.
If you have a question about Expo or related tools, please post on our forums at https://forums.expo.dev/ or join our Discord at https://chat.expo.dev/.
### Resources
- ["How do I ask a good question?"](https://stackoverflow.com/help/how-to-ask)
- ["Join the community"](https://docs.expo.dev/next-steps/community/)
stale-issue-message:"This issue is stale because it has been open for 30 days with no activity. If there is no activity in the next 7 days, the issue will be closed."
close-issue-message:"This issue was closed because it has been inactive for 7 days since being marked as stale. Please open a new issue if you believe you are encountering a related problem."
Phases can be marked as skipped, warning, or failed for granular reporting.
### Context Objects
- **BuildContext** (`build-tools`): For traditional builds, wraps Job, manages phases/artifacts/caching
- **CustomBuildContext** (`build-tools`): Implements `ExternalBuildContextProvider`, bridges BuildContext to steps framework, used in custom builds and generic jobs
- **BuildStepGlobalContext** (`steps`): Manages step outputs, interpolation, shared state
- **BuildStepContext** (`steps`): Per-step context with working directory and logger
cd packages/eas-cli && yarn test <path-to-test-file>
# Example:
cd packages/eas-cli && yarn test src/project/__tests__/projectUtils-test.ts
```
## Common Development Scenarios
### Adding a Built-in Step Function
1. Create file in `packages/build-tools/src/steps/functions/yourFunction.ts`
2. Export `createYourFunctionBuildFunction()` following existing patterns
3. Add to `getEasFunctions()` in `packages/build-tools/src/steps/functions/easFunctions.ts`
4. Function receives `BuildStepContext` and input/output maps
### Adding Error Detection
1. Add pattern detection in `packages/build-tools/src/buildErrors/detectError.ts`
2. Implement resolver for better error messages
3. Helps users understand and fix build failures
### Working with Platform-Specific Builders
- **Android builder** (`packages/build-tools/src/builders/android.ts`): Gradle-based, handles APK/AAB generation, also see `functionGroups/build.ts`
- **iOS builder** (`packages/build-tools/src/builders/ios.ts`): Fastlane/Xcode-based, handles IPA generation, also see `functionGroups/build.ts`
- Both use `runBuilderWithHooksAsync()` which runs build result hooks (on-success, on-error, on-complete) from package.json
### Introducing Breaking Changes to Job API (@expo/eas-build-job)
If you want to introduce breaking changes to the `@expo/eas-build-job` package, contact one of the CODEOWNERS to coordinate changes with EAS build servers and GraphQL API. Describe what changes you want to make and why. After everything is deployed to production, you can introduce a PR that relies on the new implementation.
## Environment Variables
```bash
# API Configuration
exportEXPO_STAGING=1# Use staging API (https://staging-api.expo.dev)
exportEXPO_LOCAL=1# Use local API (http://127.0.0.1:3000)
# Development
exportEAS_NO_VCS=1# Disable version control checks
exportEXPO_DEBUG=1# Enable debug logging
```
## Code Style & Conventions
### Validation
All changes should be validated before committing. At minimum run package-level tests (e.g. `jest-unit`)
for touched code, then run type checks/linting and format the repo:
```bash
yarn fmt # Apply Oxfmt formatting
yarn typecheck # Validate TypeScript types
yarn lint # Run Oxlint
yarn fmt:check # Run Oxfmt format check
```
### Logging
Use the `Log` module from `@expo/logger`:
```typescript
import{Log}from'@expo/logger';
Log.log('Info message');
Log.warn('Warning message');
Log.error('Error message');
```
### Pull Request conventions
When creating pull requests, make sure to adhere to [PULL_REQUEST_TEMPLATE](./.github/PULL_REQUEST_TEMPLATE).
### Commit Messages
- When possible, prepend commit messages with `[PACKAGE-BEING-CHANGED]`, e.g. `[steps] Add new step function`
- Do not use prefixes like `chore:` and `feat:`
- Commit messages should be concise. Only complex changes should be longer than one line
- Commit changes in logical groups
## Release Process
1. Update `CHANGELOG.md` in the appropriate package
1. Run `yarn release` in the repository root folder.
2. Wait, the `release` workflow on GitHub Actions is going to take care of the rest (including publishing packages to npm and updating the changelog).
3. Check the changelog. If any of the entries have been tagged with `[EAS BUILD API]`
- Open `package.json` and note the version of `@expo/eas-build-job` used in the eas-cli.
- Find the `Publish` commit in [expo/eas-build](https://github.com/expo/eas-build/commits) for that version. In most cases, it will be the latest `Publish` commit.
- Find the `eas-cli-local-build-plugin` version published in that commit.
- Run `npm dist-tags add eas-cli-local-build-plugin@VERSION latest` with the version from the previous step.
## Getting Started
If this is your first time running `eas-cli` locally, make sure you install and build the packages. In the project root, run:
```sh
yarn install
yarn build
```
From there, set up an alias for the EAS CLI so you can try it in projects all around your computer. The project is compiled on the fly so you don't need to run a build (watch) command.
> The only exception is if there have been changes in `packages/eas-json`. In that case, you'll have to run `yarn build` in the root.
Open your `.zshrc` or other config file and add:
```sh
aliaseasd="/PATH/TO/eas-cli/bin/run"
```
Then use it with `easd` like `easd build`.
If you're making changes to `packages/eas-json` or prefer/need to work with production code, start the build command in watch mode with:
```sh
yarn start
```
If it is easier for you to work with the code locally with compiler options set to:
```json
...
"compilerOptions":{
...
"noUnusedLocals":false,
"noUnusedParameters":false,
...
}
...
```
you can consider using:
```sh
yarn start-allow-unused
```
## Format
- Be sure to update the [`CHANGELOG.md`](./CHANGELOG.md) with changes for every PR. There is a changelog bot that can generate the proper entry for you. The instructions on how to use it are in the PR description placeholder.
- End `async` functions with `Async` like `runAsync`. This is just how we format functions at Expo.
- Utilize the unified `Log` module instead of `console.log`.
## Using local and staging API
For development against local API:
- Set up the API server as described at https://github.com/expo/universe/tree/main/server/www.
- Set the `EXPO_LOCAL=1` env variable either on every command run (e.g. `EXPO_LOCAL=1 easd ...`) or more permamently with `export EXPO_LOCAL=1` (works in a current shell session).
For development against staging API:
- Set the `EXPO_STAGING=1` env variable either on every command run (e.g. `EXPO_STAGING=1 easd ...`) or more permamently with `export EXPO_STAGING=1` (works in a current shell session).
## Working on local builds (`eas build --local`)
See [`CLAUDE.md`](./CLAUDE.md) for how to set up your environment when making changes to [`eas-cli-local-build-plugin`](./packages/local-build-plugin) and/or [`build-tools`](./packages/build-tools).
## Testing
From the repository root, run `yarn run -T lerna run test`. For a single package, run `yarn test` in that package directory.
1. Invoke the GitHub workflow ["Manually trigger a release"](https://github.com/expo/eas-cli/actions/workflows/trigger-release.yml). The next version is chosen automatically based on the changelog entries. If you want to use different version, pass the version string as an input to the workflow, in semver format, e.g. "1.2.3"
2. That's it! GitHub Actions is going to take care of the rest. Watch the #eas-cli Slack channel for a successful release notification.
## Choosing the next version
As stated above, the next EAS CLI version is chosen automatically based on the existing changelog entries under the unreleased section in **CHANGELOG.md**.
The algorithm works as follows:
- If there are any entries in the "🛠 Breaking changes" section, bump the MAJOR version.
- Otherwise, if there are any entries in the "🎉 New features", bump the MINOR version.
`@expo/build-tools` is the core library for the EAS Build service. It implements the build process for React Native projects and for managed Expo applications.
it('detects log for corrupted npm package',async()=>{
constfakeError=newError();
consterr=awaitresolveBuildPhaseErrorAsync(
fakeError,
[
'[stderr] WARN tarball tarball data for @typescript-eslint/[email protected] (sha512-cozo/GbwixVR0sgfHItz3t1yXu521yn71Wj6PlYCFA3WPhy51CUPkifFKfBis91bDclGmAY45hhaAXVjdn4new==) seems to be corrupted. Trying again.',
it('detects log for invalid bundler and reports it to user',async()=>{
constfakeError=newError();
consterr=awaitresolveBuildPhaseErrorAsync(
fakeError,
[
"/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/dependency.rb:313:in `to_specs': Could not find 'bundler' (2.2.3) required by your /Users/expo/project/build/ios/Gemfile.lock. (Gem::MissingSpecVersionError)",
'Your project requires a different version of the Ruby "bundler" program than the version installed in this EAS Build environment. You can specify which version of "bundler" to install by specifying the version under "build"→[buildProfileName]→"ios"→"bundler" in eas.json.'
);
expect(err.trackingCode).toBeUndefined();
expect(err.metadata).toBeUndefined();
});
it('does not detect errors if they show up in different build phase',async()=>{
constfakeError=newError();
consterr=awaitresolveBuildPhaseErrorAsync(
fakeError,
[
"/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/dependency.rb:313:in `to_specs': Could not find 'bundler' (2.2.3) required by your /Users/expo/project/build/ios/Gemfile.lock. (Gem::MissingSpecVersionError)",
],
{
job:{platform: Platform.IOS}asJob,
phase: BuildPhase.INSTALL_DEPENDENCIES,// it should be in RUN_FASTLANE
'CocoaPods could not find compatible versions for pod "react-native-google-maps":16 In Podfile:17 react-native-google-maps (from `/Users/expo/workingdir/build/node_modules/react-native-maps`)18Specs satisfying the `react-native-google-maps (from `/Users/expo/workingdir/build/node_modules/react-native-maps`)` dependency were found, but they required a higher minimum deployment target.19Error: Compatible versions of some pods could not be resolved.',
MkDir /Users/expo/workingdir/build/packages/apps/NFLNetwork/ios/build/Build/Products/Release-iphonesimulator/expo-dev-menu/EXDevMenu.bundle (in target 'expo-dev-menu-EXDevMenu' from project 'Pods')
cd /Users/expo/workingdir/build/packages/apps/NFLNetwork/ios/Pods
MkDir /Users/expo/workingdir/build/packages/apps/NFLNetwork/ios/build/Build/Products/Release-iphonesimulator/expo-dev-launcher/EXDevLauncher.bundle (in target 'expo-dev-launcher-EXDevLauncher' from project 'Pods')
cd /Users/expo/workingdir/build/packages/apps/NFLNetwork/ios/Pods
/Users/expo/workingdir/build/packages/video/ios/Vendor/dependency/ProgrammaticAccessLibrary.xcframework:1:1: error: The signature of “ProgrammaticAccessLibrary.xcframework” cannot be verified.
note: A sealed resource is missing or invalid
note: /Users/expo/workingdir/build/packages/video/ios/Vendor/dependency/ProgrammaticAccessLibrary.xcframework: a sealed resource is missing or invalid
.toBe(`The "Run fastlane" step failed because of an error in the Xcode build process. We automatically detected following errors in your Xcode build logs:
- The signature of “ProgrammaticAccessLibrary.xcframework” cannot be verified.
- Some other error
- The last one
Refer to "Xcode Logs" below for additional, more detailed logs.`);
/Users/expo/workingdir/build/managed/ios/Pods/Pods.xcodeproj: error: Signing for "EXConstants-EXConstants" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'EXConstants-EXConstants' from project 'Pods')
// CDN: trunk URL couldn't be downloaded: https://cdn.jsdelivr.net/cocoa/Specs/2/a/e/MultiplatformBleAdapter/0.0.3/MultiplatformBleAdapter.podspec.json Response: 429 429: Too Many Requests
regexp:/CDN: trunk URL couldn't be downloaded.* Response: 429 429: Too Many Requests/,
createError:()=>
newTrackedBuildError('COCOAPODS_TO_MANY_REQUEST','cocoapods: too many requests'),
},
{
phase: BuildPhase.INSTALL_DEPENDENCIES,
// Host key verification failed.
// fatal: Could not read from remote repository.
regexp:/Host key verification failed\.\nfatal: Could not read from remote repository/,
// Input is required, but Expo CLI is in non-interactive mode
// or
// CommandError: Input is required, but 'npx expo' is in non-interactive mode.
regexp:/Input is required, but .* is in non-interactive mode/,
createError:()=>
newTrackedBuildError(
'EXPO_CLI_INPUT_REQUIRED_ERROR',
`expo-cli: Input required in non-interactive mode.`
),
},
{
platform: Platform.IOS,
phase: BuildPhase.PREBUILD,
// [03:03:05] [ios.infoPlist]: withIosInfoPlistBaseMod: GoogleService-Info.plist is empty
regexp:/withIosInfoPlistBaseMod: GoogleService-Info\.plist is empty/,
createError:()=>
newTrackedBuildError(
'EXPO_CLI_EMPTY_GOOGLE_SERVICES_PLIST_ERROR',
`expo-cli: Empty GoogleService-Info.plist.`
),
},
{
platform: Platform.IOS,
phase: BuildPhase.PREBUILD,
// [01:52:04] [ios.xcodeproj]: withIosXcodeprojBaseMod: Path to GoogleService-Info.plist is not defined. Please specify the `expo.ios.googleServicesFile` field in app.json.
regexp:/withIosXcodeprojBaseMod: Path to GoogleService-Info\.plist is not defined/,
`expo-cli: Path to GoogleService-Info.plist is not defined.`
),
},
{
phase: BuildPhase.PREBUILD,
// Error: [android.dangerous]: withAndroidDangerousBaseMod: ENOENT: no such file or directory, open './assets/adaptive-icon.png'
// at Object.openSync (node:fs:585:3)
// at readFileSync (node:fs:453:35)
// at calculateHash (/home/expo/workingdir/build/node_modules/@expo/image-utils/build/Cache.js:14:91)
// at createCacheKey (/home/expo/workingdir/build/node_modules/@expo/image-utils/build/Cache.js:19:18)
// at Object.createCacheKeyWithDirectoryAsync (/home/expo/workingdir/build/node_modules/@expo/image-utils/build/Cache.js:24:33)
// at generateImageAsync (/home/expo/workingdir/build/node_modules/@expo/image-utils/build/Image.js:151:34)
// at async generateIconAsync (/home/expo/workingdir/build/node_modules/@expo/prebuild-config/build/plugins/icons/withAndroidIcons.js:369:11)
// at async /home/expo/workingdir/build/node_modules/@expo/prebuild-config/build/plugins/icons/withAndroidIcons.js:310:21
// at async Promise.all (index 0)
// at async generateMultiLayerImageAsync (/home/expo/workingdir/build/node_modules/@expo/prebuild-config/build/plugins/icons/withAndroidIcons.js:306:3)
// or
// Error: [ios.dangerous]: withIosDangerousBaseMod: ENOENT: no such file or directory, open './assets/images/app_icon_staging.png'
// at Object.openSync (fs.js:497:3)
// at readFileSync (fs.js:393:35)
// at calculateHash (/Users/expo/workingdir/build/node_modules/@expo/image-utils/build/Cache.js:14:91)
// at createCacheKey (/Users/expo/workingdir/build/node_modules/@expo/image-utils/build/Cache.js:19:18)
// at Object.createCacheKeyWithDirectoryAsync (/Users/expo/workingdir/build/node_modules/@expo/image-utils/build/Cache.js:24:33)
// at generateImageAsync (/Users/expo/workingdir/build/node_modules/@expo/image-utils/build/Image.js:151:34)
// at async setIconsAsync (/Users/expo/workingdir/build/node_modules/@expo/prebuild-config/build/plugins/icons/withIosIcons.js:169:15)
// at async /Users/expo/workingdir/build/node_modules/@expo/prebuild-config/build/plugins/icons/withIosIcons.js:71:5
// at async action (/Users/expo/workingdir/build/node_modules/@expo/config-plugins/build/plugins/withMod.js:235:23)
// at async interceptingMod (/Users/expo/workingdir/build/node_modules/@expo/config-plugins/build/plugins/withMod.js:126:21)
regexp:
/ENOENT: no such file or directory[\s\S]*prebuild-config\/build\/plugins\/icons\/with(Android|Ios)Icons\.js/,
// Cannot determine which native SDK version your project uses because the module `expo` is not installed. Please install it with `yarn add expo` and try again.
regexp:
/Cannot determine which native SDK version your project uses because the module `expo` is not installed/,
// The Swift pod `FirebaseCoreInternal` depends upon `GoogleUtilities`, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static
regexp:/The Swift pod .* depends upon .* which does not define modules/,
createError:()=>
newTrackedBuildError(
'SWIFT_POD_INCOMPATIBLE_DEPENDENCY',
'pod: Swift pod depends on a pod that does not define modules.'
),
},
{
platform: Platform.IOS,
phase: BuildPhase.INSTALL_PODS,
// Adding spec repo `24-repository-cocoapods-proxy` with CDN `http://10.254.24.7:8081/repository/cocoapods-proxy/`
// [!] No podspec exists at path `/Users/expo/.cocoapods/repos/24-repository-cocoapods-proxy/Specs/1/9/2/libwebp/1.2.0/libwebp.podspec.json`.
regexp:/Adding spec repo .* with CDN .*\n\s*\[!\] No podspec exists at path `(.*)`/,
// Some pods are hosted on git registries that are not supported e.g. chromium.googlesource.com
createError:(match: RegExpMatchArray)=>
newTrackedBuildError(
'COCOAPODS_CACHE_INCOMPATIBLE_REPO_ERROR',
`cocoapods: Missing podspec ${match[1]}.`
),
},
{
platform: Platform.IOS,
phase: BuildPhase.INSTALL_PODS,
// [!] Invalid `Podfile` file: 783: unexpected token at 'info Run CLI with --verbose flag for more details.
regexp:
/\[!\] Invalid `Podfile` file: .* unexpected token at 'info Run CLI with --verbose flag for more details./,
createError:()=>
newTrackedBuildError('NODE_ENV_PRODUCTION_DEFINED','npm: NODE_ENV=production was defined.'),
// [stderr] WARN tarball tarball data for @typescript-eslint/[email protected] (sha512-cozo/GbwixVR0sgfHItz3t1yXu521yn71Wj6PlYCFA3WPhy51CUPkifFKfBis91bDclGmAY45hhaAXVjdn4new==) seems to be corrupted. Trying again.
regexp:/tarball tarball data for ([^ ]*) .* seems to be corrupted. Trying again/,
// android:exported needs to be explicitly specified for element <activity#androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
regexp:
/Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported`/,
createError:()=>
newTrackedBuildError(
'REQUIRE_EXPLICIT_EXPORTED_ANDROID_12',
'Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported`.'
),
},
{
phase: BuildPhase.RUN_GRADLEW,
platform: Platform.ANDROID,
// > A failure occurred while executing com.android.build.gradle.internal.res.Aapt2CompileRunnable
// > Android resource compilation failed
// ERROR:/home/expo/workingdir/build/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: AAPT: error: failed to read PNG signature: file does not start with PNG signature.
regexp:/AAPT: error: failed to read PNG signature: file does not start with PNG signature/,
// Execution failed for task ':app:processReleaseGoogleServices'.
// > Malformed root json
regexp:/Execution failed for task ':app:process.*GoogleServices'.*\s.*Malformed root json/,
createError:()=>
newTrackedBuildError(
'GRADLE_MALFORMED_GOOGLE_SERVICES_JSON',
'gradle: Malformed google-services.json.'
),
},
{
phase: BuildPhase.RUN_GRADLEW,
platform: Platform.ANDROID,
// Execution failed for task ':app:processDebugGoogleServices'.
// > Missing project_info object
regexp:
/Execution failed for task ':app:process.*GoogleServices'.*\s.*Missing project_info object/,
createError:()=>
newTrackedBuildError(
'GRADLE_MALFORMED_GOOGLE_SERVICES_JSON',
'gradle: Missing project_info object.'
),
},
{
phase: BuildPhase.RUN_GRADLEW,
platform: Platform.ANDROID,
// Execution failed for task ':app:bundleReleaseJsAndAssets'.
// > Process 'command 'node'' finished with non-zero exit value 1
regexp:
/Execution failed for task ':app:bundleReleaseJsAndAssets'.*\s.*Process 'command 'node'' finished with non-zero exit value/,
createError:()=>
newTrackedBuildError(
'GRADLE_BUILD_BUNDLER_ERROR',
"gradle: ':app:bundleReleaseJsAndAssets' failed."
),
},
{
platform: Platform.ANDROID,
phase: BuildPhase.RUN_GRADLEW,
// > Could not resolve org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.5.10.
// Required by:
// project :expo-updates
// > Could not resolve org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.5.10.
// > Could not get resource 'https://lsdkfjsdlkjf.com/android/releases/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.5.10/kotlin-annotation-processing-gradle-1.5.10.pom'.
// > Could not HEAD 'https://slkdfjldskjfl.com/android/releases/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.5.10/kotlin-annotation-processing-gradle-1.5.10.pom'.
// > Connect to sdlkfjsdlkf.com:443 [slkdfjdslk.com/38.178.101.5] failed: connect timed out
regexp:/Could not get resource.*\n.*Could not HEAD 'https/,
// error: exportArchive: exportOptionsPlist error for key "iCloudContainerEnvironment": expected one of {Development, Production}, but no value was provided
regexp:/exportArchive: exportOptionsPlist error for key "iCloudContainerEnvironment"/,
createError:()=>
newTrackedBuildError(
'MISSING_ICLOUD_CONTAINER_ENVIRONMENT',
'fastlane: Missing iCloudContainerEnvironment in exportOptionsPlist.'
),
},
{
phase: BuildPhase.RUN_FASTLANE,
platform: Platform.IOS,
// The following build commands failed:
// PhaseScriptExecution [CP-User]\ Generate\ app.manifest\ for\ expo-updates /Users/expo/Library/Developer/Xcode/DerivedData/Kenkohub-eqseedlxbgrzjqagscbclhbtstwh/Build/Intermediates.noindex/ArchiveIntermediates/Kenkohub/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/EXUpdates.build/Script-BB6B5FD28815C045A20B2E5E3FEEBD6E.sh (in target 'EXUpdates' from project 'Pods')
regexp:
/The following build commands failed.*\s.*\[CP-User\]\\ Generate\\ app\.manifest\\ for\\ expo-updates/,
createError:()=>
newTrackedBuildError(
'XCODE_BUILD_UPDATES_PHASE_SCRIPT',
'fastlane: Generating app.manifest for expo-updates failed.'
),
},
{
phase: BuildPhase.RUN_FASTLANE,
platform: Platform.IOS,
// The following build commands failed:
// CompileC /Users/expo/Library/Developer/Xcode/DerivedData/Docent-amxxhphjfdtkpxecgidgzvwvnvtc/Build/Intermediates.noindex/ArchiveIntermediates/Docent/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/Flipper-Folly.build/Objects-normal/arm64/SSLErrors.o /Users/expo/workingdir/build/ios/Pods/Flipper-Folly/folly/io/async/ssl/SSLErrors.cpp normal arm64 c++ com.apple.compilers.llvm.clang.1_0.compiler (in target 'Flipper-Folly' from project 'Pods')
regexp:/in target 'Flipper-Folly' from project 'Pods'/,
createError:()=>
newTrackedBuildError(
'FLIPPER_FOLLY_COMPILE_ERROR',
'fastlane: Flipper-Folly compile error.'
),
},
{
phase: BuildPhase.RUN_FASTLANE,
platform: Platform.IOS,
// The following build commands failed:
// PhaseScriptExecution Bundle\ React\ Native\ code\ and\ images /Users/expo/Library/Developer/Xcode/DerivedData/cnaxwpahkhcjluhigkcwrturapmm/Build/Intermediates.noindex/ArchiveIntermediates/Test/IntermediateBuildFilesPath/Test.build/Release-iphoneos/Test.build/Script-00DD1BFF151E006B06BC.sh (in target 'Test' from project 'Test')
regexp:/Could not find 'bundler' (.*) required by your/,
// example log:
// /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/dependency.rb:313:in `to_specs': Could not find 'bundler' (2.2.3) required by your /Users/expo/project/build/ios/Gemfile.lock. (Gem::MissingSpecVersionError)
createError:()=>
newUserError(
'EAS_BUILD_UNSUPPORTED_BUNDLER_VERSION_ERROR',
`Your project requires a different version of the Ruby "bundler" program than the version installed in this EAS Build environment. You can specify which version of "bundler" to install by specifying the version under "build"→[buildProfileName]→"ios"→"bundler" in eas.json.`,
// > Failed to read key keyalias from store "/build/workingdir/build/generic/keystore-5787e6af-3002-4cb7-8a57-3e73d13313c2.jks": Invalid keystore format
regexp:/Invalid keystore format/,
createError:()=>
newUserError(
'EAS_BUILD_INVALID_KEYSTORE_FORMAT_ERROR',
'The keystore used in this build is malformed or it has an unsupported type. Make sure you provided the correct file.'
),
},
{
platform: Platform.ANDROID,
phase: BuildPhase.RUN_GRADLEW,
// example log:
// > Failed to read key keyalias from store "/build/workingdir/build/generic/keystore-286069a8-4bb9-48a6-add9-acf6b58ea06d.jks": null
regexp:/Failed to read key[^\n]+from store/,
createError:()=>
newUserError(
'EAS_BUILD_INVALID_KEYSTORE_ALIAS_ERROR',
'The alias specified for this keystore does not exist. Make sure you specified the correct value.'
),
},
{
platform: Platform.ANDROID,
phase: BuildPhase.PREBUILD,
// example log:
// [15:42:05] Error: Cannot copy google-services.json from /build/workingdir/build/managed/abc to /build/workingdir/build/managed/android/app/google-services.json
// or
// [11:17:29] [android.dangerous]: withAndroidDangerousBaseMod: Cannot copy google-services.json from /home/expo/workingdir/build/test/test-google-services.json to /home/expo/workingdir/build/android/app/google-services.json. Please make sure the source and destination paths exist.
// [11:17:29] Error: [android.dangerous]: withAndroidDangerousBaseMod: Cannot copy google-services.json from /home/expo/workingdir/build/test/test-google-services.json to /home/expo/workingdir/build/android/app/google-services.json. Please make sure the source and destination paths exist.
regexp:/Cannot copy google-services\.json/,
createError:()=>
newUserError(
'EAS_BUILD_MISSING_GOOGLE_SERVICES_JSON_ERROR',
'"google-services.json" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.',
// Execution failed for task ':app:processReleaseGoogleServices'.
// > File google-services.json is missing. The Google Services Plugin cannot function without it.
// Searched Location:
regexp:
/File google-services\.json is missing\. The Google Services Plugin cannot function without it/,
createError:()=>
newUserError(
'EAS_BUILD_MISSING_GOOGLE_SERVICES_JSON_ERROR',
'"google-services.json" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.',
// [08:44:18] ENOENT: no such file or directory, copyfile '/Users/expo/workingdir/build/managed/abc' -> '/Users/expo/workingdir/build/managed/ios/testapp/GoogleService-Info.plist'
regexp:/ENOENT: no such file or directory, copyfile .*GoogleService-Info.plist/,
createError:()=>
newUserError(
'EAS_BUILD_MISSING_GOOGLE_SERVICES_PLIST_ERROR',
'"GoogleService-Info.plist" is missing, make sure that the file exists. Remember that EAS Build only uploads the files tracked by git. Use EAS environment variables to provide EAS Build with the file.',
// Specs satisfying the `react-native-google-maps (from `/Users/expo/workingdir/build/node_modules/react-native-maps`)` dependency were found, but they required a higher minimum deployment target.
// Error: Compatible versions of some pods could not be resolved.
regexp:
/Specs satisfying the `(.*)` dependency were found, but they required a higher minimum deployment target/,
`Some pods require a higher minimum deployment target.
${
'type'injob&&job.type===Workflow.MANAGED
?'You can use the expo-build-properties config plugin (https://docs.expo.dev/versions/latest/sdk/build-properties/) to override the default native build properties and set a different minimum deployment target.'
:'You need to manually update the minimum deployment target in your project to resolve this issue.'
}
`
);
},
},
{
platform: Platform.IOS,
phase: BuildPhase.INSTALL_PODS,
// example log:
// [!] CocoaPods could not find compatible versions for pod "Firebase/Core":
// In snapshot (Podfile.lock):
// Firebase/Core (= 6.14.0)
// In Podfile:
// EXFirebaseCore (from `../node_modules/expo-firebase-core/ios`) was resolved to 3.0.0, which depends on
// Firebase/Core (= 7.7.0)
// You have either:
// * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
// * changed the constraints of dependency `Firebase/Core` inside your development pod `EXFirebaseCore`.
// You should run `pod update Firebase/Core` to apply changes you've made.
regexp:/CocoaPods could not find compatible versions for pod /,
createError:()=>{
returnnewUserError(
'EAS_BUILD_INCOMPATIBLE_PODS_ERROR',
`Compatible versions of some pods could not be resolved.
You are seeing this error because either:
- Some of the pods used in your project depend on different versions of the same pod. See logs for more information.
- If you are caching Podfile.lock using "cache" field in eas.json, then versions there might not match required values in Podspecs of some installed libraries. To fix this, you can re-run build command with "--clear-cache" option, or select "Clear cache and retry build" on the build page.
`
);
},
},
{
phase: BuildPhase.INSTALL_DEPENDENCIES,
// example log:
// [stderr] npm ERR! Fix the upstream dependency conflict, or retry
// [stderr] npm ERR! this command with --force, or --legacy-peer-deps
// [stderr] npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
regexp:
/Fix the upstream dependency conflict, or retry.*\s.*this command with --force, or --legacy-peer-deps/,
createError:(matchResult: RegExpMatchArray)=>{
if(matchResult.length>=2){
returnnewUserError(
'EAS_BUILD_NPM_CONFLICTING_PEER_DEPENDENCIES',
`Some of your peer dependencies are not compatible. The recommended approach is to fix your dependencies by resolving any conflicts listed by "npm install". As a temporary workaround you can:
- Add ".npmrc" file with "legacy-peer-deps=true" and commit that to your repo.
- Delete package-lock.json and use yarn instead. It does not enforce peer dependencies.
- Downgrade to older version of npm on EAS Build, by adding "npm install -g npm@version" in "eas-build-pre-install" script in package.json.`
);
}
returnundefined;
},
},
{
phase: BuildPhase.INSTALL_DEPENDENCIES,
// example log:
// [stderr] error https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz: Integrity check failed for "react-native" (computed integrity doesn't match our records, got "sha512-3jHI2YufrJi7eIABRf/DN/I2yOkmIZ0vAyezTz+PAUJiEs4v//5LLojWEU+W53AZsnuaEMcl/4fVy4bd+OuUbA== sha1-o9QuQTXIkc8VozXPaZIullB9a40=")
regexp:/Integrity check failed for "(.*)" \(computed integrity doesn't match our records, got/,
createError:(matchResult: RegExpMatchArray)=>{
if(matchResult.length>=2){
returnnewUserError(
'EAS_BUILD_YARN_LOCK_CHECKSUM_ERROR',
`Checksum for package "${matchResult[1]}" does not match value in registry. To fix that:
- run "yarn cache clean"
- remove yarn.lock (or only the section for that package)
- run "yarn install --force"`
);
}
returnundefined;
},
},
{
phase: BuildPhase.INSTALL_DEPENDENCIES,
// example log:
// yarn install v1.22.17
// [1/4] Resolving packages...
// [2/4] Fetching packages...
// [1/4] Resolving packages...
// [2/4] Fetching packages...
// [stderr] error https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz: Extracting tar content of undefined failed, the file appears to be corrupt: "ENOENT: no such file or directory, chmod '/Users/expo/Library/Caches/Yarn/v6/npm-jest-util-26.6.2-907535dbe4d5a6cb4c47ac9b926f6af29576cbc1-integrity/node_modules/jest-util/build/pluralize.d.ts'"
`One of project dependencies is starting new install process while the main one is still in progress, which might result in corrupted packages. Most likely the reason for error is "prepare" script in git-referenced dependency of your project. Learn more: https://github.com/yarnpkg/yarn/issues/7212#issuecomment-493720324`
);
}
returnundefined;
},
},
{
platform: Platform.IOS,
phase: XCODE_BUILD_PHASE,
// Prepare packages
// Computing target dependency graph and provisioning inputs
// /Users/expo/workingdir/build/managed/ios/Pods/Pods.xcodeproj: error: Signing for "EXConstants-EXConstants" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'EXConstants-EXConstants' from project 'Pods')
// /Users/expo/workingdir/build/managed/ios/Pods/Pods.xcodeproj: error: Signing for "React-Core-AccessibilityResources" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'React-Core-AccessibilityResources' from project 'Pods')
// warning: Run script build phase '[CP-User] Generate app.manifest for expo-updates' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'EXUpdates' from project 'Pods')
// warning: Run script build phase 'Start Packager' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'testapp' from project 'testapp')
// warning: Run script build phase 'Bundle React Native code and images' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'testapp' from project 'testapp')
// warning: Run script build phase '[CP-User] Generate app.config for prebuilt Constants.manifest' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'EXConstants' from project 'Pods')
// /Users/expo/workingdir/build/managed/ios/Pods/Pods.xcodeproj: error: Signing for "EXUpdates-EXUpdates" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'EXUpdates-EXUpdates' from project 'Pods')
regexp:/error: Signing for "[a-zA-Z-0-9_]+" requires a development team/,
createError:(_,{job})=>
'type'injob&&job.type===Workflow.MANAGED
?newUserError(
'XCODE_RESOURCE_BUNDLE_CODE_SIGNING_ERROR',
`Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
To resolve this issue, downgrade to an older Xcode version using the "image" field in eas.json, or upgrade to SDK 46 or higher.`,
`Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
To resolve this issue, downgrade to an older Xcode version using the "image" field in eas.json, or turn off signing resource bundles in your Podfile: https://expo.fyi/r/disable-bundle-resource-signing`,
`The bundle identifier in provisioning profile used to resign the app does not match the bundle identifier of the app selected to be resigned. See logs above for more information.`
),
},
{
platform: Platform.IOS,
phase: BuildPhase.RUN_FASTLANE,
mode: BuildMode.RESIGN,
regexp:/.*/,
createError:()=>
newUserError(
errors.ErrorCode.UNKNOWN_FASTLANE_RESIGN_ERROR,
`The "Run fastlane" step failed with an unknown error.`
),
},
{
platform: Platform.IOS,
phase: XCODE_BUILD_PHASE,
// MkDir /Users/expo/workingdir/build/packages/apps/NFLNetwork/ios/build/Build/Products/Release-iphonesimulator/expo-dev-launcher/EXDevLauncher.bundle (in target 'expo-dev-launcher-EXDevLauncher' from project 'Pods')
// cd /Users/expo/workingdir/build/packages/apps/NFLNetwork/ios/Pods
// /Users/expo/workingdir/build/packages/video/ios/Vendor/dependency/ProgrammaticAccessLibrary.xcframework:1:1: error: The signature of “ProgrammaticAccessLibrary.xcframework” cannot be verified.
// note: A sealed resource is missing or invalid
// note: /Users/expo/workingdir/build/packages/video/ios/Vendor/dependency/ProgrammaticAccessLibrary.xcframework: a sealed resource is missing or invalid
`The "Run fastlane" step failed because of an error in the Xcode build process. We automatically detected following errors in your Xcode build logs:\n${matchResult
.map(match=>`- ${match.replace('error: ','')}`)
.join('\n')}\nRefer to "Xcode Logs" below for additional, more detailed logs.`
),
},
{
platform: Platform.IOS,
phase: BuildPhase.RUN_FASTLANE,
regexp:/.*/,
createError:()=>
newUserError(
errors.ErrorCode.UNKNOWN_FASTLANE_ERROR,
`The "Run fastlane" step failed with an unknown error. Refer to "Xcode Logs" below for additional, more detailed logs.`
'Skipped running "expo prebuild" because the "android" directory already exists. Learn more about the build process: https://docs.expo.dev/build-reference/android-builds/'
'Skipped running "expo prebuild" because the "ios" directory already exists. Learn more about the build process: https://docs.expo.dev/build-reference/ios-builds/'
'"Install pods" phase takes longer then expected and it did not produce any logs in the past 15 minutes'
);
},INSTALL_PODS_WARN_TIMEOUT_MS);
killTimeout=setTimeout(async()=>{
timedOutToKill=true;
ctx.logger.error(
'"Install pods" phase takes a very long time and it did not produce any logs in the past 30 minutes. Most likely an unexpected error happened which caused the process to hang and it will be terminated'
Loaded 100 of 1556 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.