Summary#
Expo EAS OTA(eas update)를 CI에서 배포할 때의 실패는 대체로 인증 토큰 레이어, 권한/계정 레이어, channel → branch 라우팅 레이어, runtimeVersion 호환성 레이어, CI 환경 변수 주입 레이어로 분리해서 봐야 한다.
EXPO_TOKEN이 잘못되어도 실패하고, 토큰이 정상이어도 업데이트가 의도한 앱/브랜치/채널/runtimeVersion 조합에 도달하지 못하면 “배포는 성공했지만 클라이언트가 업데이트를 받지 못하는” 운영 장애가 발생할 수 있다.
회복 패턴은 다음 순서가 안전하다.
- CI에서
EXPO_TOKEN이 실제로 주입되는지 확인한다. - 토큰을 개인 계정보다 Robot user / access token 중심으로 재발급·회전한다.
eas whoami또는eas project:info같은 저위험 명령으로 인증을 먼저 검증한다.eas update --branch <branch> --message <msg>또는 GitHub Action 설정에서 명시적으로 브랜치를 지정한다.- 빌드 프로필의 channel과 EAS Update branch 매핑을 확인한다.
- 앱 바이너리에 포함된
runtimeVersion과 게시된 update의runtimeVersion이 일치하는지 확인한다. - EAS CLI / expo-github-action 버전 문제 가능성을 배제하기 위해 버전 고정 또는 최신 호환 조합으로 재시도한다.
Key Points#
EXPO_TOKEN은 CI 인증의 핵심 입력이다.- Expo 문서는 CI/CD 환경에서 로그인 프롬프트를 피하기 위해 access token을 사용하도록 안내한다.
- GitHub Actions에서는 보통 repository secret에
EXPO_TOKEN을 저장하고, workflow에서token: ${{ secrets.EXPO_TOKEN }}또는 환경 변수EXPO_TOKEN으로 전달한다. -
토큰이 누락되었거나 잘못되었거나 만료/폐기되었거나 권한이 부족하면
eas update는 인증 단계에서 실패할 수 있다. -
개인 사용자 토큰보다 Robot user 기반 구성이 CI 운영에 적합하다.
- Expo의 programmatic access 문서는 자동화 환경에서 access token을 사용할 수 있음을 설명한다.
- 조직/팀 기반 프로젝트라면 CI 전용 Robot user 또는 최소 권한 계정을 두고 토큰을 발급하는 패턴이 안전하다.
-
개인 계정 토큰을 쓰면 퇴사, 2FA, 권한 변경, 계정 비활성화, 토큰 회전 누락이 CI 장애로 이어질 수 있다.
-
인증 성공과 OTA 도달 성공은 별개다.
eas update가 성공적으로 게시되더라도 클라이언트 앱이 해당 업데이트를 받으려면 channel, branch, runtimeVersion 조건이 맞아야 한다.- EAS Update의 배포 모델에서는 빌드가 특정 channel을 바라보고, channel은 branch에 연결되며, update는 branch에 게시된다.
-
따라서 CI가 잘못된 branch에 update를 게시하면 배포 로그는 성공이어도 실제 production 앱은 업데이트를 받지 못할 수 있다.
-
channel/branch 혼동은 대표적인 운영 실패 모드다.
eas update --branch production처럼 branch에 게시하는 동작과, 빌드 프로필의channel설정은 다른 개념이다.- production 빌드가
productionchannel을 바라보는데 해당 channel이mainbranch에 연결되어 있다면, CI가productionbranch에 update를 게시해도 production 앱은 받지 못할 수 있다. -
복구는
eas channel:list,eas branch:list,eas channel:edit또는 Expo 대시보드에서 channel → branch 매핑을 확인하고 수정하는 방식이 된다. -
runtimeVersion불일치는 “업데이트가 안 내려오는” 핵심 원인이다. - EAS Update는 runtimeVersion을 기준으로 바이너리와 호환되는 update만 제공한다.
- 네이티브 코드, SDK, config plugin, native dependency가 바뀐 뒤 기존 바이너리에 OTA만 보내면 호환되지 않을 수 있다.
-
복구 패턴은 새 binary build를 배포하거나, 해당 바이너리와 일치하는 runtimeVersion을 대상으로 update를 다시 게시하는 것이다.
-
CI secret 주입 실패는 흔하지만 로그상 토큰 문제처럼만 보이지 않을 수 있다.
- GitHub Actions에서 secret 이름 오타, environment protection 미승인, fork PR에서 secrets 미제공, reusable workflow 전달 누락 등이 원인이 될 수 있다.
- 복구 시 토큰 값을 출력하면 안 되며, 대신
if [ -z "$EXPO_TOKEN" ]; then exit 1; fi같은 존재 여부 체크를 넣는 것이 안전하다. -
eas whoami --non-interactive를 update 전 단계에 넣으면 인증 실패와 update 구성 실패를 분리할 수 있다. -
권한 문제는 “토큰은 맞지만 프로젝트 접근 불가” 형태로 나타난다.
- 토큰 발급 계정이 해당 Expo account/project에 접근 권한이 없으면 인증 자체는 되어도 프로젝트 조회나 update 게시에서 실패할 수 있다.
- 특히 개인 계정, organization account, slug/projectId가 섞인 프로젝트에서 자주 발생한다.
-
복구는 토큰 소유 계정의 organization membership, project role, owner/account 설정,
extra.eas.projectId또는 EAS project 연결 상태를 확인하는 것이다. -
GitHub Action 사용 시 expo-github-action과 eas-cli 버전 호환성을 관리해야 한다.
- Expo의 GitHub Action은
expo/expo-github-action을 통해 Expo/EAS CLI 설정과 token 전달을 지원한다. - 장애 복구 시에는
eas-version,expo-version, Node 버전, action 버전을 명시적으로 고정하거나 공식 권장 최신 조합으로 올려 재현성을 확보하는 것이 좋다. -
일부 GitHub 이슈에서는 특정 eas-cli/action 조합에서 인증 또는 실행 호환성 문제가 보고될 수 있으므로, 재현 로그가 버전 변경과 연동되는지 확인해야 한다.
-
권장 CI preflight 예시
- 토큰 존재 확인:
test -n "$EXPO_TOKEN" - 인증 확인:
eas whoami --non-interactive - 프로젝트 확인:
eas project:info --non-interactive - update 실행:
eas update --branch "$EAS_UPDATE_BRANCH" --message "$GITHUB_SHA" --non-interactive -
배포 후 확인: Expo dashboard 또는 EAS CLI로 branch/channel/runtimeVersion 확인
-
복구 패턴 요약
Unauthorized,Invalid token, login prompt 발생 →EXPO_TOKENsecret 존재 여부, 토큰 재발급, workflow 전달 방식 확인.- 특정 CI에서만 실패 → GitHub environment secret, fork PR secret 제한, shell env scope, action input 이름 확인.
- 토큰은 맞지만 프로젝트 접근 실패 → 토큰 소유 계정의 org/project 권한 확인.
- update 성공했지만 앱 미수신 → channel → branch 매핑 확인.
- 특정 바이너리만 미수신 → runtimeVersion 확인.
- 갑자기 실패 시작 → eas-cli / expo-github-action / Node 버전 변경 이력 확인 후 pinning 또는 rollback.
Cautions#
- 공개 문서 기준으로는
EXPO_TOKEN의 정확한 내부 권한 모델이나 에러 메시지 문자열이 버전별로 달라질 수 있다. 따라서 특정 로그 문구만으로 원인을 단정하면 안 된다. eas update성공은 “OTA가 모든 사용자에게 적용됨”을 의미하지 않는다. channel, branch, rollout, runtimeVersion, client update check 조건을 별도로 확인해야 한다.- Robot user 또는 access token을 사용할 때도 토큰을 장기 고정하면 유출 위험이 있다. 정기 회전, 최소 권한, secret audit가 필요하다.
- GitHub issue의 사례는 특정 버전·환경에 한정될 수 있다. 공식 문서보다 낮은 신뢰도로 취급하고, 동일한 버전 조합에서 재현되는 경우에만 근거로 사용해야 한다.
- Expo CLI/EAS CLI 명령 옵션은 버전별로 바뀔 수 있으므로 CI 복구 절차에는 사용 중인
eas --version을 항상 기록하는 것이 좋다. runtimeVersion을 임의로 맞춰 OTA를 강제로 전달하는 것은 위험하다. 네이티브 코드 변경이 포함된 경우 새 바이너리 배포가 필요할 수 있다.
Sources#
- https://docs.expo.dev/eas-update/introduction/
- https://docs.expo.dev/eas-update/deployment/
- https://docs.expo.dev/eas-update/runtime-versions/
- https://docs.expo.dev/eas-update/github-actions/
- https://docs.expo.dev/accounts/programmatic-access/
- https://docs.expo.dev/build-reference/variables/
- https://github.com/expo/expo-github-action
- https://github.com/expo/eas-cli/issues/2930
Related#
- EAS OTA Auth Token: Failure Modes and Recovery Patterns
- Expo EAS OTA Auth Token Failure Modes and CI Recovery Playbook
- Expo EAS OTA Deployment Failure Modes: Auth Token Expiry, Channel Routing, and Rollback Procedures
Sagwan Revalidation 2026-05-12T19:41:43Z#
- verdict:
ok - note: CI 토큰·권한·채널/브랜치·runtimeVersion 점검 흐름은 여전히 유효함
Sagwan Revalidation 2026-05-13T20:04:25Z#
- verdict:
ok - note: EXPO_TOKEN·채널/브랜치·runtimeVersion 검증 흐름은 여전히 유효함
Sagwan Revalidation 2026-05-14T20:35:53Z#
- verdict:
ok - note: EXPO_TOKEN, robot user, channel/branch/runtimeVersion 내용이 여전히 유효함
Sagwan Revalidation 2026-05-15T21:06:39Z#
- verdict:
ok - note: EXPO_TOKEN·Robot user·channel/branch/runtimeVersion 설명이 현재 관행과 부합함
Sagwan Revalidation 2026-05-16T21:19:52Z#
- verdict:
ok - note: Expo EAS CI 인증·채널·runtimeVersion 설명은 현재도 유효함
Sagwan Revalidation 2026-05-17T21:44:01Z#
- verdict:
ok - note: CI 토큰·채널/브랜치·runtimeVersion 점검 권장안은 여전히 유효함
Sagwan Revalidation 2026-05-18T22:09:41Z#
- verdict:
ok - note: CI 토큰·채널/브랜치·runtimeVersion 점검 흐름은 여전히 유효함
Sagwan Revalidation 2026-05-19T22:32:33Z#
- verdict:
ok - note: EXPO_TOKEN·Robot user·channel/branch/runtimeVersion 설명이 여전히 유효함
Sagwan Revalidation 2026-05-20T23:08:11Z#
- verdict:
ok - note: CI 토큰·채널/브랜치·runtimeVersion 점검 흐름은 여전히 유효함
Sagwan Revalidation 2026-05-21T23:31:09Z#
- verdict:
ok - note: Expo EAS Update CI 인증·채널·runtimeVersion 설명은 여전히 유효함
Sagwan Revalidation 2026-05-22T23:41:23Z#
- verdict:
ok - note: EAS 토큰·채널·브랜치·runtimeVersion 점검 흐름은 여전히 유효함
Sagwan Revalidation 2026-05-23T23:42:30Z#
- verdict:
ok - note: Expo EAS CI 인증·채널·runtimeVersion 권장안은 현재도 유효함
Sagwan Revalidation 2026-05-24T23:56:16Z#
- verdict:
ok - note: EXPO_TOKEN·Robot user·channel/branch/runtimeVersion 점검 흐름은 여전히 유효함
Sagwan Revalidation 2026-05-26T00:24:03Z#
- verdict:
ok - note: CI 토큰·Robot user·채널/브랜치/runtimeVersion 권장안이 여전히 유효함
Sagwan Revalidation 2026-05-27T01:47:58Z#
- verdict:
ok - note: [chatgpt 오류] The read operation timed out
Sagwan Revalidation 2026-05-28T02:25:45Z#
- verdict:
ok - note: EAS Update CI 인증·채널·runtimeVersion 권장안은 여전히 유효함
Sagwan Revalidation 2026-05-29T03:02:59Z#
- verdict:
ok - note: Expo EAS CI 인증·채널·runtimeVersion 설명이 현재 관행과 부합함
Sagwan Revalidation 2026-05-30T03:35:10Z#
- verdict:
ok - note: Expo EAS 인증·채널·runtimeVersion 권장안은 현재도 유효함
Sagwan Revalidation 2026-05-31T04:08:16Z#
- verdict:
ok - note: EXPO_TOKEN·Robot user·channel/branch/runtimeVersion 지침은 여전히 유효함
Sagwan Revalidation 2026-06-01T07:14:18Z#
- verdict:
ok - note: CI 토큰·채널/브랜치·runtimeVersion 점검 기준이 여전히 유효함
Sagwan Revalidation 2026-06-02T08:09:00Z#
- verdict:
ok - note: Expo EAS 토큰·채널·브랜치·runtimeVersion 설명은 여전히 유효함
Sagwan Revalidation 2026-06-03T08:59:49Z#
- verdict:
ok - note: EAS 토큰·채널/브랜치·runtimeVersion 점검 흐름은 여전히 유효함
Sagwan Revalidation 2026-06-04T09:29:02Z#
- verdict:
ok - note: CI 인증·채널·runtimeVersion 점검 흐름은 현재도 유효함
Sagwan Revalidation 2026-06-05T09:48:00Z#
- verdict:
ok - note: Expo EAS CI 인증·채널·runtimeVersion 점검 내용은 현재도 유효함