> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiveku.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Builds & Submissions

> OTA updates, native EAS builds, auto-submission, the cancel button, and Fix-with-AI on failures

The Builds page is where you ship — both the fast path (OTA bundles in 30 seconds) and the slow path (native binaries, 20–30 minutes, auto-submitted to the stores). Every Hiveku Native Mobile project routes through this page; there is no terminal step.

## Two ways to ship

| Path                    | Time          | Use when                                                                                      |
| ----------------------- | ------------- | --------------------------------------------------------------------------------------------- |
| **Publish OTA Update**  | \~30 seconds  | JS-only changes — new screens, style tweaks, Supabase queries, business logic                 |
| **Native Build & Ship** | 20–30 minutes | Adding a native dependency, changing the app icon/splash, version bumps, the very first build |

The rule of thumb: if your change touches `package.json` and adds a package that has native code (anything with a `ios/` or `android/` folder in the package), you need a Build & Ship. Everything else is OTA.

If you're not sure, click **Native Modules** in the side nav — it lists every package and tells you which path it requires.

## The OTA Update path

OTA stands for "over-the-air." Instead of rebuilding a native binary, EAS Update publishes a new JS bundle to a hosted channel. Users running your app pick it up on next launch.

### Channels

Two channels per project, both pre-created:

* **Preview** — for QA. Open the result in Expo Go on your phone. Only people with the link see this build.
* **Production** — for users on the published TestFlight / Play release. This is the channel a real customer's app subscribes to.

The "Promote to production" button copies the current preview bundle to the production channel — same code, no rebuild.

### Publish to preview

<Steps>
  <Step title="Click Publish OTA Update">
    The card shows the last published bundle's timestamp + commit message (if connected to GitHub). Click **Publish to preview**.
  </Step>

  <Step title="Wait ~30 seconds">
    Hiveku spins up an `eas update` command in a temp directory, with your project's `EXPO_PUBLIC_SUPABASE_*` vars injected. Bundle size shows live as Metro compiles.
  </Step>

  <Step title="Open the result on a real phone">
    Success returns an `https://expo.dev/preview/...` URL and a QR code. Scan with Expo Go on your phone — the new bundle loads. (You need to be signed into the Expo Go app first, but no Hiveku account login is needed in Expo Go itself.)
  </Step>
</Steps>

Most teams keep a `Publish to preview` open in one tab and iterate every few minutes during a focused dev session.

### Promote to production

When a preview build is good, click **Promote to production**. This copies the same bundle to the production channel without rebuilding — atomic switch, no race window.

A user running the published TestFlight or App Store build of your app will pick up this new bundle on their next launch. Older bundles remain available in the channel history for \~7 days in case you need to roll back.

<Tip>
  EAS Update runtime versions matter. If you bumped a native dependency, the OTA can't deliver — the new JS bundle assumes native code that the user's device doesn't have. Hiveku will catch this and force a Build & Ship instead.
</Tip>

## The Native Build & Ship path

This is the path for going to TestFlight + Google Play Internal track. End to end:

### What happens when you click Build & Ship

1. **Pre-flight check** — Hiveku verifies your Apple + Google credentials are connected and recently validated (re-runs validation if the last check was over 24 hours ago).
2. **Project init** — On first build, runs `eas init` to register the EAS project under Hiveku's Expo organization. Stores the resulting `easProjectId` in `expo_config`.
3. **iOS app record auto-create** — Hiveku calls Apple's `POST /v1/bundleIds` and `POST /v1/apps` to register the bundle ID and create the App Store Connect entry. Saves you a manual setup step. (Requires Admin role on your ASC API key — see [Credentials](/mobile/credentials#why-admin-role).)
4. **eas.json synthesis** — A temp `eas.json` is written with your encrypted credentials referenced by path, build profiles for `production`, and submit configs.
5. **Build kickoff** — Two `eas build` commands fire in parallel (one iOS, one Android, if you picked both). Each returns a build ID; the row appears on the Builds page in `in-queue` status.
6. **EAS infrastructure builds the binary** — This is where the 20–30 minutes go. EAS pulls your code, runs `pod install` (iOS) or `gradle assemble` (Android), signs with your credentials, uploads the artifact to their CDN.
7. **EAS webhook fires** — When the build completes, EAS POSTs to Hiveku's `/api/builder/expo/eas-webhook` (HMAC-SHA1 verified). Hiveku flips the build row status to `success` or `failed`.
8. **Auto-submit** (if enabled) — On `success`, Hiveku immediately runs `eas submit` to push the binary to TestFlight (iOS) and your configured Play track (Android). Status flips to `submitted`.
9. **Email notification** — You get an email with the result and a link to the build artifact (or decoded error).

The whole chain runs without human intervention. You can close the browser at step 5 and the email at step 9 will reach you.

### Picking platforms

The Build & Ship card has three options:

* **iOS only** — for when you only have Apple Developer connected
* **Android only** — for Apple-credential issues you're still resolving
* **iOS + Android** (default) — both platforms in parallel

Both platforms run independently. If iOS fails and Android succeeds, the Android build still ships. You'd retry just iOS after fixing the issue.

### Watching a build progress

Each build row shows:

* **Status** — `in-queue` → `in-progress` → `success`/`failed` → `submitted` (if auto-submit on)
* **Started** + **Elapsed** — counters tick live
* **Bundle size** — shown after the artifact uploads (\~12 MB iOS, \~25 MB Android typical)
* **Cancel** button — visible while in-progress

The page auto-refreshes every 15 seconds while any build is in flight. No need to manually reload.

### Email notifications

Two emails per build:

* **Success**: subject `✓ iOS build finished — {App Name}`. Body includes the build URL, artifact size, and submit status.
* **Failure**: subject `✗ iOS build failed — {App Name}`. Body includes the decoded error message and a deeplink to the failed build row in Hiveku.

Sent via Resend to the account email. Configure additional recipients (e.g. a `#mobile-builds` Slack channel via email-to-Slack) in account settings.

### Cancelling a build

While `in-queue` or `in-progress`, the **Cancel** button is enabled on the row. Click it. Hiveku calls EAS's GraphQL `cancelBuild` mutation and flips the row status to `canceled`.

Cancellation refunds your EAS build minute (provided EAS hasn't fully started the build container yet — usually under 30 seconds in queue). Past that, you'll be charged for partial usage but the build still aborts.

## When a build fails

Failures fall into a few buckets, decoded from cryptic Apple/Google output into actionable messages:

| Error category      | Example decoded message                                                    | Likely fix                                                                        |
| ------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Credential          | "App Store Connect rejected the API key — Issuer ID may be wrong"          | Re-verify ASC credentials on Mobile Credentials page                              |
| Code signing        | "ITMS-90013: Provisioning profile doesn't match bundle ID"                 | Usually auto-fixable — re-trigger build (EAS regenerates the profile)             |
| Native dep mismatch | "expo-camera native code doesn't match RN runtime"                         | Update `expo-camera` to a version compatible with your Expo SDK                   |
| Bundle size         | "iOS app exceeds 100 MB compressed"                                        | Audit `assets/` and large native modules                                          |
| Auth gate           | "Apple rejected: missing Privacy Manifest entries for AdSupport.framework" | Add the required entries to `app.json` privacy block                              |
| Android signing     | "Google Play: APK signed with debug keystore"                              | EAS uses managed credentials by default; check `eas.json` profile didn't override |
| Play track          | "Track 'internal' rejected: app version code 1 already used"               | Bump `android.versionCode` in `app.json`                                          |
| API access          | "API key role 'App Manager' insufficient for app creation"                 | Either upgrade to Admin or pre-create the app in ASC                              |

If we know the fix, the row also shows a **Fix with AI** button.

### Fix with AI

Click it. Three things happen:

1. The error message is dropped into the AI chat as your next message, with the relevant build log file attached
2. The AI reads the failing files (e.g. `app.json`, `package.json`, the failing ASC response)
3. The AI proposes a patch — usually a one-or-two-file change — and asks for your confirmation

Hit Accept, then click **Build & Ship** again. The fix is now in your code and the next build runs against the patched version. Subsequent builds reuse the existing EAS project, so kickoff is faster (\~10s instead of 60s).

About 60% of the most common failures (credential mismatches, version bumps, missing privacy manifest entries) are fully resolvable by the AI without you touching the code. The remaining 40% need human judgment but the AI gets you 80% of the way.

## Bundle size warnings

After a successful build, the row shows the artifact size. If it exceeds 75 MB, the chip turns **amber**. If it exceeds 100 MB, **red** — and submit will fail.

Click the chip to see a breakdown:

* Largest native modules in the bundle
* Largest assets (uncompressed PNGs, video files in `assets/`)
* Suggested removals — packages you imported but never reference
* Whether you have `react-native-skia` or other heavyweight packages that pull large binary blobs

Common wins: compress PNGs to WebP (`expo-image` supports it natively), remove unused fonts, kill `react-native-skia` if you only use it for one effect.

## Build history

Below the active builds, the row history shows the last 30 builds for the project. Each row links to:

* The EAS build artifact (downloadable as `.ipa` / `.apk`)
* The full build log (markdown-rendered, syntax-highlighted)
* The submit log (if auto-submit was on)
* The git commit that triggered the build (if connected to GitHub)

You can re-trigger any historical row's exact configuration with **Re-build with this commit** — useful for reproducing an old release for QA.

## GitHub integration

If you've connected your project to GitHub, every Build & Ship also creates a git tag (`mobile-build-{shortHash}-{timestamp}`) on the commit being built. This makes "what code shipped in build 47?" a one-line `git show mobile-build-...` away.

OTA Updates don't create tags — they're too frequent. The bundle's `updateGroupId` is recorded in `builder_deployments` instead.

## Submission tracking

Once a build is `submitted`:

* **iOS**: the build appears in App Store Connect → TestFlight → Builds within 5–15 minutes (Apple processing time). You can add testers in App Store Connect manually, or let TestFlight's auto-distribute push to your Internal Testing group.
* **Android**: the build appears in Play Console → Testing → Internal testing immediately. Available to testers as soon as Google's signature check completes (\~2 minutes).

The build row links directly to the App Store Connect / Play Console entry once submission completes.

## Auto-submit toggle

On Mobile Credentials, each platform has an **Auto-submit** toggle. Default on. If off, builds finish at `success` (you get the artifact URL) but Hiveku doesn't run the submit step. You'd manually `eas submit` from your machine (or click the **Submit now** button on the build row).

Use auto-submit off when:

* A QA engineer reviews build artifacts before pushing to testers
* You're working on a sensitive release that needs manual sign-off
* Your test infra runs against the local artifact before submission

## What's next

<CardGroup cols={2}>
  <Card title="Native Modules" icon="puzzle-piece" href="/mobile/native-modules">
    Decide whether your next change is OTA or Build & Ship before clicking the wrong button.
  </Card>

  <Card title="App Store Assets" icon="sparkles" href="/mobile/app-store-assets">
    AI-generate the icon, screenshots, and listing copy you need to fill out App Store Connect.
  </Card>

  <Card title="Mobile Credentials" icon="key" href="/mobile/credentials">
    Common build failures trace back to credential issues — make sure yours are verified.
  </Card>

  <Card title="Phone-Frame Preview" icon="mobile" href="/mobile/preview">
    Catch most issues in preview before they cost you a 30-minute build.
  </Card>
</CardGroup>
