Se você está construindo um Add-on do Google Workspace, o runtime mora num lugar meio estranho. O Apps Script é um servidor onde você não consegue dar SSH e uma UI para a qual você não consegue mandar arquivos via scp — toda alteração tem que passar pelo editor do Google ou pela API deles. A ponte entre o seu repositório e esse ambiente é o clasp (Command Line Apps Script), e quando você embrulha tudo isso em GitHub Actions, fazer deploy vira um simples git push.
Este post percorre a pipeline inteira de ponta a ponta: instalar o clasp, configurar o arquivo que liga seu repositório a um projeto específico do Apps Script e, no fim, um workflow do GitHub Actions que joga cada commit do main direto no Apps Script.
O Que é o clasp
O clasp é uma pequena CLI em Node criada pelo Google que conversa com a API do Apps Script. O modelo mental é simples:
- Seu projeto do Apps Script vive numa URL como
script.google.com/.../edite é identificado por umscriptId. clasp pushfaz upload dos arquivos.gs,.htmleappsscript.jsonde um diretório local para esse projeto, substituindo a cópia no servidor.clasp pullfaz o inverso — útil quando alguém editou código pelo editor web do Apps Script e você quer trazer essas alterações de volta para o git.clasp deploycorta uma deployment versionada e nomeada — é justamente essa que a loja de add-ons e seus usuários finais realmente executam. Sem ela,clasp pushsó atualiza a versão@HEAD, que ninguém além do desenvolvedor enxerga.
É isso. Sem build system, sem opiniões sobre o seu código — só um mecanismo de sincronização entre uma pasta no disco e um projeto de script na nuvem do Google.
Passo 1 — Instalar o clasp
O clasp é um pacote Node global. Garanta que você tem Node 20+ instalado e rode:
npm install -g @google/clasp
clasp --version
Antes de o clasp conseguir falar com a sua conta, você precisa habilitar a Apps Script API para o seu usuário Google. Vá em script.google.com/home/usersettings e ligue a Google Apps Script API. É um botão único por conta — fácil de esquecer, e o clasp aborta com um erro críptico se você pular essa etapa.
Agora faça login:
clasp login
Uma janela do navegador se abre e te leva pelo fluxo OAuth. Quando termina, o clasp grava suas credenciais em ~/.clasprc.json. Vamos voltar a esse arquivo quando configurarmos o CI.
Passo 2 — Pegar o scriptId
Todo projeto do Apps Script tem um scriptId único — é por ele que o clasp sabe para qual projeto fazer push. Existem duas formas de obter um.
Se o projeto ainda não existe, crie pela linha de comando:
mkdir my-addon && cd my-addon
clasp create --type standalone --title "My Add-on"
--type pode ser standalone, sheets, docs, slides, forms ou webapp. Escolha o que combina com o seu add-on. O clasp cria o projeto do lado do Google e gera um .clasp.json com o novo scriptId já preenchido.
Se o projeto já existe (você criou no editor do Apps Script ou alguém compartilhou com você), abra-o em script.google.com e olhe a URL:
https://script.google.com/d/1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOp/edit
└────────────────────── scriptId ──────────────────────┘
O trecho longo de letras e números entre /d/ e /edit é o seu scriptId. Você também encontra ele dentro do editor do Apps Script em Configurações do projeto → IDs.
Passo 3 — Configurar o .clasp.json
O .clasp.json é o arquivo que prende seu diretório local a um projeto específico do Apps Script. Ele fica na raiz do repositório:
// .clasp.json
{
"scriptId": "1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOp",
"rootDir": "./src"
}
Dois campos, ambos importantes:
scriptId— o projeto para onde o clasp deve fazer push. Cole o que você obteve no Passo 2.rootDir— a pasta local que o clasp deve tratar como fonte do projeto. Tudo dentro dela é enviado, tudo fora é ignorado. Se você omiterootDir, o clasp usa o diretório atual, o que normalmente significa tentar enviar suas pastasnode_modulese.git. Sempre defina explicitamente.
Alguns campos opcionais que você pode encontrar:
scriptExtensionsehtmlExtensionspermitem customizar quais extensões o clasp trata como código de servidor ou HTML.filePushOrderforça certos arquivos a serem enviados antes de outros — só relevante se você tiver dependências de ordem de carregamento entre arquivos.gs.
Para a maioria dos projetos, a versão de dois campos acima é suficiente.
Passo 4 — Organizar os Arquivos
O clasp não se importa como os arquivos chegaram em rootDir. Desde que a pasta contenha arquivos válidos do Apps Script, ele vai enviar. Um layout mínimo é assim:
my-addon/
.clasp.json
.claspignore // opcional — arquivos a ignorar no push
src/
appsscript.json // manifesto: scopes, runtime, configuração do add-on
Code.gs // suas funções do servidor
Sidebar.html // qualquer HTML servido via HtmlService
Três coisas para saber sobre os tipos de arquivo:
- Arquivos
.gssão código de servidor do Apps Script. O clasp converte de forma transparente para e a partir do formato nativo do editor. - Arquivos
.htmlsão templates servidos viaHtmlService.createHtmlOutputFromFile(). appsscript.jsoné o manifesto do projeto. Declara escopos OAuth, a versão do runtime (V8), o fuso horário e — para add-ons — as entradas de menu e os triggers que o usuário vê. O clasp se recusa a fazer push sem ele.
Se você tem arquivos dentro de rootDir que não devem ser enviados (scripts de build, READMEs, qualquer coisa que não seja .gs/.html/appsscript.json), adicione um .claspignore ao lado do .clasp.json:
**/**
!appsscript.json
!**/*.gs
!**/*.html
Esse padrão diz: "ignore tudo, depois libere apenas os tipos de arquivo que o Apps Script realmente entende."
Com o layout pronto, você consegue fazer deploy local com dois comandos:
clasp push -f
clasp deploy --description "first version"
A flag -f pula a confirmação interativa de "manifesto alterado" — pode ficar ligada sempre, e mais tarde no CI ela vira obrigatória.
Passo 5 — Autenticar o clasp no CI
Os deploys locais funcionam porque o clasp login deixou credenciais em ~/.clasprc.json. Os runners do GitHub Actions não têm esse arquivo, e tampouco conseguem rodar um fluxo de navegador, então a gente entrega as credenciais direto via secret.
O arquivo se parece com isto:
{
"token": {
"access_token": "ya29....",
"refresh_token": "1//0g....",
"scope": "https://www.googleapis.com/auth/script.projects ...",
"token_type": "Bearer",
"expiry_date": 1736000000000
},
"oauth2ClientSettings": {
"clientId": "xxxxxxxxxxxx.apps.googleusercontent.com",
"clientSecret": "GOCSPX-xxxxxxxxxxxx",
"redirectUri": "http://localhost"
},
"isLocalCreds": false
}
O refresh_token é a peça-chave — enquanto ninguém revogar a permissão, o clasp consegue gerar tokens de acesso novos por meses.
Para guardar no GitHub:
- Numa máquina, rode
clasp login(pule se já fez no Passo 1). - Rode
cat ~/.clasprc.jsone copie a saída inteira. - No seu repo no GitHub: Settings → Secrets and variables → Actions → New repository secret.
- Name:
CLASPRC_JSON. Value: o JSON completo que você acabou de copiar.
💡 Dica: Gere esse token a partir de uma conta Google dedicada que seja dona do projeto do Apps Script — não da sua conta pessoal. Se um desenvolvedor sair da equipe, você não precisa rotacionar nada.
Passo 6 — O Workflow do GitHub Actions
Agora a recompensa. Coloque isto em .github/workflows/deploy.yml:
name: Deploy Apps Script
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install clasp
run: npm i -g @google/clasp
- name: Restore clasp credentials
run: echo '${{ secrets.CLASPRC_JSON }}' > ~/.clasprc.json
- name: Push to Apps Script
run: clasp push -f
- name: Create a versioned deployment
run: |
DESC="ci-${GITHUB_SHA::7}-$(date -u +%Y%m%d%H%M)"
clasp deploy --description "$DESC"
O que cada parte está fazendo:
on: push: branches: [main]— todo merge nomaindispara um deploy.workflow_dispatchadiciona um botão "Run workflow" na aba Actions para reexecuções manuais.environment: production— opt-in num GitHub Environment. Se você configurar reviewers obrigatórios nele, todo deploy espera a aprovação humana antes de prosseguir. Vale muito a pena para qualquer add-on com usuários reais.- Restore clasp credentials — escreve o secret de volta em
~/.clasprc.jsonpara o clasp encontrar onde ele espera. Não usecatouechono secret em outro lugar; o GitHub só mascara automaticamente quando o secret é usado via${{ secrets.* }}. clasp push -f— envia tudo derootDirpara o projeto do Apps Script. O-fé obrigatório no CI; sem ele, o prompt de "manifesto alterado" trava o runner.clasp deploy --description— corta uma nova deployment versionada. A descrição inclui o SHA curto e um timestamp para você rastrear qualquer deployment até o commit exato. Esse é o passo que a maioria esquece — sem ele,clasp pushsó atualiza o@HEAD, e os usuários instalados nunca veem a mudança.
Faça commit do workflow, dê push e veja o check verde. Daqui pra frente, fazer deploy é só git merge.
O Que Não Fazemos (e Por Quê)
Não comitamos o ~/.clasprc.json no repositório. Ele contém um refresh token que, na prática, é uma credencial de longa duração. Lugar dele é em GitHub Secrets, nunca no controle de versão.
Não compartilhamos uma única conta Google entre o time. O secret CLASPRC_JSON vem de uma conta dedicada que é dona do projeto do Apps Script. Contas pessoais mudam; a conta de deploy não.
Não rodamos testes nesse workflow. O runtime do Apps Script é diferente o suficiente do Node para tornar testes unitários significativos algo difícil. A gente roda testes de lógica num workflow separado, contra um port em Node do código compartilhado, e confia num smoke test manual depois de cada deploy.
A Recompensa
Antes desse setup, fazer deploy era: puxar o último, torcer pra o token do clasp não ter expirado, rodar clasp push, lembrar de rodar clasp deploy com uma descrição decente, torcer pra você não ter esquecido o -f. Cinco passos, cinco lugares para tropeçar.
Agora: merge no main, espera o check verde, abre o add-on. O Apps Script deixa de ser um caso especial — ele é só mais um destino de deploy atrás do mesmo workflow git que tudo o mais que você publica.
Se você mantém um Add-on do Workspace e ainda faz push do laptop, a migração é um trabalho de uma tarde. A parte mais difícil é encontrar o ~/.clasprc.json.
Tem um workflow personalizado em mente?
A gente constrói add-ons sob medida do Google Workspace adaptados aos seus processos de negócio. Escreva para support@8apps.co e vamos começar.