# Publicando um Add-on do Google Workspace com clasp e GitHub Actions

> Um guia passo a passo para fazer deploy de add-ons do Apps Script direto de um git push — instale o clasp, configure o .clasp.json e deixe o GitHub Actions cuidar do resto.

- Source: https://www.8apps.co/pt/blog/publicar-addon-google-workspace-clasp-github-actions
- Markdown: https://www.8apps.co/pt/blog/publicar-addon-google-workspace-clasp-github-actions.md
- Published: 2026-05-07
- Author: Equipe 8apps
- Language: pt

---
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/.../edit` e é identificado por um **`scriptId`**.
- `clasp push` faz upload dos arquivos `.gs`, `.html` e `appsscript.json` de um diretório local para esse projeto, substituindo a cópia no servidor.
- `clasp pull` faz 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 deploy` corta uma deployment versionada e nomeada — é justamente essa que a loja de add-ons e seus usuários finais realmente executam. Sem ela, `clasp push` só 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:

```bash
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](https://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:

```bash
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:

```bash
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:

```json
// .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ê omite `rootDir`, o clasp usa o diretório atual, o que normalmente significa tentar enviar suas pastas `node_modules` e `.git`. Sempre defina explicitamente.

Alguns campos opcionais que você pode encontrar:

- **`scriptExtensions`** e **`htmlExtensions`** permitem customizar quais extensões o clasp trata como código de servidor ou HTML.
- **`filePushOrder`** forç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 **`.gs`** são código de servidor do Apps Script. O clasp converte de forma transparente para e a partir do formato nativo do editor.
- Arquivos **`.html`** são templates servidos via `HtmlService.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:

```bash
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:

```json
{
  "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:

1. Numa máquina, rode `clasp login` (pule se já fez no Passo 1).
2. Rode `cat ~/.clasprc.json` e copie a saída inteira.
3. No seu repo no GitHub: **Settings → Secrets and variables → Actions → New repository secret**.
4. **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`:

```yaml
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 no `main` dispara um deploy. `workflow_dispatch` adiciona 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.json` para o clasp encontrar onde ele espera. Não use `cat` ou `echo` no secret em outro lugar; o GitHub só mascara automaticamente quando o secret é usado via `${{ secrets.* }}`.
- **`clasp push -f`** — envia tudo de `rootDir` para 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 push` só 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](mailto:support@8apps.co) e vamos começar.
