- Node.js >= 24 and pnpm 10
- If you use mise, run
mise install - Or use Dev Containers / Codespaces for zero local setup
Store the shared clasp credentials in Google Cloud Secret Manager and let CI fetch them keylessly via Workload Identity Federation — full guide: secret-manager.md. In short:
- Create a dedicated Google account for CI/CD (e.g.,
apps-script-deploy@yourcompany.com), runclasp login, and store~/.clasprc.jsonin theclasp-credentialssecret. - Create the WIF pool
apps-script-fleetwith agithubprovider, attribute-restricted to your org (assertion.repository_owner == '<org>'— required, the GitHub issuer is multi-tenant). - Grant
roles/secretmanager.secretAccessortoprincipalSet://…/attribute.repository_owner/<org>. - Set Organization variables
GCP_WIF_PROVIDERandCLASPRC_SECRET.
Every repository created from this template authenticates via WIF automatically — no per-repo auth setup needed. For per-repo hardening you can bind IAM to
attribute.repository/<org>/<repo>instead, or pin tokens to a deployment environment (sub = repo:ORG/REPO:environment:ENV). Note: CD runs on aworkflow_runtrigger, whereref-based OIDC conditions are unreliable — preferrepository/environmentclaims.
Legacy fallback: CLASPRC_JSON Organization Secret
Used automatically when GCP_WIF_PROVIDER is not set: add the contents of ~/.clasprc.json as an Organization Secret named CLASPRC_JSON.
Click "Use this template" on GitHub, then clone:
git clone https://github.com/<your-org>/<your-project>.git
cd <your-project>
pnpm install
Create .clasp-dev.json and .clasp-prod.json (gitignored):
{
"scriptId": "YOUR_SCRIPT_ID",
"projectId": "YOUR_GCP_PROJECT_ID",
"rootDir": "dist"
}
projectIdis the GCP project number associated with your Apps Script (a numeric string like"123456789", not the alphanumeric project ID likemy-project-abc). Find it in Apps Script editor → Project Settings → Google Cloud Platform (GCP) Project. Including it makes the GCP project association declarative and reproducible. If omitted, clasp uses the script's existing GCP project.
| Environment | Secret / Variable | Value |
|---|---|---|
development |
Secret: CLASP_JSON |
{"scriptId":"DEV_ID","projectId":"GCP_NUM","rootDir":"dist"} |
development |
Variable: DEPLOYMENT_ID |
Your dev deployment ID |
production |
Secret: CLASP_JSON |
{"scriptId":"PROD_ID","projectId":"GCP_NUM","rootDir":"dist"} |
production |
Variable: DEPLOYMENT_ID |
Your prod deployment ID |
With GCP project: Add
"projectId":"YOUR_PROJECT_NUMBER"toCLASP_JSON(e.g.,{"scriptId":"...","rootDir":"dist","projectId":"123456789"}). This is set automatically when usinginit.sh --gcp-project.
pnpm run check # lint + typecheck + test
pnpm run deploy # check → build → push to dev
That's it. Push to main triggers production deployment automatically.
No local setup needed. Everything is pre-configured in .devcontainer/.
- VS Code: "Reopen in Container"
- GitHub Codespaces: Code → Codespaces → Create codespace on main
For clasp login inside a container, use pnpm exec clasp login --no-localhost.