EAS Workflows reports SKIPPED jobs as GitHub commit status "success"
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 236
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 98
Description
### Build/Submit details page URL
https://expo.dev/accounts/propertymeld/projects/meldmobile/workflows/019ff80f-2c9e-795b-b6e0-8c6cff5914a1
### Summary
EAS Workflows reports jobs that were internally marked SKIPPED (because their if condition evaluated to false) to GitHub as commit status state: success — identical to a job that actually ran and passed. Since GitHub's Commit Status API has no "skipped" state, a skipped job and a genuinely-completed job are visually indistinguishable in the GitHub PR checks list. This is especially misleading around require-approval gates: while a require-approval job is still pending (correctly reported as state: pending), sibling/downstream jobs that get skipped as a side effect can show up as green "✓ success" checks even though they never ran, making a PR look fully deployed/released when it isn't.
### Managed or bare?
Bare
### Environment
expo-env-info 2.1.0 environment info:
System:
OS: macOS 26.5.1
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.20.0 - /.nvm/versions/node/v20.20.0/bin/node
Yarn: 1.22.22 - /opt/homebrew/bin/yarn
npm: 11.16.0 - /.nvm/versions/node/v20.20.0/bin/npm
Watchman: 2026.01.12.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.16.2 - /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 25.5, iOS 26.5, macOS 26.5, tvOS 26.5, visionOS 26.5, watchOS 26.5
IDEs:
Android Studio: 2026.1 AI-261.23567.138.2611.15646644
Xcode: 26.5/17F42 - /usr/bin/xcodebuild
npmPackages:
expo: ~54.0.34 => 54.0.34
expo-router: ~6.0.23 => 6.0.23
expo-updates: ~29.0.17 => 29.0.17
react: 19.1.0 => 19.1.0
react-dom: 19.1.0 => 19.1.0
react-native: 0.81.5 => 0.81.5
react-native-web: ~0.21.2 => 0.21.2
npmGlobalPackages:
eas-cli: 21.8.0
Expo Workflow: bare
### Error output
Not applicable — this is not a crash/error, but a status-reporting inconsistency between EAS's internal job state and the GitHub commit status it publishes.
### Reproducible demo or steps to reproduce from a blank project
1. Create an EAS Workflow with:
- a `require-approval` job (e.g. `approval_gate`),
- a second, independent job whose `if` condition is only true when a build already exists (e.g. `if: ${{ needs.get_ios_build.outputs.build_id || needs.get_android_build.outputs.build_id }}`), plus one or more jobs after it (e.g. two `update`-type jobs that publish an OTA update once that job succeeds).
2. Trigger the workflow on a commit where no existing build matches the current fingerprint, so the conditional branch's `if` evaluates to `false` and those jobs are marked `SKIPPED` by EAS, while `approval_gate` is left `ACTION_REQUIRED` (pending human approval).
3. Compare EAS's own record of job state against what's published to GitHub for the same commit:
- `eas workflow:view --json` → the skipped jobs show `"status": "SKIPPED"`.
- `gh api repos/{owner}/{repo}/commits/{sha}/statuses` (or the PR's checks list in the GitHub UI) → the same jobs show `"state": "success"` (with `"description": "Job has been skipped."`).
4. **Expected:** a job EAS itself considers `SKIPPED` should not be reported to GitHub as `success`, since that's indistinguishable from a job that actually ran and passed. **Actual:** it's reported as `success`.
**Example observed in one of our production workflow runs** (details anonymized):
| Job (role) | EAS status (`eas workflow:view`) | GitHub commit status |
|---|---|---|
| conditional approval gate, skipped because no build existed yet | `SKIPPED` | `state: success`, "Job has been skipped." |
| downstream update-publish job (Android) | `SKIPPED` | `state: success`, "Job has been skipped." |
| downstream update-publish job (iOS) | `SKIPPED` | `state: success`, "Job has been skipped." |
| primary `require-approval` gate, awaiting a human click | `ACTION_REQUIRED` | `state: pending`, "Job requires user action." (correct) |
Contributor guide
Research direction
Start by tracing the EAS workflow job status mapping used when publishing GitHub commit statuses, reproducing the case with `eas workflow:view --json` and `gh api repos/{owner}/{repo}/commits/{sha}/statuses`. Done means EAS jobs with status `SKIPPED` are no longer reported as GitHub `success`, while pending approval jobs retain their pending status.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github, typescript
- Domain
- ci-cd
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 57/100