Creating a Release
Relevant source files
The following files were used as context for generating this wiki page:Creating a release for the Ghostbird add-on is a scripted process that transforms the TypeScript source code into a distributable .xpi package for Thunderbird. The process is managed through a series of yarn scripts defined in package.json, which orchestrate various tools like tsdown for bundling, web-ext for packaging, and custom Node.js scripts for tasks like manifest generation.
The entire build workflow is designed to be consistent for both local development and automated CI/CD environments, with specific behaviors for "development" and "release" modes. This ensures that final release artifacts are optimized and correctly versioned. For a detailed look at the build script internals, refer to the project's building documentation.
Sources: package.json, doc/building.md:3-6, README.md:92-94
Build Process Overview
The primary command to create a full build is yarn build. This command executes a sequence of tasks to ensure code quality and produce the final package. The process can be broken down as follows:
- Code Validation (
yarn check): Runs type checking (tsc) and linting (biome) to catch errors. - Testing (
yarn test): Executes the unit test suite using Vitest. - JavaScript Bundling (
yarn build-js): Invokestsdownto compile TypeScript source files into bundled JavaScript. This step also handles asset copying, manifest generation, and locale file creation. - XPI Packaging (
yarn build-xpi): Uses theweb-exttool to package the contents of thedist/ext/directory into a single.xpifile.
Sources: package.json:28, 41, CONTRIBUTING.md:49-50
The following diagram illustrates the flow of inputs and outputs through the various build tools.
This diagram shows the data flow from source files through the tsdown build pipeline to the final packaged .xpi file.
Sources: doc/building.md:8-30
Build Modes: Development vs. Release
The build script operates in two distinct modes, determined by the environment. A build is considered a release build if the CI environment variable is set to true or if a ext/manifest.json file already exists. Otherwise, it is a development build.
The behavior differs between these modes:
| Feature | Development Build | Release Build |
|---|---|---|
| Source Maps | Absolute paths for easier debugging. | Relative paths for cleaner presentation in the debugger. |
| Logging | console.log() calls are preserved and prefixed with [Ghostbird]. | console.log() calls are removed entirely. |
| Pre-build Checks | Runs sanity tests (test_sanity.ts) and type checking (typecheck_with_tsc.ts). | Skips sanity tests and type checking, as these are expected to be run separately in a CI pipeline (yarn check and yarn test). |
| Codecov | Bundle size reporting is disabled. | Uploads bundle size information to Codecov if an API key is available. |
Sources: doc/building.md:43-60, tools/tsdown_config.ts:33, 89, 91, 95, 107
Manifest Generation
A crucial step in the release process is the dynamic generation of the manifest.json file. This is handled by the generate_manifest.ts plugin for tsdown.
The process starts with a template file, manifest_template.json, which contains placeholders and the core structure of the manifest. The generateManifest plugin populates this template with dynamic data, most importantly the version and version_name.
If a developer manually places a manifest.json file in the ext/ directory, the generation step is skipped. This allows for reproducing a specific build.
Sources: tools/generate_manifest.ts:11-20, manifest_template.json, doc/building.md:39-41
Version Number Calculation
The version number is determined based on the context in which the build is running. The logic is encapsulated in the getVersionInfo function within generate_manifest.ts.
The following diagram shows the decision flow for determining the version string.
The four main scenarios for versioning are:
| Scenario | Trigger | Version Source | Example Version |
|---|---|---|---|
| CI Release | GITHUB_REF_TYPE is tag. | Git tag and commit SHA. | 1.2.3.228825662 |
| CI Nightly | GITHUB_REF_TYPE is not tag. | Git branch and commit SHA. | nightly-main-da39a3ee5e... |
| Developer Build | Git repository is present. | git describe output. | 1.2.3+74.g6d0ce74.dirty |
| Tarball Build | No Git information available. | A dummy version with a timestamp. | 0.0.1893501296000 |
The version string for a release build is constructed by taking the semantic version from the Git tag and appending the first 7 characters of the commit SHA, converted to an integer.
// tools/generate_manifest.ts:95-97
function appendSha(version: string, sha: string): string {
return `${version}.${Number.parseInt(sha.slice(0, 7), 16)}`
}
Sources: doc/building.md:73-94, tools/generate_manifest.ts:51-97
Packaging and Final Artifacts
The final step of the release process is packaging the built files into an .xpi archive. This is handled by the yarn build-xpi script, which is a wrapper for web-ext build.
The web-ext tool is configured in package.json:
sourceDir:dist/ext/(The directory containing all bundled assets).artifactsDir:dist/(Where the final.xpifile will be placed).build.filename:{short_name}-{version}.xpi(The naming pattern for the output file).
This produces the final distributable file, for example, ghostbird-0.4.0.xpi.
Sources: package.json:40, 45-51, doc/building.md:31-34
Build Reproducibility
While the build process aims for consistency, builds are not strictly reproducible. Builds from the same source may have different timestamps and file ordering within the .xpi archive. However, the file names and their contents should be identical to those produced by the CI system if a release maintainer uses a checked-out ext/manifest.json to trigger a release build.
Sources: doc/building.md:96-102
Key Build Scripts
The following table summarizes the main scripts involved in creating a release, as defined in package.json.
| Script | Command | Description |
|---|---|---|
build | run check && run test && run build-js && run build-xpi | The main build command. Runs checks, tests, bundling, and packaging in sequence. |
build-js | tsdown --config=tools/tsdown_config.ts | Bundles TypeScript source into JavaScript using tsdown. |
build-xpi | web-ext build | Packages the bundled files from dist/ext/ into an .xpi file. |
check | run check-type && biome check --error-on-warnings | Performs static analysis, including type checking and linting. |
test | vitest run | Runs the unit test suite. |
archive | git archive ... | Creates a .zip archive of the source code for a given release. |
Sources: package.json:22, 28, 39-41