CPython moves code review to GitHub
CPython replaces its patch-based Mercurial workflow with GitHub pull requests, while retaining its issue tracker and changing how fixes reach supported branches.
A contribution to CPython has required a core developer to perform work that has little to do with judging the proposed change. Downloading a patch, checking whether it still applies, running tests, and carrying the fix across branches all consume the same limited maintainer time. PEP 512 describes this manual process as a reason patches accumulate on the tracker. The difficulty affects people waiting for a review as well as the volunteers trying to provide one.
On February 10, Brett Cannon announced that CPython is accepting changes through GitHub. The repository is now python/cpython. Its Mercurial predecessor is read-only, while bugs.python.org remains the issue tracker. This separation matters because moving source code and review does not automatically move the record of why changes were requested. The migration needs explicit links between those systems.
I value Python chiefly for the libraries that make difficult problems accessible through its language protocols. Those libraries depend on an interpreter that volunteers can maintain. Reducing the mechanical work of accepting a correction is therefore relevant even to developers who never intend to contribute to CPython itself.
Familiarity was part of the decision
The platform choice predates this migration by more than a year. In his January 2016 decision, Cannon explains why he selected GitHub over GitLab. He did not find a decisive difference in their capabilities for this task. Familiarity among core developers and potential contributors favored GitHub, and Guido van Rossum preferred it. Cannon also reported that some core developers expected a familiar workflow to help them become active again.
That reasoning treats knowledge of the contribution process as a maintenance cost. A contributor who already knows pull requests needs less project-specific instruction before submitting a change. A reviewer familiar with the same interface has less procedural work to remember between contributions. Neither benefit establishes that the proposed code is correct. It makes the route to examining that code less dependent on remembering a custom process.
PEP 512 gives the infrastructure side of the argument. Python has been using a custom fork of Rietveld for review, and maintaining that infrastructure consumes volunteer effort. The proposal aims to make accepting a contribution possible through a browser, including the checks needed before committing it. The relevant comparison is the amount of work required to reach a reviewed commit, rather than the visual differences between hosting services.
The January decision also makes the boundaries explicit. Hosting and review move, but the issue tracker and wiki do not. Automation is intended to reduce dependence on the hosting platform over time. This is a pragmatic choice of a familiar service, with integration work required to preserve the parts of Python development that remain elsewhere.
Pull requests become the common route
The launch announcement specifies squash commits. A single contribution produces a single commit, preserving the compact linear history the project wants. Contributors may use several commits while developing a fix, but those intermediate steps do not have to become the permanent organization of CPython history. Review can follow the evolving proposal while the accepted change has one resulting commit.
Protected development branches also change the position of core developers. Cannon says changes must go through pull requests, including changes from developers who previously committed directly. His stated reasons include reducing accidental breakage and making core developers experience the same contribution process they help others navigate. Problems in that process become visible to the people who can improve it.
The announcement describes additional restrictions for branches with different support states. Release managers control approval for security-only branches, and end-of-life branches do not accept pushes. These rules put the branch lifecycle into repository permissions. The ability to propose code and the authority to accept it remain distinct, even though the proposal now uses a common interface.
An issue reference needs special care because GitHub interprets familiar issue-number syntax itself. CPython adopts bpo-NNNN to identify bugs.python.org issues. The launch announcement says a reference in a pull request title or comment associates the pull request with the tracker issue. The same form in a commit message generates a comment on that issue linking the commit. This preserves the connection between a report and its implementation without making two independent issue-number spaces look interchangeable.
Backports become independent changes
The move changes the direction in which fixes travel. The previous workflow generally committed to the oldest affected branch and merged forward, with Python 2.7 requiring separate treatment. Cannon describes races between committers while changes moved through that sequence. A contributor starting on the newest development branch also worked against the direction expected by the old procedure.
The new workflow accepts the development change and cherry-picks it into other applicable branches. Each backport is an independent commit. This allows the development fix to proceed while maintainers decide whether a supported version should receive it. A conflict in one older branch no longer has to prevent acceptance into the development branch.
Independence creates a tracking obligation. Accepting a fix into one branch does not establish that it exists in another. The announcement provides labels such as backport to 3.6 to record outstanding work. Separate pull requests can run continuous integration for each backport, since a change that works in the development branch may need different code in an older one. The relationship between those changes remains important even though they no longer form one forward-merge sequence.
At launch, cherry-picking still requires the command line. Cannon explicitly distinguishes changes that can be accepted entirely in the web interface from changes needing backports. Automatic generation of backport pull requests is future work in his announcement. The migration supplies a different way to organize the work before it supplies automation for every part of that work.
Automated checks have defined limits
Travis now runs checks for pull requests, including debug builds with GCC and Clang. The launch announcement also lists documentation validation and Python.h compatibility with C++. These checks remove repeated manual steps from common contributions and attach their results to the proposed change. Reviewers can inspect the patch with that evidence already available.
The initial setup does not cover every supported platform. Cannon specifically notes that the Travis checks do not exercise macOS or Windows changes in this arrangement. A successful result therefore describes the checks that ran. It does not establish universal platform compatibility, and a platform-specific correction still needs evidence appropriate to that platform.
Passing status checks are not initially a requirement for committing. The announcement attributes that decision to test flakiness and the disruption a strict gate could cause before the team knows the setup is sufficiently stable. GitHub still displays failed or incomplete results. That distinction leaves reviewers responsible for interpreting the available evidence while the automation becomes part of ordinary work.
Codecov adds coverage information to pull requests and runs a non-debug build in the process described by Cannon. Some tests are skipped because they delay completion of the coverage run. The report is useful precisely when its scope remains visible. A coverage change can inform review without claiming to account for every interpreter path or every test configuration.
Contributor identity crosses both services
The contributor license agreement remains associated with the contributor account on bugs.python.org. GitHub therefore cannot determine signing status from a pull request alone. The migration connects the GitHub username to that tracker account and uses a bot, The Knights Who Say Ni, to check the relationship. Its labels tell reviewers whether the agreement requirement has been met.
The failure cases need different remedies. A contributor may need to sign the agreement or may already have signed it but need to connect the two accounts. The bot explains how to resolve the problem. Cannon also describes removing a negative label to trigger another check after the contributor corrects their account information. No label indicates a possible failure of the checking process, which is different from a confirmed unsigned contribution.
I regard this kind of explicit state as useful maintenance design. A review interface should make missing administrative information visible without requiring every reviewer to reconstruct it. The same principle applies to issue references and backport labels, where a proposed change carries obligations that the code diff alone cannot express.
The remaining NEWS-file work shows why moving repositories is only part of changing a workflow. Cannon identifies conflicts in Misc/NEWS as a recurring problem when fixes span versions. His proposed next step is an individual file for each entry, collected into release notes later. As of the migration announcement, that work and automatic cherry-pick pull requests remain plans. The new repository already changes review and branch handling, while those specific sources of backport effort still require maintainer attention.