CI automation with GitHub Actions

This workflow builds your app, uploads a new bundle with the CLI, and can release it to a channel when you set one variable.

1) Add repository secrets and variables

GitHub repository secrets (required):

OTAKIT_SECRET_KEY=otakit_sk_...
OTAKIT_APP_ID=app_...
OTAKIT_SERVER_URL=https://your-otakit.example.com  # optional, only for self-hosted

GitHub repository variables (optional):

OTAKIT_BUILD_DIR=out                 # only if not in capacitor.config.ts webDir
OTAKIT_RELEASE_CHANNEL=staging      # if empty/unset: upload only (no release)

2) Copy this workflow

Create file .github/workflows/otakit.yml:

name: OTA upload

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  upload:
    runs-on: ubuntu-latest
    env:
      OTAKIT_SECRET_KEY: ${{ secrets.OTAKIT_SECRET_KEY }}
      OTAKIT_APP_ID: ${{ secrets.OTAKIT_APP_ID }}
      OTAKIT_SERVER_URL: ${{ secrets.OTAKIT_SERVER_URL }}
      OTAKIT_BUILD_DIR: ${{ vars.OTAKIT_BUILD_DIR }}
      OTAKIT_RELEASE_CHANNEL: ${{ vars.OTAKIT_RELEASE_CHANNEL }}

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - run: npm ci
      - run: npm run build

      - name: Upload bundle (and optionally release)
        run: |
          BASE_VERSION="$(node -p "require('./package.json').version")"
          OTA_VERSION="${BASE_VERSION}+${GITHUB_RUN_NUMBER}.${GITHUB_SHA::7}"

          if [ -n "$OTAKIT_RELEASE_CHANNEL" ]; then
            npx --yes @otakit/cli@latest upload --version "$OTA_VERSION" --channel "$OTAKIT_RELEASE_CHANNEL"
          else
            npx --yes @otakit/cli@latest upload --version "$OTA_VERSION"
          fi

Best practices

  • Pin CLI version after first successful run (replace @latest with a fixed version).
  • Use staging for auto-release and promote to production after validation.
  • Keep OTAKIT_RELEASE_CHANNEL unset if you want upload-only CI and release manually later.
  • Use branch protection so OTA uploads only run from trusted branches.

Related docs: CLI reference and channels and update mode.