@otalan/cli 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to `@otalan/cli` will be documented in this file.
4
4
 
5
+ ## 1.2.1 - 2026-05-11
6
+
7
+ ### Changed
8
+
9
+ - Exclude source map files (`*.map`) from Capacitor and Expo bundle ZIPs by default and print the omitted file count.
10
+ - Clarify direct-upload wording around opaque `uploadUrl` values.
11
+ - Cancel the reserved ingest when the direct object-storage upload fails before completion.
12
+ - Add `otalan pause` and `otalan resume` commands for active bundle rollout control.
13
+
14
+ ## 1.2.0 - 2026-05-08
15
+
16
+ ### Changed
17
+
18
+ - Switch `otalan publish` to the direct-upload release contract: create JSON upload metadata, upload the ZIP to the returned opaque `uploadUrl`, complete the ingest, then poll validation.
19
+ - Stream the local ZIP through Bun's disk-backed file body during direct uploads instead of loading the full archive into memory.
20
+ - Send the full generated Otalan Expo satellite manifest as `expoManifest` during publish instead of only raw Expo config.
21
+ - Use the Expo `runtimeVersion` as the release `nativeVersion` sent to the API, matching the current Expo update matching contract.
22
+ - Use the release bundle `publishedAt` timestamp for bundle lists, status summaries, rollback prompts, and published bundle ID hints.
23
+
5
24
  ## 1.1.1 - 2026-05-07
6
25
 
7
26
  ### Changed
package/README.md CHANGED
@@ -105,7 +105,7 @@ otalan bundle --target expo --platform ios --bundle-id 1.0.5
105
105
  otalan publish --channel production
106
106
  ```
107
107
 
108
- `otalan bundle --target expo` runs `bunx expo export` itself, exports into a temporary project-local `.otalan/expo-export-*` folder, packages the exported JS bundle and assets, and stores the resolved Expo config in the Otalan manifest for publish. You do not need to create a `dist/` or `www/` folder before running it.
108
+ `otalan bundle --target expo` runs `bunx expo export` itself, exports into a temporary project-local `.otalan/expo-export-*` folder, packages the exported JS bundle and assets, and stores the generated Otalan satellite manifest for publish. You do not need to create a `dist/` or `www/` folder before running it.
109
109
  `otalan publish` waits for server-side validation to finish before it returns.
110
110
 
111
111
  ## CI/CD Usage
@@ -222,7 +222,7 @@ Example project config:
222
222
  }
223
223
  ```
224
224
 
225
- `otalan.config.json` only links the repo to an Otalan project/app. Bundle and release targeting data such as `target`, `platform`, `nativeVersion`, and `bundleId` live in `.otalan/bundle/manifest.json`.
225
+ `otalan.config.json` only links the repo to an Otalan project/app. Bundle and release targeting data such as `target`, `platform`, `nativeVersion`, `runtimeVersion`, and `bundleId` live in `.otalan/bundle/manifest.json`.
226
226
 
227
227
  ## Command Reference
228
228
 
@@ -335,8 +335,9 @@ Current behavior:
335
335
  - pass `--input-dir <path>` to package a different Capacitor web output folder
336
336
  - Expo runs `bunx expo export --platform <platform>` into a temporary project-local `.otalan/expo-export-*` folder
337
337
  - Expo does not require a prebuilt `dist/` or `www/` folder
338
- - Expo stores the resolved Expo app config in `.otalan/bundle/manifest.json` so publish can forward it for `extra.expoClient`
338
+ - Expo stores the generated Otalan satellite manifest in `.otalan/bundle/manifest.json`, including `launchAsset`, `assets`, `runtimeVersion`, `bundleId`, and `expoConfig`
339
339
  - both outputs produce a ZIP plus `manifest.json`
340
+ - source map files (`*.map`) are omitted from bundle ZIPs by default; the CLI prints the omitted file count when any are skipped
340
341
  - `--platform` is required so the CLI exports the selected platform and resolves the correct native/runtime version
341
342
 
342
343
  Native version defaults:
@@ -346,6 +347,7 @@ Native version defaults:
346
347
  - Capacitor Android reads `versionName` from `android/app/build.gradle` or `build.gradle.kts`
347
348
  - Expo reads the selected platform version from Expo config and falls back to the top-level Expo `version`
348
349
  - Expo runtimeVersion reads `--runtime-version`, Expo export metadata, or Expo config runtimeVersion policies/strings; if none are present, the CLI falls back to the resolved native version
350
+ - Expo publishes use `runtimeVersion` as the Otalan release `nativeVersion` because Expo update checks send `expo-runtime-version`
349
351
  - `--native-version` overrides auto-detection
350
352
 
351
353
  For Expo projects, the recommended app config is:
@@ -400,7 +402,7 @@ otalan bundle --target expo --platform ios --bundle-from-package
400
402
 
401
403
  Publishes the current bundle output with rollout metadata.
402
404
 
403
- `otalan publish` uses the `bundleId`, `platform`, and `nativeVersion` already stored in `.otalan/bundle/manifest.json`. To release `1.0.5`, set it when you run `otalan bundle --bundle-id 1.0.5`.
405
+ `otalan publish` uses the `bundleId`, `platform`, and release version stored in `.otalan/bundle/manifest.json`. Capacitor uses `nativeVersion`; Expo uses `runtimeVersion`. To release `1.0.5`, set it when you run `otalan bundle --bundle-id 1.0.5`.
404
406
 
405
407
  Current behavior:
406
408
 
@@ -412,8 +414,10 @@ Current behavior:
412
414
  - `--rollout-percent` accepts an integer from `0` to `100`
413
415
  - `--optional` marks the update as non-mandatory
414
416
  - `--release-notes` attaches release notes to the published bundle
415
- - Expo publish forwards the stored Expo app config when present
417
+ - Expo publish forwards the full generated Otalan satellite manifest when present
418
+ - Expo publish sends `runtimeVersion` as the API `nativeVersion` and normalizes the serialized `expoManifest.nativeVersion` to the same value for server validation
416
419
  - Otalan validates the release ZIP before the publish completes
420
+ - active rollouts can be paused and resumed later without changing the selected bundle
417
421
 
418
422
  Default flow:
419
423
 
@@ -433,7 +437,16 @@ Optional update:
433
437
  otalan publish --channel production --optional
434
438
  ```
435
439
 
436
- This uses `POST /v1/releases/create` and waits for `GET /v1/releases/ingests/:id` to reach `ready` before returning success.
440
+ This uses the direct-upload release flow:
441
+
442
+ 1. `POST /v1/releases/create` with JSON metadata for the release and local ZIP, including `expoManifest` for Expo bundles
443
+ 2. `PUT` the ZIP bytes directly to the returned opaque `uploadUrl` with the exact returned `Content-Type`
444
+ 3. `POST /v1/releases/ingests/:id/complete`
445
+ 4. poll `GET /v1/releases/ingests/:id` until the ingest reaches `ready` or `failed`
446
+
447
+ If the direct object-storage upload fails before completion, the CLI calls `POST /v1/releases/ingests/:id/cancel` so the reserved ingest does not block a retry.
448
+
449
+ The ZIP is opened as a disk-backed `Bun.file` and passed directly to the returned `PUT` upload URL; `otalan publish` does not load the full archive into memory first.
437
450
 
438
451
  If validation fails, `otalan publish` exits non-zero and prints the ingest failure reason when the API provides one. This makes the command safe to use directly in CI/CD pipelines.
439
452
 
@@ -441,6 +454,8 @@ If validation fails, `otalan publish` exits non-zero and prints the ingest failu
441
454
 
442
455
  Lists remote bundles for the current app so you can choose a bundle for rollback or rollout operations.
443
456
 
457
+ Remote bundle tables display the API `publishedAt` timestamp, not the bundle row `createdAt` timestamp.
458
+
444
459
  Default resolution order:
445
460
 
446
461
  1. `--native-version`
@@ -462,10 +477,32 @@ Reactivates an older bundle for the same tuple.
462
477
  otalan rollback --bundle-id 1.0.0-web.1 --platform ios --channel production
463
478
  ```
464
479
 
480
+ ### `otalan pause`
481
+
482
+ Pauses delivery of the currently active bundle for the selected release tuple.
483
+
484
+ `pause` uses the same native-version default order as `bundles`. The active bundle remains selected, but new OTA checks stop receiving it until you resume the rollout.
485
+
486
+ ```bash
487
+ otalan pause --platform ios --channel production
488
+ ```
489
+
490
+ ### `otalan resume`
491
+
492
+ Resumes delivery of the currently active bundle for the selected release tuple.
493
+
494
+ `resume` uses the same native-version default order as `bundles`.
495
+
496
+ ```bash
497
+ otalan resume --platform ios --channel production
498
+ ```
499
+
465
500
  ### `otalan status`
466
501
 
467
502
  Shows the active bundle for the selected release tuple.
468
503
 
504
+ The active bundle summary displays `publishedAt` as `Published at`.
505
+
469
506
  `status` also uses the same native-version default order as `bundles`.
470
507
 
471
508
  ```bash
@@ -487,7 +524,7 @@ otalan status --platform ios --channel production
487
524
  }
488
525
  ```
489
526
 
490
- ### Expo Manifest
527
+ ### Expo Satellite Manifest
491
528
 
492
529
  ```json
493
530
  {
@@ -510,6 +547,8 @@ otalan status --platform ios --channel production
510
547
  }
511
548
  ```
512
549
 
550
+ For Expo publishes, `otalan publish` serializes this file and sends it to `/v1/releases/create` as `expoManifest`.
551
+
513
552
  ## Maintainer Release Checklist
514
553
 
515
554
  Before publishing a public package release: