build: use workflows for bumping versions and cargo publishing on the CI (#13995)

This commit is contained in:
David Sherret 2022-03-30 16:37:00 -04:00 committed by GitHub
parent f61b2c0b11
commit 5cab3e7dba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 306 additions and 74 deletions

42
.github/workflows/cargo_publish.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: cargo_publish
on: workflow_dispatch
jobs:
build:
name: cargo publish
runs-on: ubuntu-20.04-xl
timeout-minutes: 90
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: full
RUSTC_FORCE_INCREMENTAL: 1
steps:
- name: Configure git
run: |
git config --global core.symlinks true
git config --global fetch.parallel 32
- name: Clone repository
uses: actions/checkout@v2
with:
submodules: recursive
- uses: dtolnay/rust-toolchain@stable
- name: Install deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.19.3
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: ./tools/release/03_publish_crates.ts --real
- name: Create release tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./tools/release/04_create_release_tag.ts

View File

@ -89,9 +89,9 @@ jobs:
- name: Install Deno
if: matrix.job == 'lint'
run: |
curl -fsSL https://deno.land/x/install/install.sh | sh -s v1.13.2
echo "$HOME/.deno/bin" >> $GITHUB_PATH
uses: denoland/setup-deno@v1
with:
deno-version: v1.19.3
- name: Install Python
uses: actions/setup-python@v1

57
.github/workflows/version_bump.yml vendored Normal file
View File

@ -0,0 +1,57 @@
name: version_bump
on:
workflow_dispatch:
inputs:
releaseKind:
description: 'Kind of version bump'
default: 'patch'
type: choice
options:
- patch
- minor
- major
required: true
jobs:
build:
name: version bump
runs-on: ubuntu-20.04-xl
timeout-minutes: 90
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: full
RUSTC_FORCE_INCREMENTAL: 1
steps:
- name: Configure git
run: |
git config --global core.symlinks true
git config --global fetch.parallel 32
- name: Clone repository
uses: actions/checkout@v2
with:
submodules: recursive
- uses: dtolnay/rust-toolchain@stable
- name: Install deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.19.3
- name: Run version bump
run: |
git remote add upstream https://github.com/denoland/deno
./tools/release/01_bump_crate_versions.ts --${{github.event.inputs.releaseKind}}
- name: Create PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_WORKFLOW_ACTOR: ${{ github.actor }}
run: |
git config user.email "${{ github.actor }}@users.noreply.github.com"
git config user.name "${{ github.actor }}"
./tools/release/02_create_pr.ts

View File

@ -1155,6 +1155,7 @@ fn legacy_main_resolve(
#[cfg(test)]
mod tests {
use super::*;
use crate::compat::STD_URL_STR;
fn testdir(name: &str) -> PathBuf {
let c = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
@ -1233,8 +1234,10 @@ mod tests {
fn builtin_http() {
let cwd = testdir("basic");
let main = Url::from_file_path(cwd.join("main.js")).unwrap();
let expected =
Url::parse("https://deno.land/std@0.132.0/node/http.ts").unwrap();
let expected = Url::parse(STD_URL_STR)
.unwrap()
.join("node/http.ts")
.unwrap();
let actual = node_resolve("http", main.as_str(), &cwd).unwrap();
assert!(matches!(actual, ResolveResponse::Esm(_)));

View File

@ -20,7 +20,7 @@ pub use esm_resolver::NodeEsmResolver;
// each release, a better mechanism is preferable, but it's a quick and dirty
// solution to avoid printing `X-Deno-Warning` headers when the compat layer is
// downloaded
static STD_URL_STR: &str = "https://deno.land/std@0.132.0/";
pub(crate) static STD_URL_STR: &str = "https://deno.land/std@0.132.0/";
static SUPPORTED_MODULES: &[&str] = &[
"assert",

View File

@ -64,63 +64,62 @@ previous release and start cherry-picking newer commits from the `main`.
Once all relevant commits are cherry-picked, push the branch to the upstream and
verify on GitHub that everything looks correct.
1. Update your local branch (`v1.XX` for patch or `main` for minor) and checkout
another branch (e.g. `release_#.#.#`).
### Phase 1: Bumping versions
2. Run `./tools/release/01_bump_crate_versions.ts` to increase the versions of
all crates including the CLI. If you are doing a CLI patch release, answer
`y` to the _Increment patch?_ prompt.
1. After releasing deno_std, go to the "version_bump" workflow in the CLI repo's
actions: https://github.com/denoland/deno/actions/workflows/version_bump.yml
3. The above command will update the `Releases.md` file. Review it and ensure
its output is correct. **If you are cutting a minor release**: make sure that
there are no duplicate entries in previous releases; most often commits with
`fix` prefix would have been included in patch releases.
2. Click on the "Run workflow" button.
1. In the drop down, select the minor branch if doing a path release or the
main branch if doing a minor release.
2. For the kind of release, select either "patch", "minor", or "major".
3. Run the workflow.
4. Update link in `cli/compat/mod.rs` with the released version of `deno_std`
and do a search through the tests to find std urls that need to be updated.
3. Wait for the workflow to complete and for a pull request to be automatically
opened.
5. Create a PR for these changes. **If you are cutting a patch release**: make
sure to target `v1.XX` branch instead of `main` in your PR.
4. Review the pull request and make any necessary changes.
6. Make sure CI pipeline passes (DO NOT merge yet).
5. Merge it.
7. Publish the crates to `crates.io` by running
`./tools/release/02_publish_crates.ts`
### Phase 2: Publish
8. Merge the PR.
1. Go to the "cargo_publish" workflow in the CLI repo's actions:
https://github.com/denoland/deno/actions/workflows/cargo_publish.yml
9. Create a tag with the version number (with `v` prefix).
2. Run it on the same branch that you used before and wait for it to complete.
10. Wait for CI pipeline on the created tag branch to pass.
3. This CI run create a tag which triggers a second CI run that publishes the
GitHub draft release.
The CI pipeline will create a release draft on GitHub
(https://github.com/denoland/deno/releases). Update the draft with the
contents of `Releases.md` that you previously added.
The CI pipeline will create a release draft on GitHub
(https://github.com/denoland/deno/releases). Update the draft with the
contents of `Releases.md` that you previously added.
11. Upload Apple M1 build (`deno-aarch64-apple-darwin.zip`) to the release draft
and to https://console.cloud.google.com/storage/browser/dl.deno.land
4. Upload Apple M1 build (`deno-aarch64-apple-darwin.zip`) to the release draft
and to https://console.cloud.google.com/storage/browser/dl.deno.land
```
cargo build --release
cd target/release
zip -r deno-aarch64-apple-darwin.zip deno
```
```
cargo build --release
cd target/release
zip -r deno-aarch64-apple-darwin.zip deno
```
12. Publish the release on Github
5. Publish the release on Github
13. Update the Deno version on the website by updating
https://github.com/denoland/dotland/blob/main/versions.json.
6. Update the Deno version on the website by updating
https://github.com/denoland/dotland/blob/main/versions.json.
14. Push a new tag to [`manual`](https://github.com/denoland/manual). The tag
must match the CLI tag; you don't need to create dedicated commit for that
purpose, it's enough to tag the latest commit in that repo.
7. Push a new tag to [`manual`](https://github.com/denoland/manual). The tag
must match the CLI tag; you don't need to create dedicated commit for that
purpose, it's enough to tag the latest commit in that repo.
15. For minor releases: make sure https://github.com/mdn/browser-compat-data has
been updated to reflect Web API changes in this release. Usually done ahead
of time by @lucacasonato.
8. For minor releases: make sure https://github.com/mdn/browser-compat-data has
been updated to reflect Web API changes in this release. Usually done ahead
of time by @lucacasonato.
16. **If you are cutting a patch release**: open a PR that forwards all commits
created in the release process to the `main` branch.
9. **If you are cutting a patch release**: open a PR that forwards all commits
created in the release process to the `main` branch.
## Updating `doc.deno.land`

View File

@ -1,4 +1,4 @@
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo,git --allow-net --no-check
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { DenoWorkspace } from "./deno_workspace.ts";
import { GitLogOutput, path, semver } from "./deps.ts";
@ -8,8 +8,19 @@ const repo = workspace.repo;
const cliCrate = workspace.getCliCrate();
const originalCliVersion = cliCrate.version;
// update the std version used in the code
await updateStdVersion();
// increment the cli version
await cliCrate.promptAndIncrement();
if (Deno.args.some((a) => a === "--patch")) {
await cliCrate.increment("patch");
} else if (Deno.args.some((a) => a === "--minor")) {
await cliCrate.increment("minor");
} else if (Deno.args.some((a) => a === "--major")) {
await cliCrate.increment("major");
} else {
await cliCrate.promptAndIncrement();
}
// increment the dependency crate versions
for (const crate of workspace.getCliDependencyCrates()) {
@ -17,7 +28,7 @@ for (const crate of workspace.getCliDependencyCrates()) {
}
// update the lock file
await workspace.getCliCrate().cargoCheck();
await workspace.getCliCrate().cargoUpdate("--workspace");
// try to update the Releases.md markdown text
try {
@ -101,3 +112,26 @@ async function getGitLog() {
);
}
}
async function updateStdVersion() {
const newStdVersion = await getLatestStdVersion();
const compatFilePath = path.join(cliCrate.folderPath, "compat/mod.rs");
const text = Deno.readTextFileSync(compatFilePath);
Deno.writeTextFileSync(
compatFilePath,
text.replace(/std@[0-9]+\.[0-9]+\.[0-9]+/, `std@${newStdVersion}`),
);
}
async function getLatestStdVersion() {
const url =
"https://raw.githubusercontent.com/denoland/deno_std/main/version.ts";
const result = await fetch(url);
const text = await result.text();
const version = /"([0-9]+\.[0-9]+\.[0-9]+)"/.exec(text);
if (version == null) {
throw new Error(`Could not find version in text: ${text}`);
} else {
return version[1];
}
}

51
tools/release/02_create_pr.ts Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-env --allow-net --allow-run=cargo,git --no-check
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { DenoWorkspace } from "./deno_workspace.ts";
import { createOctoKit, getGitHubRepository } from "./deps.ts";
const octoKit = createOctoKit();
const workspace = await DenoWorkspace.load();
const repo = workspace.repo;
const cliCrate = workspace.getCliCrate();
const originalBranch = await repo.gitCurrentBranch();
const newBranchName = `release_${cliCrate.version.replace(/\./, "_")}`;
// Create and push branch
console.log(`Creating branch ${newBranchName}...`);
await repo.gitBranch(newBranchName);
await repo.gitAdd();
await repo.gitCommit(cliCrate.version);
console.log("Pushing branch...");
await repo.gitPush("-u", "origin", "HEAD");
// Open PR
console.log("Opening PR...");
const openedPr = await octoKit.request("POST /repos/{owner}/{repo}/pulls", {
...getGitHubRepository(),
base: originalBranch,
head: newBranchName,
draft: true,
title: cliCrate.version,
body: getPrBody(),
});
console.log(`Opened PR at ${openedPr.data.url}`);
function getPrBody() {
let text = `Bumped versions for ${cliCrate.version}\n\n` +
`Please ensure:\n` +
`- [ ] Crate versions are bumped correctly\n` +
`- [ ] deno_std version is incremented in the code\n` +
`- [ ] Releases.md is updated correctly\n\n` +
`To make edits to this PR:\n` +
"```shell\n" +
`git fetch upstream ${newBranchName} && git checkout -b ${newBranchName} upstream/${newBranchName}\n` +
"```\n";
const actor = Deno.env.get("GH_WORKFLOW_ACTOR");
if (actor != null) {
text += `\ncc @${actor}`;
}
return text;
}

View File

@ -1,23 +0,0 @@
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo --allow-net=crates.io
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { DenoWorkspace } from "./deno_workspace.ts";
import { getCratesPublishOrder } from "./deps.ts";
const workspace = await DenoWorkspace.load();
const cliCrate = workspace.getCliCrate();
const dependencyCrates = getCratesPublishOrder(
workspace.getCliDependencyCrates(),
);
try {
for (const [i, crate] of dependencyCrates.entries()) {
await crate.publish();
console.log(`Published ${i + 1} of ${dependencyCrates.length} crates.`);
}
await cliCrate.publish();
} finally {
// system beep to notify error or completion
console.log("\x07");
}

View File

@ -0,0 +1,48 @@
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo --allow-net=crates.io --no-check
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { DenoWorkspace } from "./deno_workspace.ts";
import { Crate, getCratesPublishOrder } from "./deps.ts";
const isReal = parseIsReal();
console.log(`Running a ${isReal ? "real" : "dry"} cargo publish...`);
const workspace = await DenoWorkspace.load();
const cliCrate = workspace.getCliCrate();
const dependencyCrates = getCratesPublishOrder(
workspace.getCliDependencyCrates(),
);
try {
for (const [i, crate] of dependencyCrates.entries()) {
await publishCrate(crate);
console.log(`Finished ${i + 1} of ${dependencyCrates.length} crates.`);
}
await publishCrate(cliCrate);
} finally {
// system beep to notify error or completion
console.log("\x07");
}
async function publishCrate(crate: Crate) {
if (isReal) {
await crate.publish();
} else {
await crate.publishDryRun();
}
}
function parseIsReal() {
const isReal = Deno.args.some((a) => a === "--real");
const isDry = Deno.args.some((a) => a === "--dry");
// force the call to be explicit and provide one of these
// so that it's obvious what's happening
if (!isDry && !isReal) {
console.error("Please run with `--dry` or `--real`.");
Deno.exit(1);
}
return isReal;
}

View File

@ -0,0 +1,17 @@
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo --no-check
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { DenoWorkspace } from "./deno_workspace.ts";
const workspace = await DenoWorkspace.load();
const repo = workspace.repo;
const cliCrate = workspace.getCliCrate();
await repo.gitFetchTags("origin");
const tags = await repo.getGitTags();
if (tags.has(cliCrate.version)) {
console.log(`Tag ${cliCrate.version} already exists.`);
} else {
await repo.gitTag(cliCrate.version);
await repo.gitPush(cliCrate.version);
}

View File

@ -12,7 +12,10 @@ export class DenoWorkspace {
static async load(): Promise<DenoWorkspace> {
return new DenoWorkspace(
await Repo.load("deno", DenoWorkspace.rootDirPath),
await Repo.load({
name: "deno",
path: DenoWorkspace.rootDirPath,
}),
);
}

View File

@ -1,3 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
export * from "https://raw.githubusercontent.com/denoland/automation/0.5.0/mod.ts";
export * from "https://raw.githubusercontent.com/denoland/automation/0.9.0/mod.ts";
export * from "https://raw.githubusercontent.com/denoland/automation/0.9.0/github_actions.ts";