diff --git a/tools/cut_a_release.md b/tools/cut_a_release.md index ca6cb9ff3f..aa5e0eb47d 100644 --- a/tools/cut_a_release.md +++ b/tools/cut_a_release.md @@ -64,65 +64,40 @@ 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. Checkout a branch for releasing crate dependencies (e.g. `deps_#.#.#`). - -2. Run `./tools/release/01_bump_dependency_crate_versions.ts` to increase the - minor versions of all crates in the `bench_util`, `core`, `ext`, and - `runtime` directories. - -3. Commit these changes with a commit message like - `chore: bump crate version for #.#.#` and create a PR for this change. **If - you are cutting a patch release**: make sure to target `v1.XX` branch instead - of `main` in your PR. - -4. Make sure CI pipeline passes (DO NOT merge yet). - -5. Run `./tools/release/02_publish_dependency_crates.ts` to publish these bumped - crates to `crates.io` - - **Make sure that `cargo` is logged on with a user that has permissions to - publish those crates.** - - If there are any problems when you publish, that require you to change the - code, then after applying the fixes they should be committed and pushed to - the PR. - -6. Once all crates are published merge the PR. - -7. Update your local branch (`v1.XX` for patch or `main` for minor) and checkout +1. Update your local branch (`v1.XX` for patch or `main` for minor) and checkout another branch (e.g. `release_#.#.#`). -8. Run `./tools/release/03_bump_cli_version.ts` to bump the CLI version. +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. -9. If you are doing a patch release, answer `y` to the _Increment patch?_ - prompt. +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. -10. 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. +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. -11. 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. +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. -12. 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. +6. Make sure CI pipeline passes (DO NOT merge yet). -13. Make sure CI pipeline passes. +7. Publish the crates to `crates.io` by running + `./tools/release/02_publish_crates.ts` -14. Publish `cli` crate to `crates.io`: `cd cli && cargo publish` +8. Merge the PR. -15. Merge the PR. +9. Create a tag with the version number (with `v` prefix). -16. Create a tag with the version number (with `v` prefix). - -17. Wait for CI pipeline on the created tag branch to pass. +10. Wait for CI pipeline on the created tag branch to pass. 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. -18. Upload Apple M1 build (`deno-aarch64-apple-darwin.zip`) to the release draft +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 ``` @@ -131,20 +106,20 @@ verify on GitHub that everything looks correct. zip -r deno-aarch64-apple-darwin.zip deno ``` -19. Publish the release on Github +12. Publish the release on Github -20. Update the Deno version on the website by updating +13. Update the Deno version on the website by updating https://github.com/denoland/dotland/blob/main/versions.json. -21. Push a new tag to [`manual`](https://github.com/denoland/manual). The tag +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. -22. For minor releases: make sure https://github.com/mdn/browser-compat-data has +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. -23. **If you are cutting a patch release**: open a PR that forwards all commits +16. **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` diff --git a/tools/release/01_bump_crate_versions.ts b/tools/release/01_bump_crate_versions.ts new file mode 100644 index 0000000000..a29bdd554f --- /dev/null +++ b/tools/release/01_bump_crate_versions.ts @@ -0,0 +1,103 @@ +#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +import { DenoWorkspace } from "./deno_workspace.ts"; +import { GitLogOutput, path, semver } from "./deps.ts"; + +const workspace = await DenoWorkspace.load(); +const repo = workspace.repo; +const cliCrate = workspace.getCliCrate(); +const originalCliVersion = cliCrate.version; + +// increment the cli version +await cliCrate.promptAndIncrement(); + +// increment the dependency crate versions +for (const crate of workspace.getDependencyCrates()) { + await crate.increment("minor"); +} + +// update the lock file +await workspace.getCliCrate().cargoCheck(); + +// try to update the Releases.md markdown text +try { + await updateReleasesMd(); +} catch (err) { + console.error(err); + console.error( + "Updating Releases.md failed. Please manually run " + + "`git log --oneline VERSION_FROM..VERSION_TO` and " + + "use the output to update Releases.md", + ); +} + +async function updateReleasesMd() { + const filePath = path.join(DenoWorkspace.rootDirPath, "Releases.md"); + const oldFileText = await Deno.readTextFile(filePath); + const insertText = await getReleasesMdText(); + + await Deno.writeTextFile( + filePath, + oldFileText.replace(/^### /m, insertText + "\n\n### "), + ); + + await workspace.runFormatter(); + console.log( + "Updated Release.md -- Please review the output to ensure it's correct.", + ); +} + +async function getReleasesMdText() { + const gitLog = await getGitLog(); + const formattedGitLog = gitLog.formatForReleaseMarkdown(); + const formattedDate = getFormattedDate(new Date()); + + return `### ${cliCrate.version} / ${formattedDate}\n\n` + + `${formattedGitLog}`; + + function getFormattedDate(date: Date) { + const formattedMonth = padTwoDigit(date.getMonth() + 1); + const formattedDay = padTwoDigit(date.getDate()); + return `${date.getFullYear()}.${formattedMonth}.${formattedDay}`; + + function padTwoDigit(val: number) { + return val.toString().padStart(2, "0"); + } + } +} + +async function getGitLog() { + const lastVersion = semver.parse(originalCliVersion)!; + const lastVersionTag = `v${originalCliVersion}`; + // fetch the upstream tags + await repo.gitFetchTags("upstream"); + + // this means we're on the patch release + const latestTag = await repo.gitLatestTag(); + if (latestTag === lastVersionTag) { + return await repo.getGitLogFromTags( + "upstream", + lastVersionTag, + undefined, + ); + } else { + // otherwise, get the history of the last release + await repo.gitFetchHistory("upstream"); + const lastMinorHistory = await repo.getGitLogFromTags( + "upstream", + `v${lastVersion.major}.${lastVersion.minor}.0`, + lastVersionTag, + ); + const currentHistory = await repo.getGitLogFromTags( + "upstream", + latestTag, + undefined, + ); + const lastMinorMessages = new Set( + lastMinorHistory.lines.map((r) => r.message), + ); + return new GitLogOutput( + currentHistory.lines.filter((l) => !lastMinorMessages.has(l.message)), + ); + } +} diff --git a/tools/release/01_bump_dependency_crate_versions.ts b/tools/release/01_bump_dependency_crate_versions.ts deleted file mode 100755 index 931b7d199b..0000000000 --- a/tools/release/01_bump_dependency_crate_versions.ts +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -import { DenoWorkspace } from "./deno_workspace.ts"; - -const workspace = await DenoWorkspace.load(); - -for (const crate of workspace.getDependencyCrates()) { - await crate.increment("minor"); -} - -// update the lock file -await workspace.getCliCrate().cargoCheck(); diff --git a/tools/release/02_publish_dependency_crates.ts b/tools/release/02_publish_crates.ts old mode 100755 new mode 100644 similarity index 90% rename from tools/release/02_publish_dependency_crates.ts rename to tools/release/02_publish_crates.ts index d210971a14..1bb02f4608 --- a/tools/release/02_publish_dependency_crates.ts +++ b/tools/release/02_publish_crates.ts @@ -4,6 +4,7 @@ import { DenoWorkspace } from "./deno_workspace.ts"; import { getCratesPublishOrder } from "./deps.ts"; const workspace = await DenoWorkspace.load(); +const cliCrate = workspace.getCliCrate(); const dependencyCrates = getCratesPublishOrder(workspace.getDependencyCrates()); @@ -12,6 +13,8 @@ try { 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"); diff --git a/tools/release/03_bump_cli_version.ts b/tools/release/03_bump_cli_version.ts deleted file mode 100755 index 553133405e..0000000000 --- a/tools/release/03_bump_cli_version.ts +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo,git -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -import { DenoWorkspace } from "./deno_workspace.ts"; -import { path } from "./deps.ts"; - -const workspace = await DenoWorkspace.load(); -const repo = workspace.repo; - -const cliCrate = workspace.getCliCrate(); -const originalVersion = cliCrate.version; - -// increment the version -await cliCrate.promptAndIncrement(); -// update the lock file -await cliCrate.cargoCheck(); - -// update the Releases.md markdown text -await updateReleasesMd(); -await workspace.runFormatter(); -console.log( - "Updated Release.md -- Please review the output to ensure it's correct.", -); - -async function updateReleasesMd() { - const filePath = path.join(DenoWorkspace.rootDirPath, "Releases.md"); - const oldFileText = await Deno.readTextFile(filePath); - const insertText = await getReleasesMdText(); - - await Deno.writeTextFile( - filePath, - oldFileText.replace(/^### /m, insertText + "\n\n### "), - ); -} - -async function getReleasesMdText() { - const gitLog = await repo.getGitLogFromTags( - "upstream", - `v${originalVersion}`, - undefined, - ); - const formattedGitLog = gitLog.formatForReleaseMarkdown(); - const formattedDate = getFormattedDate(new Date()); - - return `### ${cliCrate.version} / ${formattedDate}\n\n` + - `${formattedGitLog}`; - - function getFormattedDate(date: Date) { - const formattedMonth = padTwoDigit(date.getMonth() + 1); - const formattedDay = padTwoDigit(date.getDate()); - return `${date.getFullYear()}.${formattedMonth}.${formattedDay}`; - - function padTwoDigit(val: number) { - return val.toString().padStart(2, "0"); - } - } -} diff --git a/tools/release/deps.ts b/tools/release/deps.ts index 4a1ec87258..5e249c1cf0 100644 --- a/tools/release/deps.ts +++ b/tools/release/deps.ts @@ -1,3 +1,3 @@ // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -export * from "https://raw.githubusercontent.com/denoland/automation/0.3.0/mod.ts"; +export * from "https://raw.githubusercontent.com/denoland/automation/0.4.0/mod.ts";