summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2024-08-16 22:59:10 +0100
committerGitHub <noreply@github.com>2024-08-16 23:59:10 +0200
commit2eeea0a1d2011567d3a41065d66802097366dc8c (patch)
treea231ffa562cbd2eabbd7703a25938b3f9e47fb25 /tools
parentdb75462bd6f01d4a470c2ed7b5aad2f9a877f150 (diff)
ci: add script to promote to RC release (#25072)
This commits add a CI script that allows to promote a certain canary build to a "Release Candidate" release. This is done using `libsui` and `patchver` utilities.
Diffstat (limited to 'tools')
-rw-r--r--tools/deno.lock.json68
-rw-r--r--tools/release/promote_to_rc.ts212
2 files changed, 280 insertions, 0 deletions
diff --git a/tools/deno.lock.json b/tools/deno.lock.json
index d4f7c6230..46c09ce24 100644
--- a/tools/deno.lock.json
+++ b/tools/deno.lock.json
@@ -2,9 +2,77 @@
"version": "3",
"packages": {
"specifiers": {
+ "jsr:@david/dax@0.41.0": "jsr:@david/dax@0.41.0",
+ "jsr:@david/which@^0.4.1": "jsr:@david/which@0.4.1",
+ "jsr:@deno/patchver@0.1.0": "jsr:@deno/patchver@0.1.0",
+ "jsr:@std/assert@^0.221.0": "jsr:@std/assert@0.221.0",
+ "jsr:@std/bytes@^0.221.0": "jsr:@std/bytes@0.221.0",
+ "jsr:@std/fmt@1": "jsr:@std/fmt@1.0.0",
+ "jsr:@std/fmt@^0.221.0": "jsr:@std/fmt@0.221.0",
+ "jsr:@std/fs@0.221.0": "jsr:@std/fs@0.221.0",
+ "jsr:@std/io@0.221.0": "jsr:@std/io@0.221.0",
+ "jsr:@std/io@^0.221.0": "jsr:@std/io@0.221.0",
+ "jsr:@std/path@0.221.0": "jsr:@std/path@0.221.0",
+ "jsr:@std/path@^0.221.0": "jsr:@std/path@0.221.0",
+ "jsr:@std/streams@0.221.0": "jsr:@std/streams@0.221.0",
"jsr:@std/yaml@^0.221": "jsr:@std/yaml@0.221.0"
},
"jsr": {
+ "@david/dax@0.41.0": {
+ "integrity": "9e1ecf66a0415962cc8ad3ba4e3fa93ce0f1a1cc797dd95c36fdfb6977dc7fc8",
+ "dependencies": [
+ "jsr:@david/which@^0.4.1",
+ "jsr:@std/fmt@^0.221.0",
+ "jsr:@std/fs@0.221.0",
+ "jsr:@std/io@0.221.0",
+ "jsr:@std/path@0.221.0",
+ "jsr:@std/streams@0.221.0"
+ ]
+ },
+ "@david/which@0.4.1": {
+ "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e"
+ },
+ "@deno/patchver@0.1.0": {
+ "integrity": "3102aa1b751a9fb85ef6cf7d4c0a1ec6624c85a77facc140c5748d82126d66a6"
+ },
+ "@std/assert@0.221.0": {
+ "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a"
+ },
+ "@std/bytes@0.221.0": {
+ "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966"
+ },
+ "@std/fmt@0.221.0": {
+ "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a"
+ },
+ "@std/fmt@1.0.0": {
+ "integrity": "8a95c9fdbb61559418ccbc0f536080cf43341655e1444f9d375a66886ceaaa3d"
+ },
+ "@std/fs@0.221.0": {
+ "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286",
+ "dependencies": [
+ "jsr:@std/assert@^0.221.0",
+ "jsr:@std/path@^0.221.0"
+ ]
+ },
+ "@std/io@0.221.0": {
+ "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da",
+ "dependencies": [
+ "jsr:@std/assert@^0.221.0",
+ "jsr:@std/bytes@^0.221.0"
+ ]
+ },
+ "@std/path@0.221.0": {
+ "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095",
+ "dependencies": [
+ "jsr:@std/assert@^0.221.0"
+ ]
+ },
+ "@std/streams@0.221.0": {
+ "integrity": "47f2f74634b47449277c0ee79fe878da4424b66bd8975c032e3afdca88986e61",
+ "dependencies": [
+ "jsr:@std/io@^0.221.0"
+ ]
+ },
"@std/yaml@0.221.0": {
"integrity": "bac8913ee4f6fc600d4b92cc020f755070e22687ad242341f31d123ff690ae98"
}
diff --git a/tools/release/promote_to_rc.ts b/tools/release/promote_to_rc.ts
new file mode 100644
index 000000000..6d7375385
--- /dev/null
+++ b/tools/release/promote_to_rc.ts
@@ -0,0 +1,212 @@
+#!/usr/bin/env -S deno run -A --lock=tools/deno.lock.json
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+import { $ } from "jsr:@david/dax@0.41.0";
+import { gray } from "jsr:@std/fmt@1/colors";
+import { patchver } from "jsr:@deno/patchver@0.1.0";
+
+const SUPPORTED_TARGETS = [
+ "aarch64-apple-darwin",
+ "aarch64-unknown-linux-gnu",
+ "x86_64-apple-darwin",
+ "x86_64-pc-windows-msvc",
+ "x86_64-unknown-linux-gnu",
+];
+
+const DENO_BINARIES = [
+ "deno",
+ "denort",
+];
+
+const CHANNEL = "rc";
+
+const CANARY_URL = "https://dl.deno.land";
+
+function getCanaryBinaryUrl(
+ version: string,
+ binary: string,
+ target: string,
+): string {
+ return `${CANARY_URL}/canary/${version}/${binary}-${target}.zip`;
+}
+
+function getUnzippedFilename(binary: string, target: string) {
+ if (target.includes("windows")) {
+ return `${binary}.exe`;
+ } else {
+ return binary;
+ }
+}
+
+function getRcBinaryName(binary: string, target: string): string {
+ let ext = "";
+ if (target.includes("windows")) {
+ ext = ".exe";
+ }
+ return `${binary}-${target}-rc${ext}`;
+}
+
+function getArchiveName(binary: string, target: string): string {
+ return `${binary}-${target}.zip`;
+}
+
+interface CanaryVersion {
+ target: string;
+ version: string;
+}
+
+async function remove(filePath: string) {
+ try {
+ await Deno.remove(filePath);
+ } catch {
+ // pass
+ }
+}
+
+async function fetchLatestCanaryBinary(
+ version: string,
+ binary: string,
+ target: string,
+) {
+ const url = getCanaryBinaryUrl(version, binary, target);
+ await $.request(url).showProgress().pipeToPath();
+}
+
+async function fetchLatestCanaryBinaries(canaryVersion: string) {
+ for (const binary of DENO_BINARIES) {
+ for (const target of SUPPORTED_TARGETS) {
+ $.logStep("Download", binary, gray("target:"), target);
+ await fetchLatestCanaryBinary(canaryVersion, binary, target);
+ }
+ }
+}
+
+async function unzipArchive(archiveName: string, unzippedName: string) {
+ await remove(unzippedName);
+ const output = await $`unzip ./${archiveName}`;
+ if (output.code !== 0) {
+ $.logError(`Failed to unzip ${archiveName} (error code ${output.code})`);
+ Deno.exit(1);
+ }
+}
+
+async function createArchive(rcBinaryName: string, archiveName: string) {
+ const output = await $`zip -r ./${archiveName} ./${rcBinaryName}`;
+
+ if (output.code !== 0) {
+ $.logError(
+ `Failed to create archive ${archiveName} (error code ${output.code})`,
+ );
+ Deno.exit(1);
+ }
+}
+
+async function runPatchver(
+ binary: string,
+ target: string,
+ rcBinaryName: string,
+) {
+ const input = await Deno.readFile(binary);
+ const output = patchver(input, CHANNEL);
+
+ try {
+ await Deno.writeFile(rcBinaryName, output);
+ } catch (e) {
+ $.logError(
+ `Failed to promote to RC ${binary} (${target}), error:`,
+ e,
+ );
+ Deno.exit(1);
+ }
+}
+
+async function promoteBinaryToRc(binary: string, target: string) {
+ const unzippedName = getUnzippedFilename(binary, target);
+ const rcBinaryName = getRcBinaryName(binary, target);
+ const archiveName = getArchiveName(binary, target);
+ await remove(unzippedName);
+ await remove(rcBinaryName);
+ $.logStep(
+ "Unzip",
+ archiveName,
+ gray("binary"),
+ binary,
+ gray("rcBinaryName"),
+ rcBinaryName,
+ );
+
+ await unzipArchive(archiveName, unzippedName);
+ await remove(archiveName);
+
+ $.logStep(
+ "Patchver",
+ unzippedName,
+ `(${target})`,
+ gray("output to"),
+ rcBinaryName,
+ );
+ await runPatchver(unzippedName, target, rcBinaryName);
+ // Remove the unpatched binary and rename patched one.
+ await remove(unzippedName);
+ await Deno.rename(rcBinaryName, unzippedName);
+ // Set executable permission
+ if (!target.includes("windows")) {
+ Deno.chmod(unzippedName, 0o777);
+ }
+
+ await createArchive(unzippedName, archiveName);
+ await remove(unzippedName);
+}
+
+async function promoteBinariesToRc() {
+ const totalCanaries = SUPPORTED_TARGETS.length * DENO_BINARIES.length;
+
+ for (let targetIdx = 0; targetIdx < SUPPORTED_TARGETS.length; targetIdx++) {
+ const target = SUPPORTED_TARGETS[targetIdx];
+ for (let binaryIdx = 0; binaryIdx < DENO_BINARIES.length; binaryIdx++) {
+ const binaryName = DENO_BINARIES[binaryIdx];
+ const currentIdx = (targetIdx * 2) + binaryIdx + 1;
+ $.logLight(
+ `[${currentIdx}/${totalCanaries}]`,
+ "Promote",
+ binaryName,
+ target,
+ "to RC...",
+ );
+ await promoteBinaryToRc(binaryName, target);
+ $.logLight(
+ `[${currentIdx}/${totalCanaries}]`,
+ "Promoted",
+ binaryName,
+ target,
+ "to RC!",
+ );
+ }
+ }
+}
+
+async function dumpRcVersion() {
+ $.logStep("Compute version");
+ await unzipArchive(getArchiveName("deno", Deno.build.target), "deno");
+ const output = await $`./deno -V`.stdout("piped");
+ const denoVersion = output.stdout.slice(5).split("+")[0];
+ $.logStep("Computed version", denoVersion);
+ await Deno.writeTextFile("./release-rc-latest.txt", denoVersion);
+}
+
+async function main() {
+ const commitHash = Deno.args[0];
+ if (!commitHash) {
+ throw new Error("Commit hash needs to be provided as an argument");
+ }
+ $.logStep("Download canary binaries...");
+ await fetchLatestCanaryBinaries(commitHash);
+ console.log("All canary binaries ready");
+ $.logStep("Promote canary binaries to RC...");
+ await promoteBinariesToRc();
+
+ // Finally dump the version name to a `release.txt` file for uploading to GCP
+ await dumpRcVersion();
+}
+
+await main();