Wenn du ein Google Workspace Add-on baust, lebt die Laufzeit an einem etwas seltsamen Ort. Apps Script ist ein Server, in den du dich nicht per SSH einloggen kannst, und ein UI, auf das du keine Dateien per scp kopieren kannst — jede Änderung muss durch Googles Editor oder deren API. Die Brücke zwischen deinem Repo und dieser Umgebung ist clasp (Command Line Apps Script), und sobald du das in GitHub Actions verpackst, wird Deployen zu einem ganz normalen git push.
Dieser Beitrag führt Schritt für Schritt durch die gesamte Pipeline: clasp installieren, die Konfiguration einrichten, die dein Repo mit einem konkreten Apps-Script-Projekt verknüpft, und am Ende ein GitHub-Actions-Workflow, der jeden Commit auf main direkt nach Apps Script schiebt.
Was clasp ist
clasp ist ein kleines Node-CLI von Google, das mit der Apps Script API spricht. Das mentale Modell ist einfach:
- Dein Apps-Script-Projekt liegt unter einer URL wie
script.google.com/.../editund wird durch einescriptIdidentifiziert. clasp pushlädt die.gs-,.html- undappsscript.json-Dateien aus einem lokalen Verzeichnis in das Skriptprojekt hoch und ersetzt die serverseitige Kopie.clasp pullmacht das Gegenteil — praktisch, wenn jemand Code im Apps-Script-Web-Editor geändert hat und du diese Änderungen zurück nach Git holen willst.clasp deployschneidet ein versioniertes, benanntes Deployment — genau das, was im Add-on-Store landet und was deine Endnutzer tatsächlich ausführen. Ohne diesen Schritt aktualisiertclasp pushnur die@HEAD-Version, die niemand außer dem Entwickler zu sehen bekommt.
Das ist das ganze Tool. Kein Build-System, keine Meinung zu deinem Code — nur ein Sync-Mechanismus zwischen einem Ordner auf der Platte und einem Skriptprojekt in Googles Cloud.
Schritt 1 — clasp installieren
clasp ist ein globales Node-Paket. Stell sicher, dass du Node 20+ installiert hast, dann:
npm install -g @google/clasp
clasp --version
Bevor clasp mit deinem Account sprechen kann, musst du die Apps Script API für deinen Google-Nutzer aktivieren. Geh zu script.google.com/home/usersettings und schalte Google Apps Script API auf An. Das ist ein einmaliger Schalter pro Account — leicht zu übersehen, und clasp bricht mit einem kryptischen Fehler ab, wenn du es vergisst.
Jetzt einloggen:
clasp login
Ein Browserfenster öffnet sich und führt dich durch den OAuth-Flow. Wenn das durch ist, legt clasp deine Anmeldedaten in ~/.clasprc.json ab. Auf diese Datei kommen wir zurück, wenn wir CI einrichten.
Schritt 2 — Die scriptId besorgen
Jedes Apps-Script-Projekt hat eine eindeutige scriptId — daran erkennt clasp, in welches Projekt es pushen soll. Es gibt zwei Wege, an eine zu kommen.
Wenn das Projekt noch nicht existiert, leg es direkt von der Kommandozeile an:
mkdir my-addon && cd my-addon
clasp create --type standalone --title "My Add-on"
--type kann standalone, sheets, docs, slides, forms oder webapp sein. Wähl, was zu deinem Add-on passt. clasp legt das Projekt auf Googles Seite an und schreibt eine .clasp.json, in der die neue scriptId schon eingetragen ist.
Wenn das Projekt schon existiert (du hast es im Apps-Script-Editor angelegt oder jemand hat dir eines geteilt), öffne es auf script.google.com und schau dir die URL an:
https://script.google.com/d/1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOp/edit
└────────────────────── scriptId ──────────────────────┘
Der lange alphanumerische Abschnitt zwischen /d/ und /edit ist deine scriptId. Du findest sie auch im Apps-Script-Editor unter Projekteinstellungen → IDs.
Schritt 3 — .clasp.json einrichten
.clasp.json ist die Datei, die dein lokales Verzeichnis an ein konkretes Apps-Script-Projekt bindet. Sie liegt im Wurzelverzeichnis deines Repos:
// .clasp.json
{
"scriptId": "1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOp",
"rootDir": "./src"
}
Zwei Felder, beide wichtig:
scriptId— das Projekt, in das clasp pushen soll. Trag die ein, die du in Schritt 2 bekommen hast.rootDir— der lokale Ordner, den clasp als Projektquelle behandelt. Alles in diesem Ordner wird hochgeladen, alles außerhalb ignoriert. Wenn durootDirweglässt, nimmt clasp das aktuelle Verzeichnis — was meist heißt, dass es versucht, deinenode_modulesund.gitmitzuschicken. Setz es immer explizit.
Ein paar optionale Felder, die dir begegnen können:
scriptExtensionsundhtmlExtensionslassen dich anpassen, welche Dateiendungen clasp als Servercode oder HTML behandelt.filePushOrdererzwingt, dass bestimmte Dateien vor anderen gepusht werden — nur relevant, wenn du Ladereihenfolge-Abhängigkeiten zwischen.gs-Dateien hast.
Für die meisten Projekte reicht die Zwei-Feld-Variante oben.
Schritt 4 — Die Dateien anlegen
clasp ist es egal, wie deine Dateien in rootDir gelandet sind. Solange der Ordner gültige Apps-Script-Dateien enthält, werden sie gepusht. Ein minimales Layout sieht so aus:
my-addon/
.clasp.json
.claspignore // optional — Dateien, die beim Push übersprungen werden
src/
appsscript.json // Manifest: Scopes, Runtime, Add-on-Konfig
Code.gs // deine serverseitigen Funktionen
Sidebar.html // alles HTML, was du via HtmlService ausliefern willst
Drei Dinge zu den Dateitypen:
.gs-Dateien sind Apps-Script-Servercode. clasp wandelt sie transparent in das native Editor-Format und zurück..html-Dateien sind Templates, die viaHtmlService.createHtmlOutputFromFile()ausgeliefert werden.appsscript.jsonist das Projekt-Manifest. Es deklariert OAuth-Scopes, die Runtime-Version (V8), die Zeitzone und — bei Add-ons — die Menüeinträge und Trigger, die Nutzer sehen. clasp weigert sich, ohne dieses Manifest zu pushen.
Wenn du Dateien in rootDir hast, die nicht hochgeladen werden sollen (Build-Skripte, READMEs, alles, was nicht .gs/.html/appsscript.json ist), leg eine .claspignore neben .clasp.json:
**/**
!appsscript.json
!**/*.gs
!**/*.html
Dieses Muster sagt: „Alles ignorieren, dann genau die Dateitypen wieder zulassen, die Apps Script tatsächlich versteht."
Sobald das Layout steht, kannst du lokal mit zwei Befehlen deployen:
clasp push -f
clasp deploy --description "first version"
-f überspringt die interaktive „Manifest geändert"-Bestätigung — kann dauerhaft anbleiben, und ist später für CI sowieso Pflicht.
Schritt 5 — clasp im CI authentifizieren
Lokale Deploys funktionieren, weil clasp login Anmeldedaten in ~/.clasprc.json hinterlassen hat. GitHub-Actions-Runner haben diese Datei nicht, und sie können auch keinen Browser-Flow ausführen, also reichen wir die Anmeldedaten direkt über ein Secret durch.
Die Datei sieht ungefähr so aus:
{
"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
}
Der refresh_token ist das tragende Element — solange niemand die Berechtigung widerruft, kann clasp damit monatelang frische Access-Tokens nachgenerieren.
So packst du ihn in GitHub:
- Auf einer Workstation
clasp loginausführen (überspringen, wenn du Schritt 1 schon gemacht hast). cat ~/.clasprc.jsonund die komplette Ausgabe kopieren.- In deinem Repo auf GitHub: Settings → Secrets and variables → Actions → New repository secret.
- Name:
CLASPRC_JSON. Value: das gerade kopierte JSON.
💡 Tipp: Erzeug dieses Token aus einem dedizierten Google-Account, dem das Apps-Script-Projekt gehört — nicht aus deinem persönlichen Account. Wenn jemand das Team verlässt, musst du nichts rotieren.
Schritt 6 — Der GitHub-Actions-Workflow
Jetzt der Lohn. Leg das hier nach .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"
Was die einzelnen Teile tun:
on: push: branches: [main]— jeder Merge aufmaintriggert ein Deploy.workflow_dispatchfügt im Actions-Tab einen „Run workflow"-Button für manuelle Re-Runs hinzu.environment: production— opt-in zu einer GitHub-Umgebung. Wenn du erforderliche Reviewer dafür konfigurierst, wartet jedes Deploy auf eine menschliche Freigabe, bevor es weitergeht. Empfehlenswert für jedes Add-on mit echten Nutzern.- Restore clasp credentials — schreibt das Secret zurück in
~/.clasprc.json, damit clasp es dort findet, wo es es erwartet.catoderechodas Secret nirgendwo anders aus; GitHub maskiert es nur dann automatisch, wenn es über${{ secrets.* }}benutzt wird. clasp push -f— lädt alles ausrootDirins Apps-Script-Projekt hoch. Das-fist im CI Pflicht, sonst hängt der Runner an der „Manifest geändert"-Eingabeaufforderung.clasp deploy --description— schneidet ein neues, versioniertes Deployment. Die Beschreibung enthält den Short-SHA und einen Zeitstempel, damit du jedes Deployment auf den exakten Commit zurückführen kannst. Diesen Schritt vergessen die meisten — ohne ihn aktualisiertclasp pushnur@HEAD, was deine installierten Nutzer nie zu sehen bekommen.
Workflow committen, pushen und auf den grünen Haken warten. Ab jetzt ist Deployen einfach git merge.
Was wir nicht tun (und warum)
Wir checken ~/.clasprc.json nicht ins Repo ein. Sie enthält ein Refresh-Token, das praktisch ein langlebiges Credential ist. Es gehört in GitHub Secrets, nie in die Versionskontrolle.
Wir teilen keinen einzelnen Google-Account im Team. Das CLASPRC_JSON-Secret kommt aus einem dedizierten Account, dem das Apps-Script-Projekt gehört. Persönliche Accounts wechseln, der Deploy-Account nicht.
Wir lassen in diesem Workflow keine Tests laufen. Die Apps-Script-Runtime unterscheidet sich genug von Node, dass sinnvolle Unit-Tests schwierig sind. Wir lassen Logik-Tests in einem separaten Workflow gegen einen Node-Port des gemeinsamen Codes laufen und verlassen uns nach jedem Deploy auf einen manuellen Smoke-Test.
Der Lohn der Mühe
Vor diesem Setup hieß deployen: Latest pullen, hoffen, dass dein clasp-Token nicht abgelaufen ist, clasp push ausführen, daran denken, clasp deploy mit einer sinnvollen Beschreibung anzustoßen, hoffen, dass du -f nicht vergessen hast. Fünf Schritte, fünf Stellen zum Verheddern.
Jetzt: Merge nach main, grünen Haken abwarten, Add-on öffnen. Apps Script ist keine Sondersache mehr — es ist einfach ein weiteres Deploy-Ziel hinter demselben Git-Workflow wie alles andere, was du ausspielst.
Wenn du ein Workspace-Add-on pflegst und immer noch von deinem Laptop pushst, ist die Migration ein Nachmittagsprojekt. Das Schwierigste ist, ~/.clasprc.json zu finden.
Hast du einen eigenen Workflow im Kopf?
Wir bauen maßgeschneiderte Google-Workspace-Add-ons, die exakt zu deinen Geschäftsprozessen passen. Schreib uns an support@8apps.co, um loszulegen.