The journey of a Launchpad change from a developer’s branch to production¶
Warning
This document contains many links that are Canonical-internal and only accessible to those who work for Canonical.
Characters¶
The Launchpad developer.
Launchpad’s branches.
Launchpad itself.
Jenkins jobs.
Buildbot.
Deployable.
Launchpad
qastaging
andstaging
environments.Scripts from the
lp:launchpad-bastion-scripts
repository.Juju and mojo.
Fragile Launchpad jobs.
Launchpad production environment.
The journey¶
What VCS branches does Launchpad use?¶
The main Launchpad repository has 4
main (or “trunk”) branches. These are master
, stable
, db-devel
,
and db-stable
. For more details see branches.
How to contribute a code change or a database schema change to Launchpad?¶
If the change includes code and database schema changes, both have to be done
separately and target different branches. The database patch needs to be based
on and target the db-devel
branch, whereas the code changes need to be based
on and target the master
branch. This is because database changes can be
destabilising to other work, so we isolate them into a separate branch. Since
Launchpad has a large database and codebase with strict uptime requirements,
we want to deploy changes to only one of these at a time and this separation
helps that as well.
How to test the code and database changes together?¶
It is important to get the database patches submitted and merged to the
db-devel
branch as early as possible. This is because those changes get
merged to the master
branch only after they are deployed to production
(the details will be explained in a later question) and it is a pre-requisite
to get the code changes merged.
While the database patches make their way to production and to the master
branch, one way to test the code and the database changes together is
to copy the database patch from the db-devel
branch manually and apply
it locally in the development environment to implement and test the
corresponding code changes. Once the database patch is deployed to the
production environment and merged back to the master
branch, the code and
the database changes should be tested together in the qastaging
environment before deploying the code changes to production.
How to deploy the database changes to the production environment?¶
The database patches should be submitted to the db-devel
branch and once
they are approved, they get merged by a landing (aka “merging”) bot which
performs the merge. The trunk branches of Launchpad have ACLs so that only
the landing bot can push changes to them.
Once the changes are merged to the db-devel branch
, the
Launchpad buildbot, runs the full
Launchpad test suite on the db-devel
branch and if it passes, the new
changes get merged to the db-stable
branch.
Once this is done, the changes show up on the launchpad-db deployable page and there is a periodic cron job that automatically deploys the new database patches, if any, to the Launchpad staging environment.
The database patch application time can
be checked from the staging
deployment logs. Launchpad has strict
requirements about the patch application time and it should be under
10 seconds.
After confirming the patch application time, the instructions in the
fastdowntime deployment process documentation can be used to deploy the
database patch to production. Our database deployment policy requires
deploying only one database patch per deployment. If there are multiple patches
to deploy, they should be deployed separately. Since there are some fragile
jobs (for example, the PPA and ftpmaster
publishers, librarian garbage
collector) that shouldn’t be interrupted by a database downtime, the deployment
process ensures that there are no such jobs running before applying the patch
with a small downtime. At the end of this process, the database changes will get
merged to the master
branch.
What is the landing bot?¶
When a Launchpad merge proposal is approved and its status is set to
Approved
, there is a Launchpad Jenkins trigger that runs and
triggers the Launchpad merge Jenkins job to merge the changes to
the appropriate target branch. This job is often called as the landing
bot. This and the other Jenkins jobs that we use are defined in the
ols-jenkaas-jobs repository.
What is buildbot?¶
Buildbot is a continuous integration system that we
use for running the Launchpad test suite before promoting the changes in the
master
, db-devel
branches to the stable
, db-stable
branches
(changes to production are deployed from these branches) respectively.
Our deployment of buildbot has 2 or more build configurations defined and these
configurations have names like lp-devel-focal
and lp-db-devel-focal
,
where the former runs the test suite on the master
branch (code changes)
and the latter runs the test suite on the db-devel
branch (database
changes).
There is a buildbot poller script that runs on the buildbot buildmaster and merges new commits that have completed a successful Launchpad test suite run into the appropriate stable branch.
What is deployable?¶
Deployable is the web application that
we use to track each revision of code, whether it is ready to be deployed, and
the details of the commits included in each deployment. There is a
Launchpad deployable project (tracking the stable
branch) and a
Launchpad DB deployable project (tracking the db-stable
branch.)
The deployable page lists the commits in the corresponding stable branch that
haven’t been deployed to the production environment. To deploy a specific
commit, that commit and all its ancestors that are listed in that page should
be tested by a Launchpad engineer (usually the author of the commit) in the
staging
or qastaging
environments and marked as deployable using the
button under each commit.
Then during the deployment process, a deployment request is created on this web application to track the commits that are included in that deployment. And after the deployment is completed, the deployment request is marked as deployed.
The deployment requests on this application are solely used for tracking and do not affect the actual deployment process in any way.
What are the Launchpad pre-production environments?¶
At the time of writing, Launchpad has 2 pre-production environments,
staging and qastaging. The staging
environment is primarily used to
test the database changes whereas the qastaging
environment is used to
test the code changes. These are deployed on a Canonical ProdStack environment
and the Launchpad team members have shell access to these environments via the
VPN.
We have cron jobs in the Launchpad bastion environment to automatically deploy
new changes in the db-stable
branch to the staging
environment and
new changes in the stable
branch to the qastaging
environment. These
jobs are added to the stg-launchpad
user’s crontab and the scripts used
in these jobs are present in the launchpad-bastion-scripts repository.
Shell access to these environment is available after connecting to the VPN,
logging in to the Launchpad bastion, and switching to the stg-launchpad
user. This user has access to the staging
and qastaging
Juju models.
Even though these environments are mainly used by the Launchpad team, there are other Canonical teams (IS, Store, Kernel, for example) that use these environments in limited ways too.
How to check the database patch application time in the staging
environment?¶
The automatic deployment and application of the database patches to the
staging
environment is done using the auto-upgrade-staging script,
which uses mojo and the Launchpad mojo specs
to do its job, and the staging_restore.sh script. These scripts are run
periodically as cron jobs under the stg-launchpad
account on the Launchpad
bastion.
The database patch application times can be found from files in the ~/logs
directory with a name like 2024-11-17-staging_restore.log
. If the database
patch application failed with an error, it is possible to apply it manually
by running the preflight
juju action on the staging
launchpad-db-update
unit to verify that there are fragile jobs running and
then running the db-update
juju action to apply the patch. The output of
the db-update
juju action will show the patch application time.
What is the fastdowntime
deployment process?¶
Deploying cold database patches to the production Launchpad database requires
having a very short downtime (usually < 10 seconds). That is why the process
to deploy such cold database patches is called fastdowntime
. For details
about hot and cold database patches, see Live Patching.
How do code changes in the stable
branch get added to the db-stable
branch?¶
The same buildbot poller script takes care of periodically merging the latest
changes in the stable
branch to the db-devel
branch. Then the changes
get tested on buildbot before they get merged to the db-stable
branch.
As mentioned in the explanation of the database deployment process, the changes
in the db-stable
branch get submitted for merge to the master
branch
by a Launchpad developer after deploying a database patch. Once the merge
proposal gets approved and merged, buildbot runs the test suite and if it
passes, the changes then get merged to the stable
branch.
How does a Launchpad branch get deployed?¶
When a change is merged to the master
branch, there is a
launchpad-build-charm Jenkins job that builds a Launchpad deployment tarball
of the latest commit in that branch and publishes it to a well-known bucket
on the ProdStack SWIFT storage. All the Launchpad charms use these tarballs
to deploy the Launchpad source and its dependencies.
Similarly, there is a launchpad-build-db-charm Jenkins job that builds a
tarball of the latest commit in the db-devel
branch and publishes it to
SWIFT.
In the production environment, all the Launchpad units except the
launchpad-db-update
unit run the tarball of a specified commit in the
stable
branch. The launchpad-db-update
unit runs the tarball of the
latest commit in the db-stable
branch because it is used to apply the
database patches.
In the staging
environment, all the Launchpad units run the tarball of the
latest commit in the db-stable
branch and in the qastaging
environment,
all the Launchpad units run the tarball of the latest commit in the stable
branch. Due to this, database changes can be deployed to the qastaging
environment only after they have been merged to the master
after the
production deployment and promoted to the stable
branch after a successful
buildbot run.
The database changes have to be deployed in the qastaging
environment
manually by following a process similar to the production fastdowntime
deployment.
How does the Launchpad deployment process work?¶
Launchpad is deployed to a Canonical ProdStack environment using Juju charms
and mojo
. We use the lp
spec in the launchpad-mojo-specs repository
to define the Juju bundle (see lp/bundle.yaml
) used to deploy the Launchpad
stack.
For deploying changes to the pre-production environments, we directly invoke
the mojo run
command from the stg-launchpad
account on the Launchpad
bastion. This is usually only needed when the automatic deployment cron jobs
did not work. Since this account has access to both the staging and qastaging
environments, we have to source either .mojorc.staging
or
.mojorc.qastaging
before running mojo run
. Alternatively, we can also
prefix environment-specific commands with in-model staging
or
in-model qastaging
to run them in the context of that environment.
For deploying changes to the production environment, we use the
upgrade-production
command from the stg-launchpad
account on the
Launchpad bastion to invoke the appropriate mojo
commands on the production
bastion that only IS have access to.
How to deploy code changes to the production environment?¶
The code changes must be made on a branch based on the master
branch
and a merge proposal with the changes must be submitted to the master
branch.
If the code changes require some related database changes, those must be
deployed to production and merged back to the master
branch before
the code changes can be merged to the master
branch.
Similar to the process for deploying the database patch, there is a landing
bot to merge the approved code merge proposals to the master
branch.
After that, buildbot runs the full Launchpad test suite on the master
branch and if it passes, the new changes get merged to the stable
branch.
Once this is done, the changes show up on the launchpad deployable page
and there is a periodic cron job that automatically deploys the new changes
in the stable
branch to the qastaging
environment.
The code changes must be tested and verified in the qastaging
environment
the related commits must be marked as deployable in the deployable site.
Then the changes can be deployed to the production environment by following the instructions in the nodowntime deployment process documentation.
What is the nodowntime
deployment process?¶
Code changes can be deployed to the Launchpad production environment without
causing any user-visible downtime. That is why the process is called the
nodowntime
deployment process. This is achieved by deploying the new code
on all the Launchpad units and performing a coordinated rolling restart of the
Launchpad appserver units.