With EAS Workflows, how do you build and submit a budgeting app on every push to main, and how does the submit job get the build?
answer
- YAML under .eas/workflows
- on.push.branches
- type: build, then type: submit
- needs plus outputs.build_id
- GitHub link for push triggers
basics
~10 sA YAML file in .eas/workflows triggers on push to main, runs a build job (type: build) per platform, then a submit job (type: submit) that needs it and reads its build_id output.
solid answer
~40 sEAS Workflows are YAML files in **.eas/workflows/**, next to `eas.json`. `on: push: branches: ['main']` triggers the workflow on pushes to main once the GitHub repository is linked to the EAS project; `eas workflow:run` starts any workflow by hand. Under `jobs`, a pre-packaged job with `type: build` takes `params.platform` (required) and `params.profile` (default `production`). A `type: submit` job lists the build in `needs`, so it runs only if the build succeeded, and passes `build_id: ${{ needs.build_android.outputs.build_id }}`. There is no matrix support, so Android and iOS are two job pairs. With `autoIncrement` and a remote version source on the production profile, every merge also gets a fresh build number.
code
bash · 2 lines# run a workflow by hand, whatever its on: triggers say
eas workflow:run .eas/workflows/release-on-main.ymlgo deeper
Recall that EAS Workflows are YAML files in .eas/workflows made of pre-packaged jobs such as build and submit.
Explain triggers, the build job's params and outputs, and how needs plus interpolation hand the build_id to the submit job.
Show you can run it in production: credential prerequisites, remote build numbers per merge, path filters, skip markers and notification jobs using after.
Weigh EAS Workflows against a general CI system: less wiring and mobile-specific jobs versus no matrices, no shared configuration and another vendor to govern.
## What EAS Workflows are **EAS Workflows** is Expo's hosted CI/CD for app tasks. A workflow is a YAML file (`.yml` or `.yaml`) in the **.eas/workflows/** directory, at the same level as `eas.json`. Instead of scripting every command, you compose **pre-packaged job types** — `build`, `submit`, `update`, `fingerprint`, `get-build`, `testflight`, `maestro` and more — and wire them together with control-flow keys. ## Triggering on merges to main The `on` key names the GitHub events that start the workflow: - `on.push.branches` — pushes to matching branches; globs work, and `!` excludes a pattern. - `on.push.paths` — only when matching files changed, useful in a monorepo. - `on.pull_request` — pull requests targeting matching branches. - `on.schedule.cron` — timed runs. Push and pull-request triggers need the GitHub repository **linked to the EAS project** through the GitHub app. Independently of `on`, `eas workflow:run .eas/workflows/<file>.yml` starts any workflow manually. A commit message containing `[eas skip]`, `[skip eas]` or `[no eas]` skips push- and pull-request-triggered runs. ## Build and submit jobs A `build` job builds one platform: | Param | Required | Meaning | |---|---|---| | `platform` | yes | `android` or `ios` | | `profile` | no | build profile from `eas.json`, default `production` | | `message` | no | like `eas build --message` | It exposes **outputs** such as `build_id`, `app_build_version`, `app_version`, `distribution` and `profile`. A `submit` job takes `params.build_id` (required) and `params.profile` (the submit profile, default `production`) and uploads that build with EAS Submit. ## Passing the build between jobs Jobs run in parallel unless control flow says otherwise: 1. **`needs: [build_android]`** — run after that job and **only if it succeeded**. 2. **`after: [build_android]`** — run after that job **whether it succeeded or not**, useful for notifications. 3. **`if: ${{ ... }}`** — skip the job unless an expression holds; a skipped job counts as not successful for anything that `needs` it. The submit job reads the build through interpolation: `${{ needs.build_android.outputs.build_id }}`. ## The budgeting app's workflow ```yaml name: Release on main on: push: branches: ['main'] jobs: build_android: type: build params: platform: android profile: production submit_android: needs: [build_android] type: submit params: build_id: ${{ needs.build_android.outputs.build_id }} build_ios: type: build params: platform: ios profile: production submit_ios: needs: [build_ios] type: submit params: build_id: ${{ needs.build_ios.outputs.build_id }} ``` EAS Workflows has **no matrix builds**, so each platform is spelled out; the two pairs still run in parallel. ## Practical requirements - **Credentials first.** The build job's documented prerequisite is one completed build from your machine with the same platform and profile, which is typically when signing credentials get set up on EAS. - **Build numbers.** With `cli.appVersionSource: "remote"` and `autoIncrement: true` on the production profile, each merge-triggered build gets a new build number without a commit back to main. - **Environment variables** for the build are normally configured on the build profile and its EAS environment, which keeps the YAML about orchestration. - **Submission settings** such as the Play track or TestFlight groups live in the submit profile, so the YAML stays short. ## Operating the workflow EAS CLI has commands for the day-to-day side: - `eas workflow:validate` checks a workflow YAML file before you push it. - `eas workflow:runs` lists recent runs, `eas workflow:logs` shows a run's logs, and `eas workflow:cancel` stops one. - Each run also appears on the project's workflows page in the EAS dashboard, named by the workflow's `name` key. For the budgeting app, a useful addition is a notification job with `after: [submit_android, submit_ios]`, so the team hears about failures as well as successes. ## Compared with a generic CI script A generic CI runner can do the same by calling `eas build --non-interactive` and `eas submit`, but it must manage the Expo token, wait for the build and carry its ID between steps. The pre-packaged jobs do that wiring for you; the trade-off is a narrower model, with no shared configurations between workflows and no matrices.
- What is the difference between needs and after in an EAS Workflows job?`needs` waits for the listed jobs and runs only if all of them succeeded, which suits a submit that must not upload a failed build. `after` waits for them to finish whatever the outcome, which suits a notification job that reports both success and failure.
- How do you stop a documentation-only commit on main from triggering the build workflow?Put `[eas skip]`, `[skip eas]` or `[no eas]` in the commit message, or narrow the trigger with `on.push.paths` so only changes under the app's source directories start the workflow.
- Why might the first run of a workflow build job fail even though the YAML is valid?The build job expects signing credentials to exist on EAS. Expo's documented prerequisite is one completed build from your machine with the same platform and profile, which is when credentials are generated or uploaded interactively.
saying these in an interview costs you the question
- EAS Workflows files go in .github/workflows
- A submit job finds the latest build on its own without a build_id
- after runs a job only when the earlier job succeeded
- One build job can target android and ios through a matrix
- Push triggers work without linking the GitHub repository to EAS