We use Firefox's built in update system to update the browser, running our own Balrog server to provide updates. We have a fork of that project that contains the changes needed to configure the update server for our purposes, and the deployment steps. The deployment is documented here.
The balrog public endpoint is available at update.ghosterybrowser.com
, and we configure the browser
to use this URL by setting MOZ_APPUPDATE_HOST
during the build. This is achived by the
this patch.
We have two update channels, release
and nightly
. On balrog we can configure which version
each channel should get. The nightly
channel automatically gets nightly builds run on CI. This is
done by the "publish to balrog" step of the Jenkins job. Submitting a new nightly build to balrog
consists of 3 steps.
- Creating a release on balrog.
python3 ci/submitter.py release --tag TAG_NAME
- Attaching each build to the release (each
.mar
file is fingerprinted).python3 ci/submitter.py build --tag TAG_NAME --bid BUILD_ID --mar ARTIFACT_PATH
- Update the nightly update rule to point to the new release:
python3 ci/submitter.py nightly --tag TAG_NAME
The operations on the balrog API are implemented by the ci/submitter.py
script, which uses Mozilla's balrogclient
library to talk to the balrog admin endpoint.
The release
channel is manually updated via the balrog admin UI to point to specific release
builds which were uploaded as nightly builds.
The update channel used by the browser is configured by the app.update.channel
pref. In Firefox
this pref is locked, so it can only be changed by editing files on disk. Changes made in about:config
to this pref will not register. This is so that the update channel can be locked with the build
and it should not be changed after install.
For Ghostery we distribute the same builds to both channels in order to simplify the build process,
but this means that we cannot configure release builds differently to nightlies. We get around this
by making app.update.channel
pref changes from about:config
work, so users can manually update
their update channel in the browser. This is achieved via a subtle change to UpdateUtils.jsm
, as
you can see in this patch.
For incremental updates partial updates can be used to reduce the update size. From a normal build
a "complete" update .mar
file is generated, which contains a full update from any version to the
new version. We can also generate a diff between too complete mars, which can be used to update
between specific versions.
This "partial" mar can be generated with the following steps (see also ci/mar_diff.sh
)
- Download both mars and unpack each with the
mozilla-release/tools/update-packaging/unwrap_full_update.pl
script. - Run
mozilla-release/tools/update-packaging/make_incremental_update.sh
with the two unpacked mars as input.
We can then add these partials to a balrog Release, which enables clients with specific versions to use the partial to update rather than the complete mar.
The "partial-updates" Jenkins job automates the generation of partials, given a pair of releases to diff, by doing the following:
- Fetching mars for all build targets for the given releases (using Balrog to get the download
links for these) and diffing each pair (implemented by
ci/partials.py generate
). - Signing the partial mars.
- Uploading mars to Github Releases.
- Updating Balrog with the new partial builds (implemented by
ci/partials.py publish
)