While the R 4.0 migration has been functionally complete for quite a
while, the recent migration of r-java
and its dependents gives a good
opportunity to write a retrospective on the technical issues with
large-scale migrations in conda-forge
and how we solved them.
The R 4.0 migration rebuilt every package in conda-forge
that had
r-base
as a requirement, including more than 2200 feedstocks. A
migration of this size in conda-forge
faces several hurdles. First,
since every feedstock is a separate GitHub repository, one needs to
merge more 2200 pull requests (PRs). Second, conda-forge
's packages
on anaconda.org
are behind a CDN (content delivery network). This
service reduces web hosting costs for Anaconda Inc. but introduces an
approximately 30 minute delay from when a package is uploaded to
anaconda.org
and when it will appear as available using conda
from
the command line. Thus, even if the dependencies of a package have been
built, we have to wait until they appear on the CDN before we can
successfully issue the next PR and have it build correctly. Finally, the
existing bot and conda
infrastructure limited the throughput of the
migrations, due in part to the speed of the conda
solver.
Given the size of the R 4.0 migration, we took this opportunity to try
out a bunch of new technology to speed up large-scale migrations. The
main enhancements were using GitHub Actions to automerge PRs, using
mamba
to quickly check for solvability of package environments, and
enabling long-running migration jobs for the autotick bot. All told, the
bulk of the feedstocks for R 4.0 were rebuilt in less than a week, with
many PRs being merged in 30 minutes or less from when they were issued.
These enhancements to the autotick bot and conda-forge
infrastructure
can be used to enhance future migrations (e.g., Python 3.9) and reduce
maintenance burdens for feedstocks.
Automerging conda-forge PRs
In a typical migration on conda-forge
, we issue a PR to a feedstock
and then ask the feedstock maintainers to make sure it passes and merge
it. In the case of the R 4.0 migration, the maintainers of R packages on
conda-forge
use a maintenance team (i.e., @conda-forge/r
) on the
vast majority of feedstocks. This team is small and so merging over 2000
PRs by hand is a big undertaking. Thus, with their permission, we added
the conda-forge
automerge functionality to all R feedstocks that they
maintain. The automerge bot, which relies on GitHub Actions, is able to
automatically merge any PR from the autotick bot that passes the recipe
linter, the continuous integration services, and has the special
[bot automerge]
slug in the PR title. This feature removed the
bottleneck of waiting for maintainers to merge PRs and reduced the
maintenance burden on the R maintenance team.
Checking Solvability with mamba
While being able to automatically merge PRs removed much of the work of performing the R 4.0 migration, it relied on the PR building correctly the first time it was issued. Due to the CDN delays and the build times of a package's dependencies, the dependencies of a package may not be immediately available after all of their migration PRs are merged. If the bot issued the packages migration PR before the dependents are available, the PR would fail with an unsolvable environment and have to be restarted manually. This failure would negate any of the benefits of using automerge in the first place.
To control for this edge case, we employed the mamba
package to check
for the solvability of a PR's environments before the PR was issued.
mamba
is a fast alternative to conda
that produces solutions for
environments orders of magnitude more quickly. Since, we have to perform
our checks of PR environments many times, an extremely fast solver was
essential for making the code efficient enough to run as part of the
autotick bot. We ended up using mamba to try to install the dependencies
for every variant produced by the feedstock to be migrated. With this
check in place, the autotick bot was able to issue migration PRs that
passed on the first try and were thus automatically merged, many within
30 minutes or less.
Improving the Autotick Bot's Efficiency
Finally, we made several upgrades to the autotick bot infrastructure to increase the uptime of the bot and its efficiency. First, we moved from an hourly cron job to a set of chained CI jobs. This change eliminated downtime between the runs of the bot. Second, we started to refactor the autotick bot from one monolithic piece of code into a distributed set of microservices which perform various independent tasks in parallel. These independent tasks, used for things like checking the statuses of previously issued PRs, are run separately allowing the bot to spend more time issuing PRs. Finally, we optimized the internal prioritization of the PRs to make sure the bot was spending more time on larger migrations where there is more work to do. More work on the autotick bot infrastructure, including work done by Vinicius Cerutti as part of the Google Summer of Code program, will further streamline the bot's operation.
Despite some initial hiccups with the bot infrastructure, the migration
ran quite smoothly for an endeavor of its size. The vast majority of
migration PRs were completed within a week from when we started, which
is a first for a migration of this size on conda-forge
. The largest
issue was solved recently, with the fixing of the openjdk
recipe and
the removal of aarch64
and ppc64le
builds from r-java
, enabling
the last large piece of the R ecosystem to be updated.
Looking forward, the improvements we made for the R 4.0 migration seem
broadly applicable to other migration tasks, including the yearly python
minor version bump. These kinds of large-scale migrations are
particularly suitable, since they usually involve few changes to the
feedstock itself and usually fail on CI when a broken package would be
produced. Faster migrations will help to provide the latest features to
downstream users and keep transition times to a minimum, helping to
foster greater stability of the ecosystem and the seamless experience
users have come to expect from conda-forge
.