How I Used GitHub Actions to Auto-Publish to AMO on Every Release
Manually uploading extension files to AMO (Mozilla's Add-On Observatory) is tedious. After the fifth time forgetting to increment the version number, I automated it with GitHub Actions.
Here's exactly how I set up the pipeline for the Weather & Clock Dashboard extension.
What the Pipeline Does
- Trigger on new GitHub release
- Validate the manifest version matches the release tag
- Bundle the extension into a
.zip - Submit to AMO via the
web-extCLI - Wait for AMO review completion (or fail gracefully)
Setting Up AMO API Credentials
First, create API credentials at addons.mozilla.org:
- Go to AMO → User menu → Developer Hub → API Credentials
- Create a new credential
- Note your
JWT issuerandJWT secret
Store these in GitHub Secrets:
AMO_JWT_ISSUER = user:12345678:123
AMO_JWT_SECRET = your-secret-here
The Workflow
# .github/workflows/publish.yml
name: Publish to AMO
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install web-ext
run: npm install -g web-ext
- name: Verify version matches release tag
run: |
MANIFEST_VERSION=$(node -p "require('./manifest.json').version")
RELEASE_TAG="${GITHUB_REF#refs/tags/v}"
echo "Manifest version: $MANIFEST_VERSION"
echo "Release tag: $RELEASE_TAG"
if [ "$MANIFEST_VERSION" != "$RELEASE_TAG" ]; then
echo "Version mismatch! manifest.json has $MANIFEST_VERSION but release is $RELEASE_TAG"
exit 1
fi
echo "Version match confirmed: $MANIFEST_VERSION"
- name: Build extension package
run: |
web-ext build \
--source-dir . \
--artifacts-dir ./web-ext-artifacts \
--overwrite-dest
ls -la ./web-ext-artifacts/
- name: Sign and publish to AMO
run: |
web-ext sign \
--source-dir . \
--api-key "$AMO_JWT_ISSUER" \
--api-secret "$AMO_JWT_SECRET" \
--channel listed
env:
AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }}
AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }}
- name: Upload artifact to GitHub Release
uses: softprops/action-gh-release@v1
with:
files: ./web-ext-artifacts/*.zip
The web-ext sign Command Explained
web-ext sign \
--source-dir . # Where your extension files are
--api-key $AMO_JWT_ISSUER # From AMO API credentials
--api-secret $AMO_JWT_SECRET # From AMO API credentials
--channel listed # 'listed' for public, 'unlisted' for private
--timeout 900000 # 15 min timeout for review queue
Important: --channel listed means your extension goes through AMO's review process. The command will wait (up to the timeout) for AMO to review and approve the submission.
For unlisted, the signing happens immediately.
Handling AMO Review Delays
AMO review can take anywhere from hours to days. For listed extensions, the web-ext sign command might time out. Handle this gracefully:
- name: Submit to AMO
continue-on-error: true # Don't fail the workflow if review is pending
run: |
web-ext sign \
--api-key "$AMO_JWT_ISSUER" \
--api-secret "$AMO_JWT_SECRET" \
--channel listed \
--timeout 300000 # 5 minutes, then continue
Local Testing with web-ext
Before triggering CI, test the web-ext commands locally:
# Install globally
npm install -g web-ext
# Build and check for errors
web-ext build
# Lint your extension
web-ext lint
# Run in Firefox for local testing
web-ext run --firefox=/Applications/Firefox.app/Contents/MacOS/firefox
Creating a Release to Trigger the Workflow
# 1. Update version in manifest.json
jq '.version = "1.2.0"' manifest.json > tmp.json && mv tmp.json manifest.json
# 2. Commit and push
git add manifest.json && git commit -m "chore: bump version to 1.2.0"
git push
# 3. Tag and create release
git tag v1.2.0
git push origin v1.2.0
# Then create the release in GitHub UI or via CLI:
gh release create v1.2.0 --title "v1.2.0" --notes "What changed"
This triggers the workflow and publishes to AMO automatically.
What Gets Submitted
The web-ext CLI automatically excludes files listed in .gitignore and certain development files. I also add a .web-ext-config.json:
{
"build": {
"overwriteDest": true,
"filename": "weather-clock-dashboard-{version}.zip"
},
"ignoreFiles": [
".github",
"*.md",
"tests/**",
"scripts/**",
"node_modules"
]
}
The Result
Now every GitHub release automatically:
- Validates version consistency
- Publishes to AMO
- Attaches the built
.zipto the release
Check out the extension: Weather & Clock Dashboard on AMO
Part of a series on building and publishing Firefox browser extensions.
Top comments (0)