blob: f7002cdda51a77789ce4bebc561f96576a471f97 [file] [log] [blame]
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Release process - Cargo Contributor Guide</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root to javascript -->
<script>
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Cargo Contributor Guide</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/rust-lang/cargo/tree/master/src/doc/contrib/src" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/rust-lang/cargo/edit/master/src/doc/contrib/src/process/release.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="release-process"><a class="header" href="#release-process">Release process</a></h1>
<p>Cargo is released with <code>rustc</code> using a <a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">“train model”</a>. After a
change lands in Cargo’s master branch, it will be synced with the
<a href="https://github.com/rust-lang/rust/">rust-lang/rust</a> repository by a Cargo team member, which happens about once a
week. If there are complications, it can take longer. After it is synced and
merged, the changes will appear in the next nightly release, which is usually
published around 00:30 UTC.</p>
<p>After changes are in the nightly release, they will make their way to the
stable release anywhere from 6 to 12 weeks later, depending on when during the
cycle it landed.</p>
<p>The current release schedule is posted on the <a href="https://forge.rust-lang.org/">Rust Forge</a>. See the <a href="https://forge.rust-lang.org/release/process.html">release
process</a> for more details on how Rust’s releases are created. Rust releases
are managed by the <a href="https://www.rust-lang.org/governance/teams/operations#release">Release team</a>.</p>
<h2 id="build-process"><a class="header" href="#build-process">Build process</a></h2>
<p>The build process for Cargo is handled as part of building Rust. Every PR on
the <a href="https://github.com/rust-lang/rust/">rust-lang/rust</a> repository creates a full collection of release artifacts
for every platform. The code for this is in the <a href="https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/dist.rs"><code>dist</code> bootstrap module</a>.
Every night at 00:00 UTC, the artifacts from the most recently merged PR are
promoted to the nightly release channel. A similar process happens for beta
and stable releases.</p>
<h2 id="submodule-updates"><a class="header" href="#submodule-updates">Submodule updates</a></h2>
<p>Cargo is tracked in the <a href="https://github.com/rust-lang/rust/">rust-lang/rust</a> repository using a <a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules">git submodule</a>.
It is updated manually about once a week by a Cargo team member.
However, anyone is welcome to update it as needed.</p>
<p><a href="https://github.com/ehuss/">@ehuss</a> has a tool called <a href="https://github.com/ehuss/subup">subup</a> to automate the process of updating the submodule, updating the lockfile, running tests, and creating a PR.
Running the tests ahead-of-time helps avoid long cycle times waiting for bors if there are any errors.
Subup will also provide a message to include in the PR with a list of all PRs it covers.
Posting this in the PR message also helps create reference links on each Cargo PR to the submodule update PR to help track when it gets merged.</p>
<p>The following is an example of the command to run in a local clone of rust-lang/rust to run a certain set of tests of things that are likely to get broken by a Cargo update:</p>
<pre><code class="language-bash">subup --up-branch update-cargo \
--commit-message "Update cargo" \
--test="src/tools/linkchecker tidy \
src/tools/cargo \
src/tools/rustfmt" \
src/tools/cargo
</code></pre>
<p>If doing a <a href="#beta-backports">beta backport</a>, the command is similar, but needs to point to the correct branches:</p>
<pre><code class="language-bash">subup --up-branch update-beta-cargo \
--rust-branch beta \
--set-config rust.channel=beta \
--commit-message "[beta] Update cargo" \
--test="src/tools/linkchecker tidy \
src/tools/cargo \
src/tools/rustfmt" \
rust-1.66.0:src/tools/cargo
</code></pre>
<h2 id="version-updates"><a class="header" href="#version-updates">Version updates</a></h2>
<p>Shortly after each major release, a Cargo team member will post a PR to update
Cargo’s version in <code>Cargo.toml</code>. Cargo’s library is permanently unstable, so
its version number starts with a <code>0</code>. The minor version is always 1 greater
than the Rust release it is a part of, so cargo 0.49.0 is part of the 1.48
Rust release. The <a href="https://github.com/rust-lang/cargo/blob/master/src/doc/src/CHANGELOG.md">CHANGELOG</a> is also usually updated at this time.</p>
<p>Also, any version-specific checks that are no longer needed can be removed.
For example, some tests are disabled on stable if they require some nightly
behavior. Once that behavior is available on the new stable release, the
checks are no longer necessary. (I usually search for the word “nightly” in
the testsuite directory, and read the comments to see if any of those nightly
checks can be removed.)</p>
<p>Sometimes Cargo will have a runtime check to probe <code>rustc</code> if it supports a
specific feature. This is usually stored in the <a href="https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/build_context/target_info.rs"><code>TargetInfo</code></a> struct. If this
behavior is now stable, those checks should be removed.</p>
<p>Cargo has several other packages in the <a href="https://github.com/rust-lang/cargo/tree/master/crates"><code>crates/</code> directory</a>. If any of these
packages have changed, the version should be bumped <strong>before the beta
release</strong>. It is rare that these get updated. Bumping these as-needed helps
avoid churning incompatible version numbers. This process should be improved
in the future!</p>
<p><a href="https://github.com/ehuss/">@ehuss</a> has a tool called <a href="https://github.com/ehuss/cargo-new-release">cargo-new-release</a> to automate the process of doing a version bump.
It runs through several steps:</p>
<ol>
<li>Creates a branch</li>
<li>Updates the version numbers</li>
<li>Creates a changelog for anything on the master branch that is not part of beta</li>
<li>Creates a changelog for anything on the beta branch</li>
</ol>
<p>It opens a browser tab for every PR in order to review each change.
It places each PR in the changelog with its title, but usually every PR should be rewritten to explain the change from the user’s perspective.
Each PR should also be categorized as an Addition, Change, Fix, or Nightly-only change.
Most PRs are deleted, since they are not relevant to users of Cargo.
For example, remove all PRs related to Cargo internals, infrastructure, documentation, error changes, refactorings, etc.
Usually about half of the PRs get removed.
This process usually takes @ehuss about an hour to finish.</p>
<h2 id="docs-publishing"><a class="header" href="#docs-publishing">Docs publishing</a></h2>
<p>Docs are automatically published during the Rust release process. The nightly
channel’s docs appear at <a href="https://doc.rust-lang.org/nightly/cargo/">https://doc.rust-lang.org/nightly/cargo/</a>. Once
nightly is promoted to beta, those docs will appear at
<a href="https://doc.rust-lang.org/beta/cargo/">https://doc.rust-lang.org/beta/cargo/</a>. Once the stable release is made, it
will appear on <a href="https://doc.rust-lang.org/cargo/">https://doc.rust-lang.org/cargo/</a> (which is the “current”
stable) and the release-specific URL such as
<a href="https://doc.rust-lang.org/1.46.0/cargo/">https://doc.rust-lang.org/1.46.0/cargo/</a>.</p>
<p>The code that builds the documentation is located in the <a href="https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/doc.rs"><code>doc</code> bootstrap
module</a>.</p>
<h2 id="cratesio-publishing"><a class="header" href="#cratesio-publishing">crates.io publishing</a></h2>
<p>Cargo’s library and its related dependencies (like <code>cargo-util</code>) are published
to <a href="https://crates.io/">crates.io</a> as part of the 6-week stable release process by the <a href="https://www.rust-lang.org/governance/teams/operations#release">Release
team</a>. The release process involves a series of steps:</p>
<ol>
<li>The Release team’s automation scripts (see <a href="https://github.com/rust-lang/simpleinfra/">https://github.com/rust-lang/simpleinfra/</a>) will run <a href="https://github.com/rust-lang/promote-release"><code>promote-release</code></a> which will create a tag in the <code>rust-lang/cargo</code> repository associated with the version of the cargo submodule for that release.</li>
<li>The creation of a tag will trigger the <a href="https://github.com/rust-lang/cargo/blob/master/.github/workflows/release.yml">release workflow</a> in <code>rust-lang/cargo</code>.</li>
<li>The release workflow will run the <a href="https://github.com/rust-lang/cargo/blob/master/publish.py"><code>publish.py</code> script</a> on the commit associated with the tag.</li>
<li>The <code>publish.py</code> script will run <code>cargo publish</code> on any crates that are not already published.</li>
</ol>
<p>On very rare cases, the Cargo team may decide to manually publish a new
release to <a href="https://crates.io/">crates.io</a>. For example, this may be necessary if there is a
problem with the current version that only affects API users, and does not
affect the <code>cargo</code> binary shipped in the stable release. In this situation,
PRs should be merged to the associated stable release branch in the cargo repo
(like <code>rust-1.70.0</code>) that fix the issue and bump the patch version of the
affected package. Then you need to work with the Release Team to get a release
published to crates.io.<sup class="footnote-reference"><a href="#release-problem">1</a></sup></p>
<p>Some packages are not published automatically because they are not part of the
Rust release train. This currently only includes the <a href="https://github.com/rust-lang/cargo/tree/master/crates/home"><code>home</code></a> package. These
are published manually on an as-needed or as-requested basis by whoever has
permissions (currently <a href="https://github.com/ehuss/">@ehuss</a> or the Release/Infra team)<sup class="footnote-reference"><a href="#fix-manual-release">2</a></sup>.</p>
<div class="footnote-definition" id="release-problem"><sup class="footnote-definition-label">1</sup>
<p>Unfortunately there are some complications with this process. See <a href="https://github.com/rust-lang/cargo/issues/14538">https://github.com/rust-lang/cargo/issues/14538</a> for more detail, and thoughts on how to improve this.</p>
</div>
<div class="footnote-definition" id="fix-manual-release"><sup class="footnote-definition-label">2</sup>
<p>This should be fixed, see <a href="https://forge.rust-lang.org/policies/crate-ownership.html">crate ownership policy</a> about removing ownership. Also see <a href="https://github.com/rust-lang/cargo/issues/14538">https://github.com/rust-lang/cargo/issues/14538</a> for problems with tagging. In general, these should be published from GitHub Actions, but we don’t have the infrastructure set up for that, yet.</p>
</div>
<h2 id="beta-backports"><a class="header" href="#beta-backports">Beta backports</a></h2>
<p>If there is a regression or major problem detected during the beta phase, it
may be necessary to backport a fix to beta. The process is documented in the
<a href="https://forge.rust-lang.org/release/beta-backporting.html">Beta Backporting</a> page.</p>
<h2 id="stable-backports"><a class="header" href="#stable-backports">Stable backports</a></h2>
<p>In (hopefully!) very rare cases, a major regression or problem may be reported
after the stable release. Decisions about this are usually coordinated between
the <a href="https://www.rust-lang.org/governance/teams/operations#release">Release team</a> and the Cargo team. There is usually a high bar for making
a stable patch release, and the decision may be influenced by whether or not
there are other changes that need a new stable release.</p>
<p>The process here is similar to the beta-backporting process. The
<a href="https://github.com/rust-lang/cargo/">rust-lang/cargo</a> branch is the same as beta (<code>rust-1.XX.0</code>). The
<a href="https://github.com/rust-lang/rust/">rust-lang/rust</a> branch is called <code>stable</code>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../process/working-on-cargo.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../process/rfc.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../process/working-on-cargo.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../process/rfc.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>