This repository is an example of how to setup an automatic CI/CD process for Google Apps Script using GitHub Actions.
forked from https://github.com/ericanastas/deploy-google-app-script-action
- major changes:
- saves extra GitHub action context data data in a object stored in
git-info.js
- adds the ability to have a document container by setting
PARENT_ID
in actions secrets. commitTracker.js
will automatically log whenever the script in GAS gets updated if you set up a recurring trigger for it.- at present, this requires a parent container.
- saves extra GitHub action context data data in a object stored in
This is useful if you want to work from a nicer editor than the built-in Google one (ie vsCode) and use GitHub for version control & etc. There's probably a better thing to use for standalone GAS scripts or stuff that uses features of GCP, but if you don't have access to GCP because your organization locked down your gSuite access a little too much, this is a nice alternative.
- Install clasp on your development machine if not already installed.
- Create a local copy of a Google Apps Script project. You may use
clasp create
to create a new project orclasp clone
to download an existing project. This will create a.clasp.json
file. - Initialize the project folder as a new Git repo:
git init
.- The
.clasp.json
file created in the prior step MUST be in the root of the Git repository, .clasp.json
may point to source files in a sub folder throgh arootDir
property.
- The
- Copy
.github/workflows/deploy-script.yml
from this repository to the same relative path.
{
"scriptId": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
"rootDir": "src",
"projectId": "project-id-0000000000000000000",
"fileExtension": "js",
"filePushOrder": ["src/File1.js", "src/File1.js", "src/File1.js"],
"parentId": "XXXXXXXXXXXXXXXXXXXXXX"
}
- Stage files:
git add .
- Commit files:
git commit -m "first commit"
- Create a
develop
branch:git branch -M develop
- Create a
main
branch:git branch -M main
- Create a new GitHub repository, and add it as a remote:
git remote add origin [email protected]:account/repo.git
- Push the
main
branch to GitHub:git push -u origin main
- Push the
develop
branch to GitHub:git push -u origin develop
At this point the workflow will be triggered, but will fail because it is not configured completely.
Github encrypted secrets are used to configure the workflow and can be set from the repository settings page on GitHub.
The clasp
command line tool uses a .clasprc.json
file to store the current login information. The contents of this file need to be added to a CLASPRC_JSON
secret to allow the workflow to update and deploy scripts.
- Login to clasp as the user that should run the workflow:
- Run
clasp login
- A web browser will open asking you to authenticate clasp. Accept this from the account you want the workflow to use.
- Run
- Open the
.clasprc.json
file that is created in the home directory (C:\Users\{username}
on windows, and~/.clasprc.json
on Linux) - Copy the contents of
.clasprc.json
into a new secret namedCLASPRC_JSON
A GitHub personal access token must be provided to the workfow to allow it to update the CLASPRC_JSON
secret configured about when tokens expire and refresh.
- Create a new GitHubpersonal access token with
repo
scope. - Copy the token into a new secret named
REPO_ACCESS_TOKEN
The clasp command line tool identifies the Google Apps Script project to push and deploy too using the scriptId
property in .clasp.json
. You may leave this value hard coded in .clasp.json
or you may have this set dynamically. To specify the target script dynamically add a SCRIPT_ID
secret to the repository. This will cause the workflow to override whatever literal scriptId value is in .clasp.json
This is for projects that have a container document, such as a spreadsheet. Similar to SCRIPT_ID
, You can leave this value hard coded in .clasp.json
or you may have this set dynamically. To specify the target script dynamically add a PARENT_ID
secret to the repository. This will cause the workflow to override whatever the literal parentId
value is in .clasp.json
The workflow can automatically deploy the script when the main
branch is pushed to github.
- Determine the ID of the deployment you want
- Create a new deployment by running
clasp deploy
or on https://scripts.google.com. - Find the deploymen id by running
clasp deployments
or checking the projet settings on https://scripts.google.com.
- Create a new deployment by running
- Add the desired deployment id to a secret naned
DEPLOYMENT_ID
- Pushing to either the
main
ordevelop
branches on github will automatically trigger the workflow to push the code to theHEAD
deployment on https://scripts.google.com` - If the
DEPLOYMENT_ID
secret has been setup pushing tomain
will also deploy the script to the specified deployment.
The .clasprc.json
file that stores the authentication information contains a access_token
which expires at the specified expiry_date
and a refresh_token
that can be used to request a new access_token
. These tokens will change over time, but the workflow should update the CLASPRC_JSON
repository secret.
However, there are conditions where the refresh token may also expire. So in addition to the push triggers the workflow is also configured to automatically attempt to login to clasp once a week which will confirm the authentication is still working and potentially refresh and save new tokens.
{
"access_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"refresh_token": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
"scope": "https://www.googleapis.com/auth/script.projects https://www.googleapis.com/auth/script ...",
"token_type": "Bearer",
"expiry_date": 0000000000000
}
The whole system described here copying the credentials out of .clasprc.json
and using a scheduled trigger to automatically update the tokens on a regular basis is a hack.
The "correct" way to setup a server to server connection like is through a GCP service account. It is possible to login clasp using a key file for a service account. However, the Apps Scripts API does not work with service accounts.
- Execution API - cant use service account
- Can the Google Apps Script Execution API be called by a service account?