Documentation

Tokens and CI

Configure identity, targets and build tools to automate the release you already verified locally.

Updated 2026-09-14

On this page

Verify a local release first

CI automates the first-release workflow. Verify the same baseline, bundle command and targets locally before adding automation so build and authentication issues are not mixed.

Create a publishing token

Open API Key in the console sidebar (/settings/tokens). Select the required permissions, application scope and expiration. The full value appears once; save it directly to CI Secrets.

A token is constrained by its selected permissions and application scope, not equivalent to an unrestricted account session. The CLI reads PAKTA_API_TOKEN and sends x-api-token; interactive login uses a session token. The SDK uses only the public appKey.

Prepare release configuration

Commit the app's package.json, lockfile, update.json containing public identifiers only, and targets.json. Generate update.json locally with selectApp; do not rely on selection prompts in CI.

targets.json · replace with verified production targets
[
  { "channel": "default", "packageVersion": "1.0.0", "rollout": 10 }
]

Match the local Node, Metro/Hermes and platform dependencies. Choose a runner capable of the same commands for iOS, HarmonyOS or custom Android builds; a generic Linux image is not always enough.

GitHub Actions example

This is a steps fragment for an existing job, not a complete workflow. It assumes checkout, Node and the required toolchain are configured, the working directory is the app root, and the CLI is installed at the same version used locally:

Steps in your existing workflow
- name: Install locked dependencies
  run: |
    npm ci
    npm install -g rn-update-cli@1.1.0

- name: Verify identity and targets
  env:
    PAKTA_API_TOKEN: ${{ secrets.PAKTA_API_TOKEN }}
    NO_INTERACTIVE: 'true'
  run: |
    pakta me
    pakta publish .pakta/output/android.ppk --platform android --name "$GITHUB_RUN_ID" --targets targets.json --dryRun --no-interactive

- name: Bundle and publish
  env:
    PAKTA_API_TOKEN: ${{ secrets.PAKTA_API_TOKEN }}
    NO_INTERACTIVE: 'true'
  run: |
    pakta bundle --platform android --output .pakta/output/android.ppk --no-interactive
    pakta publish .pakta/output/android.ppk --platform android --name "$GITHUB_RUN_ID" --targets targets.json --sourcemap .pakta/intermedia/android/index.bundlejs.map --no-interactive

The run blocks use Bash. Add --expo to bundling for Expo; keep custom sourcemap paths consistent. For self-hosting, add your RNU_SERVICE_URL to both steps' environment.

Non-interactive release and recovery

  • Explicitly provide --targets, a native --packageId, or --packageVersion instead of selection prompts.

  • --dryRun does not upload, create channels or publish; it is not a successful release.

  • Retain the returned update-package packageId and all deploymentIds. If a failure supplies retryable deployment IDs, resume those exact targets:

bash
pakta publish --deploymentIds DEPLOYMENT_ID_1,DEPLOYMENT_ID_2 --platform android --no-interactive

Replace the placeholder IDs; do not guess unrelated drafts. Serialize deployments by application and target so parallel jobs do not replace each other. Archive the package, map, commit and publishing output from the same build.

Completion check

The pipeline exits successfully, the console shows the expected active targets, and a matching device activates and confirms health. Upload completion alone is insufficient; verify in analytics.

Token maintenance

Issue a separate token per pipeline; revoke unused tokens and rotate before expiration. Inject through CI Secrets, never update.json, the app or logs. On authentication failure, check expiration, revocation, scope and permissions, then verify identity with me.

CLI · Channel publishing · Production checklist.