Skip to content

Como publicar updates OTA pelo GitHub Actions ​

Atualizado em outubro de 2026.

Resposta curta: crie um token de deploy só para o CI, salve como segredo PIPANOAR_TOKEN no repositório e rode npx hot-updater deploy num workflow do GitHub Actions a cada push na main. Cada release fica ligada a um commit, com a mensagem dele, e o token sai das máquinas das pessoas. Comece com rollout baixo (-r 10) e aumente pelo painel depois de olhar os crashes.

Este artigo assume que o app já está configurado com o Pipa no Ar. Se ainda não está, siga o guia rápido ou rode npx @pipanoar/init.

Por que publicar pelo CI ​

  • Rastreabilidade. A release nasce de um commit da main, com a mensagem do commit. Ninguém publica do próprio computador um código que não passou por revisão.
  • Menos segredos espalhados. O token de deploy vive nos segredos do repositório, não no .env de cada pessoa.
  • Repetível. O mesmo comando, com a mesma versão do Node e das dependências, todo dia.

1. Crie um token só para o CI ​

  1. No painel, abra a organização e vá em Tokens de deploy.
  2. Crie um token com escopo Deploy. Se o repositório é de um app só, limite o token a esse app.
  3. Copie o valor (começa com pn_). Ele aparece uma vez só.
  4. No GitHub, em Settings → Secrets and variables → Actions, crie o segredo PIPANOAR_TOKEN com esse valor.

A CLI lê o token da variável PIPANOAR_TOKEN, então não é preciso mudar o hot-updater.config.ts. Mais sobre credenciais em Tokens e API keys.

2. O workflow ​

Este exemplo publica no canal production a cada push na main, para 10% dos aparelhos:

yaml
# .github/workflows/ota.yml
name: Update OTA

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - name: Publicar iOS e Android
        env:
          PIPANOAR_TOKEN: ${{ secrets.PIPANOAR_TOKEN }}
        run: |
          npx hot-updater deploy -p ios -r 10
          npx hot-updater deploy -p android -r 10

A mensagem da release vem do último commit. Para usar outra, passe -m "texto". Se o projeto usa yarn, pnpm ou bun, troque o cache e o npm ci pelo equivalente.

3. Variações úteis ​

Publicar no beta primeiro ​

Uma branch beta que publica no canal beta:

yaml
on:
  push:
    branches: [beta]

# ...
        run: |
          npx hot-updater deploy -p ios -c beta
          npx hot-updater deploy -p android -c beta

Quando estiver bom, promova a mesma release para production pelo painel ou com npx hot-updater bundle promote <id> -t production. A release promovida é exatamente o bundle testado, sem gerar outro.

Disparar à mão, escolhendo o rollout ​

Com workflow_dispatch, o deploy roda pelo botão Run workflow do GitHub, com a porcentagem como entrada:

yaml
on:
  workflow_dispatch:
    inputs:
      rollout:
        description: "Porcentagem de aparelhos (1 a 100)"
        default: "10"

# ...
        run: |
          npx hot-updater deploy -p ios -r ${{ inputs.rollout }}
          npx hot-updater deploy -p android -r ${{ inputs.rollout }}

Uma plataforma por job ​

Se o build de uma plataforma demora, separe em dois jobs com matrix, cada um com o seu -p. Assim uma falha no Android não segura o iOS.

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        platform: [ios, android]
    steps:
      # checkout, setup-node e npm ci como acima
      - run: npx hot-updater deploy -p ${{ matrix.platform }} -r 10
        env:
          PIPANOAR_TOKEN: ${{ secrets.PIPANOAR_TOKEN }}

4. Depois do deploy ​

  • Olhe o Insights. Com o plugin insights() no app, o painel mostra adoção e taxa de crash por release.
  • Aumente o rollout aos poucos, pelo painel ou com a automação Liberar aos poucos, que sobe os degraus e desativa a release se a taxa de crash passar do limite. Ver Rollout automático.
  • Avise o time. As notificações da organização mandam cada deploy para um canal do Slack ou do Discord, ou para um webhook seu.

Rollout gradual e automação estão nos planos pagos, a partir do Starter. No Free, a release vai para 100% dos aparelhos do canal, então vale publicar no beta antes.

Cuidados ​

  • Código nativo não vai pelo ar. Se o commit muda o iOS ou o Android (um módulo nativo novo, uma permissão), ele precisa de uma build nova na loja. O OTA leva só o JavaScript e os assets.
  • Um token por pipeline. Se um token vazar, revogue só ele no painel. Para scripts que só consultam releases, use um token de escopo Leitura.
  • Não coloque o token no app. O app usa a API key, que só lê updates. O token de deploy publica releases.
  • Assinatura funciona igual no CI. Com signing: true no config, a CLI pede as assinaturas com o mesmo token, sem chave privada no runner. Ver Como assinar bundles OTA.

Uma action oficial ​

A action oficial pipanoar/deploy-action faz os mesmos passos numa linha: valida os inputs, instala o Node e as dependências (detecta Bun, pnpm, Yarn ou npm pelo lockfile), roda o deploy e escreve um resumo no job.

yaml
      - uses: actions/checkout@v4
      - uses: pipanoar/deploy-action@v1
        with:
          token: ${{ secrets.PIPANOAR_TOKEN }}
          channel: production
          rollout: 10

O workflow manual acima continua valendo para quem quer controlar cada passo.

Perguntas frequentes ​

Preciso de runner macOS para publicar no iOS? O deploy OTA gera só o bundle JavaScript, sem compilar o app nativo, e o exemplo do guia roda em ubuntu-latest para as duas plataformas. A build nativa para a App Store continua precisando de macOS.

O CI pode desativar uma release? Pode, com npx hot-updater bundle disable <id>, usando um token de escopo Deploy. Na maioria dos casos, desativar pelo painel ou pela automação é mais rápido.

O guia de referência está em Deploy pelo CI, e todos os comandos e opções, em Comandos da CLI.