Automating Chrome extension publishing with GitHub Actions
In the earlier days of Jam engineering, we did a few things that don’t scale. As one of those many things, we manually submitted this developer Chrome extension to the Chrome Web Store. This meant whenever we wanted to release newer versions of our extension, one of our engineers had to run a script to build the extension bundle and literally click and drop the archive file into the Web Store dashboard.
Needless to say this became a pain point for us! This post describes our approach to automating this, but before that here’s a quick overview of how publishing an extension works:
- Build your Chrome extension
- Archive the output folder
- Go to Chrome Web Store Developer Dashboard
- Potentially login, and switch to your organization’s publisher
- Upload new package
- Submit for review
- Wait 1-2 business days for extension review
- Extension is published
To save us time, whenever we push a tag to our master
branch, our continuous integration system automatically uploads the extension archive to the Web Store!
Automating extension upload
We use GitHub Workflows as our CI system and follow the GitHub branching model so our shared branches are develop
, staging
, and master
.
When we push a semver git tag to master, CI runs a specific workflow for publishing the extension:
name: Update Chrome Extension
on:
push:
tags:
- v*.*.*
Inside of this workflow we have two main jobs, building and publishing the artifact.
jobs:
build-chrome-extension:
name: Build Chrome extension artifact
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: |-
# fill in your build steps here...
# we archive the dist folder and include SHA commit as the last step
zip -r chrome-extension-${{ github.event.pull_request.head.sha }}.zip dist
- name: Archive chrome-extension artifact
uses: actions/upload-artifact@v2
with:
name: chrome-extension-${{ github.sha }}
path: chrome-extension-${{ github.event.pull_request.head.sha }}.zip
Then the next job is for uploading the extension. We use a CLI utility called chrome-webstore-upload-cli
# api usage reference:
# * <https://developer.chrome.com/docs/webstore/using_webstore_api/>
# * <https://github.com/fregante/chrome-webstore-upload/blob/main/How%20to%20generate%20Google%20API%20keys.md>
upload-extension:
name: Upload extension
runs-on: ubuntu-latest
needs: build-chrome-extension
env:
# you can optionally specify extension ID here, we do this so that
# all of our environments (dev, staging, prod) have a consistent ID
# we can reference. Otherwise the extension ID is autogenerated.
EXTENSION_ID: <extension id her>
steps:
- uses: actions/setup-node@v2-beta
with:
node-version: "16.10"
- name: Download bundle artifact
uses: actions/download-artifact@v3
with:
name: chrome-extension-${{ github.sha }}
- name: Install webstore cli
run: |-
npm install -g chrome-webstore-upload-cli
- name: Upload step
run: |-
chrome-webstore-upload upload \\
--source chrome-extension-${{ github.event.pull_request.head.sha }}.zip \\
--extension-id ${{ env.EXTENSION_ID }} \\
--client-id ${{ secrets.CI_GOOGLE_CLIENT_ID }} \\
--client-secret ${{ secrets.CI_GOOGLE_CLIENT_SECRET }} \\
--refresh-token ${{ secrets.CI_GOOGLE_REFRESH_TOKEN }}
You’ll need to generate Google API keys which is outlined here.
Then in your GitHub repo go to Settings > Security > Actions and click New repository secret for each of the above secrets
Accessing the bundle
As a bonus, in the GitHub Workflow summary page, you can access the produced artifact at the bottom of the page.
In our other builds like staging
branch or feature branches, we use the build artifact to leave a GitHub comment with a link to the bundle. You could also send a notification to your company chat like Slack, Hipchat, etc.
Chrome Web Store Submission
Once the above workflow gets triggered it only uploads the package. Remember that this is only staging the extension submission, we still manually visit the developer dashboard and submit for review but we’ve automated the most tedious parts of it.
Typically, you’ll update your manifest version for each release. We verify that the newest draft in the Developer Dashboard matches our upcoming version.
When we are ready to submit, we click Submit for Review
Then we wait! The approval process is async and takes 1-2 days but now that we’ve automated some of the toil, we can spend more time on building more features and making Jam better!