LXD Tools Extension Build Process
Overview
This document describes the automated build and deployment process for the LXD browser extension. The workflow is triggered when a pull request is merged to the main branch and handles building, signing, and distributing the extension across multiple platforms (Chrome and Firefox).
The deployment pipeline manages version control, package signing, storage on Cloudflare R2, and maintains a clean version history.
Workflow Trigger
When the workflow runs
- A pull request is merged to the main branch
- The event type must be 'closed' (not open, reopened, or synchronize)
What triggers it NOT to run
- Pull request is closed without merging
- Pull request is opened or updated
Pre-requisites
Repository requirements
- Version number in
package.jsonis updated with each release - Extension source code follows the npm build pipeline
updates.jsonandupdate.xmlfiles are present in the dist directory
Secrets and credentials
| Secret Name | Purpose |
|---|---|
CHROME_KEY_PEM_B64 |
Base64-encoded Chrome extension signing key (PEM format) |
WEB_EXT_API_KEY |
Firefox AMO API key for signing |
WEB_EXT_API_SECRET |
Firefox AMO API secret for signing |
R2_ACCESS_KEY_ID |
Cloudflare R2 access key ID for storage |
R2_SECRET_ACCESS_KEY |
Cloudflare R2 secret access key |
CF_ACCOUNT_ID |
Cloudflare account ID for R2 endpoint |
R2_BUCKET_NAME |
Name of the Cloudflare R2 bucket for storage |
LXD_TOOLS_BUILD_TOKEN |
GitHub personal access token for lxd-tools-build repository |
Build Process Steps
The workflow performs the following automated steps in sequence:
- Repository Checkout & Setup — Clones the lxd-tools repository and installs Node.js 20 with all dependencies. Git tags are fetched to enable version detection.
- Version Validation — Reads the version from
package.jsonand verifies it hasn't been deployed before by checking for an existing git tag. If a duplicate version is detected, the entire build fails with a clear error message to prevent accidental re-deployment. - Extension Compilation — Runs
npm run buildto compile the extension source code into thedistdirectory. - Platform-Specific Signing — The compiled extension is signed for both platforms:
- Chrome: Uses the crx3 tool with the private key to produce
lxd-extension-{VERSION}.crx -
Firefox: Uses the
web-ext signcommand with AMO API credentials to producelxd-extension-{VERSION}.xpisigned for the unlisted channel -
Artifact Verification — Validates that all required output files exist: both signed extensions (
.crxand.xpi), plus the update manifests (updates.jsonandupdate.xml). File paths are captured for downstream steps. - Upload to Cloudflare R2 — All artifacts are uploaded to the R2 bucket with appropriate content types. This includes both signed extensions and update manifests needed by the browser extension update mechanisms.
- Version Pruning — Automatically deletes old versions from R2, keeping only the 5 most recent releases of each file type (
.crxand.xpi). This reduces storage costs while maintaining version history. - Sync to Build Repository — The entire
distdirectory is copied to thelxd-tools-buildrepository on the main branch, creating an audit trail of all deployments with commits attributed togithub-actions[bot]. - Git Release Management — A git tag matching the version number is created and pushed, and a corresponding release branch (
release/{VERSION}) is created for long-term reference and potential rollback scenarios.
Important Considerations
Version Management
package.jsonversion must be incremented BEFORE merging the PR- The pull reqest will be blocked from merging unless the package version is bumped
- Duplicate version deployments are prevented by version validation step
- If version already exists, entire build fails with clear error message
Security
- All secrets are referenced via
${{ secrets.VAR_NAME }}syntax, per GitHub Actions format - Chrome key is base64-encoded and must be decoded before use
- Firefox API credentials are environment variables, never logged
- GitHub token used for pushing to build repository is scoped and temporary
Storage Retention
- Only the 5 most recent versions are retained in R2
- Older versions are automatically pruned to control costs
- This applies to both
.xpiand.crxfiles
Repository Structure
- Source code:
lxd-toolsrepository (main branch) - Built artifacts:
lxd-tools-buildrepository (main branch) - This separation allows history tracking and rollback capability
Workflow Execution Environment
- Runner: ubuntu-latest
- Permissions:
contents: write(for creating tags and commits) - Duration: Typically 5-10 minutes depending on npm install time
File Outputs
After successful execution, the following files are available:
| File | Location | Platform | Purpose |
|---|---|---|---|
lxd-extension-{VERSION}.crx |
R2 bucket & dist/ | Chrome | Signed extension package |
lxd-extension-{VERSION}.xpi |
R2 bucket & dist/ | Firefox | Signed extension package |
update.xml |
R2 bucket & dist/ | Chrome | Update manifest for Chrome |
updates.json |
R2 bucket & dist/ | Firefox | Update manifest for Firefox |
Troubleshooting
Build fails at version validation
Cause: package.json version was not incremented
Solution:
- Update
package.jsonwith a new version number - Push the change to a new commit or amend the PR
- Re-merge the PR to trigger the workflow again
Chrome extension fails to sign
Cause: Invalid or missing CHROME_KEY_PEM_B64 secret
Solution:
- Verify the secret is properly base64-encoded
- Check that the PEM file is valid (openssl x509 -in cert.pem -text -noout)
- Update the secret in GitHub repository settings if needed
- Re-run the workflow
Monitoring and Notifications
The workflow produces the following artifacts for monitoring:
- GitHub Actions logs: Real-time build output in Actions tab
- Git tags: Version tags created on successful deployment (visible in Releases)
- Release branches: Version-specific branches created at release/{VERSION}
- lxd-tools-build commits: Automatic commits showing deployment history
Maintenance
Before modifying the workflow
- Test changes in a separate branch
- Ensure all secrets are still available
- Verify npm build script still works
- Test signing keys are still valid
- Review and test any version management changes