playpub
README.md
# playpub
CLI para **automatizar a publicação de apps Android na Google Play Console** — do zero ao teste fechado. Feito pra **monorepos** (N apps por repo) e pra ser **dirigido por IA** (Claude Code) via um servidor **MCP** embutido.
> Você baixa no seu projeto, aponta um arquivo de config (que pode ler do seu `app.json` do Expo) e roda. O que dá pra automatizar via API, ele faz sozinho. O que só existe no console, ele te guia (ou dirige via RPA).
## As 3 camadas da automação do Play Console
A publicação no Play **não é** uma coisa só — ela se divide em 3 camadas, e o `playpub` trata cada uma:
| Camada | O quê | Como o playpub resolve |
|---|---|---|
| **1. API** | Enviar AAB/APK, faixas, testadores, países, ficha da loja (texto + ícone + feature + screenshots), lançamentos | `playpub publish` — Google Play Developer API (`androidpublisher`). **Funciona de verdade.** |
| **2. Só-console (RPA)** | Declarações de "Conteúdo da app" (privacidade, anúncios, IARC, segurança de dados, público-alvo, app access…), categoria/contato e envio pra revisão | `playpub rpa` — Playwright dirigindo o navegador logado. O que não fechar vira `followups` pra um browser MCP. |
| **3. Manual (one-time)** | Criar a **service account** no Google Cloud + **convidá-la** no Play Console | `playpub setup:sa` faz o Cloud e o secret; o convite no Play é o único clique manual (o Google não tem API pra isso). |
## Instalação
```bash
# global
npm i -g playpub
# ou dentro do seu projeto (pra customizar)
git clone https://github.com/DIEGOHORVATTI/playpub && cd playpub
npm i && npm run build && npm link
```
## Pré-requisitos (CLIs)
O `playpub doctor` checa isto:
- **node** ≥ 18 — runtime
- **gcloud** — cria projeto GCP + service account (`setup:sa`) · [instalar](https://cloud.google.com/sdk/docs/install)
- **gh** (GitHub CLI, autenticado) — grava a chave da SA como secret e dispara workflows · [instalar](https://cli.github.com)
- **java** (opcional) — assinar o AAB localmente, se não assinar no CI
## Começando
```bash
playpub init # cria playpub.config.json (detecta apps/* de monorepo Expo)
playpub doctor # checa CLIs + valida a config
playpub setup:sa --repo SEU_USER/SEU_REPO # cria a service account e grava o secret
# → depois: convide o e-mail da SA no Play Console (o comando te diz qual)
playpub publish --app unitv --status draft # sobe o AAB + ficha pra faixa alpha
playpub links --all # imprime os links de opt-in e de loja
```
## Config (monorepo)
Um `playpub.config.json` descreve **N apps**. Cada app pode herdar de `defaults` e ler `packageName`/versão de um `app.json` do Expo. Veja [`playpub.config.example.json`](./playpub.config.example.json).
```jsonc
{
"serviceAccountKey": "PLAY_SERVICE_ACCOUNT_JSON", // arquivo .json OU nome de env
"defaults": { "track": "alpha", "status": "draft" },
"apps": {
"unitv": {
"expoAppJson": "apps/unitv/app.json",
"aab": "apps/unitv/android/app/build/outputs/bundle/release/app-release.aab",
"listing": { "pt-BR": { "title": "…", "shortDescription": "…", "fullDescription": "…",
"icon": "…/icon-512.png", "featureGraphic": "…/feature-1024x500.png",
"phoneScreenshots": ["…/1.png", "…/2.png"] } },
"testers": { "countries": ["BR"], "emails": ["tester@gmail.com"] }
},
"nexatv": { "expoAppJson": "apps/nexatv/app.json", "aab": "…" }
}
}
```
Seleção de app: `--app <nome>` ou `--all`. Se o repo tem só 1 app, ele é o default.
## Camada 2 — RPA (declarações só-console)
O que não tem API, o `playpub rpa` faz dirigindo o navegador **já logado** no Play Console (Playwright). Preenche as 10 declarações do "Conteúdo da app", categoria + contato, e envia pra revisão — espelhando o fluxo validado à mão.
```bash
# 1x: instale o playwright (dependência opcional) e logue com janela
npm i -D playwright
playpub rpa --app unitv --phase declarations # abre o Chrome; faça login no Console na 1ª vez
# fases: declarations | store | submit | all (default all)
playpub rpa --app unitv --phase store # categoria + detalhes de contato
playpub rpa --app unitv --phase submit # "Enviar N alterações para revisão"
playpub rpa --app unitv --dry-run # navega e valida, sem clicar Guardar/Enviar
```
Config: preencha `developerId` (topo) e, por app, `rpa.consoleAppId` + as respostas (veja o bloco `rpa` em [`playpub.config.example.json`](./playpub.config.example.json)). O login é reaproveitado via `--user-data-dir` (default: um dir no tmp). Inclui a **Classificação de conteúdo (IARC)**: preencha `rpa.iarc` (email, categoria, `inAppPurchases`, e `yes[]` pra perguntas que devem ser "Sim"); o resto vai "Não".
### Fallback: "CLI → IA no navegador" (browser MCP)
O RPA determinístico cobre o caminho comum, mas formulários mudam. O que ele **não** conseguir fechar volta em `followups` — uma lista de `{ step, url, hint, values }`. A ideia é ser 100% CLI e, no que falhar, deixar um **agente de browser MCP** (ex.: `claude-in-chrome`) terminar: abra a `url`, siga o `hint`, use os `values`. Na CLI aparece assim:
```
✗ rpa:all unitv
↳ browser-MCP [classificação-iarc]: Abra "Classificação de conteúdo" → Iniciar questionário: email…
https://play.google.com/console/u/0/developers/<dev>/app/<app>/app-content/overview
```
Via MCP (`playpub_rpa`), esses `followups` vêm no JSON — a IA que orquestra pega cada um e executa no seu próprio browser MCP. Dica: rode com `--dry-run` primeiro pra ver a navegação antes de deixar salvar.
## Uso por IA (MCP)
O `playpub` sobe um **servidor MCP** que expõe os comandos como tools (`playpub_doctor`, `playpub_publish`, `playpub_rpa`, `playpub_links`, `playpub_setup_sa`, `playpub_init`). Toda tool devolve um `Result` em JSON. Registre no seu cliente MCP:
```jsonc
// .mcp.json / config do Claude Code
{ "mcpServers": { "playpub": { "command": "playpub", "args": ["mcp"] } } }
```
Ou pela CLI, tudo aceita `--json` pra saída estruturada e exit code determinístico (`0` ok, `1` erro).
## CI/CD (GitHub Actions)
Tem um **workflow de referência** pronto em [`templates/github-actions-publish.yml`](./templates/github-actions-publish.yml): faz build do AAB, assina em **cadeia única** (via `android.injected.signing.*` — reassinar depois faz o Play recusar com _"multiple certificate chains"_), e publica com `playpub publish`. Copie pra `.github/workflows/` e ajuste o passo de build ao seu app.
Secrets: `ANDROID_KEYSTORE_BASE64`, `ANDROID_KEYSTORE_PASSWORD`, `ANDROID_KEY_ALIAS`, `ANDROID_KEY_PASSWORD` e `PLAY_SERVICE_ACCOUNT_JSON` (esse o `playpub setup:sa` cria e grava).
## Comandos
| Comando | Camada | O quê |
|---|---|---|
| `init` | — | cria a config (detecta monorepo Expo) |
| `doctor` | — | checa CLIs obrigatórias + valida a config |
| `setup:sa` | 3 | cria projeto GCP + SA + chave + secret no GitHub |
| `publish` | 1 | sobe AAB + ficha da loja pra faixa (API) |
| `rpa` | 2 | declarações só-console + categoria/contato + enviar pra revisão (Playwright) |
| `links` | 1 | links de opt-in e de loja |
| `mcp` | — | sobe o servidor MCP (stdio) |
## Segurança
- A chave da service account **nunca** é commitada. O `.gitignore` cobre `*service-account*.json`, `play-sa*.json`, `.env*`. O `setup:sa` gera a chave num tempdir e **apaga** depois de gravar o secret.
- Guarde a chave só como **secret do GitHub** (ou variável de ambiente do CI).
## Roadmap
- [x] `rpa` completo (Playwright) — declarações (incl. IARC) + loja + envio pra revisão
- [x] Fallback `followups` pra browser MCP no que o RPA não fecha
- [ ] Import/Export CSV da Segurança de dados
- [ ] `create-app` (criação do 1º app via RPA)
- [ ] `promote` (mover de faixa) e `rollout` (percentual)
- [ ] schema.json publicado + validação forte da config
## Licença
MIT © Diego Horvatti
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues