summaryrefslogtreecommitdiff
path: root/tools/release/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'tools/release/helpers')
-rw-r--r--tools/release/helpers/cargo.ts72
-rw-r--r--tools/release/helpers/crates_io.ts22
-rw-r--r--tools/release/helpers/deno_workspace.ts228
-rw-r--r--tools/release/helpers/helpers.ts104
-rw-r--r--tools/release/helpers/mod.ts10
5 files changed, 0 insertions, 436 deletions
diff --git a/tools/release/helpers/cargo.ts b/tools/release/helpers/cargo.ts
deleted file mode 100644
index 15dd0c5b6..000000000
--- a/tools/release/helpers/cargo.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-import { runCommand } from "./helpers.ts";
-
-export interface CargoMetadata {
- packages: CargoPackageMetadata[];
- /** Identifiers in the `packages` array of the workspace members. */
- "workspace_members": string[];
- /** The absolute workspace root directory path. */
- "workspace_root": string;
-}
-
-export interface CargoPackageMetadata {
- id: string;
- name: string;
- version: string;
- dependencies: CargoDependencyMetadata[];
- /** Path to Cargo.toml */
- "manifest_path": string;
-}
-
-export interface CargoDependencyMetadata {
- name: string;
- /** Version requrement (ex. ^0.1.0) */
- req: string;
-}
-
-export async function getMetadata(directory: string) {
- const result = await runCommand({
- cwd: directory,
- cmd: ["cargo", "metadata", "--format-version", "1"],
- });
- return JSON.parse(result!) as CargoMetadata;
-}
-
-export function publishCrate(directory: string) {
- return runCargoSubCommand({
- directory,
- args: ["publish"],
- });
-}
-
-export function build(directory: string) {
- return runCargoSubCommand({
- directory,
- args: ["build", "-vv"],
- });
-}
-
-export function check(directory: string) {
- return runCargoSubCommand({
- directory,
- args: ["check"],
- });
-}
-
-async function runCargoSubCommand(params: {
- args: string[];
- directory: string;
-}) {
- const p = Deno.run({
- cwd: params.directory,
- cmd: ["cargo", ...params.args],
- stderr: "inherit",
- stdout: "inherit",
- });
-
- const status = await p.status();
- if (!status.success) {
- throw new Error("Failed");
- }
-}
diff --git a/tools/release/helpers/crates_io.ts b/tools/release/helpers/crates_io.ts
deleted file mode 100644
index af26f55af..000000000
--- a/tools/release/helpers/crates_io.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-export interface CratesIoMetadata {
- crate: {
- id: string;
- name: string;
- };
- versions: {
- crate: string;
- num: string;
- }[];
-}
-
-export async function getCratesIoMetadata(crateName: string) {
- // rate limit
- await new Promise((resolve) => setTimeout(resolve, 100));
-
- const response = await fetch(`https://crates.io/api/v1/crates/${crateName}`);
- const data = await response.json();
-
- return data as CratesIoMetadata;
-}
diff --git a/tools/release/helpers/deno_workspace.ts b/tools/release/helpers/deno_workspace.ts
deleted file mode 100644
index 6d7a03cb7..000000000
--- a/tools/release/helpers/deno_workspace.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-import * as path from "https://deno.land/std@0.105.0/path/mod.ts";
-import * as semver from "https://deno.land/x/semver@v1.4.0/mod.ts";
-import * as cargo from "./cargo.ts";
-import { getCratesIoMetadata } from "./crates_io.ts";
-import { withRetries } from "./helpers.ts";
-
-export class DenoWorkspace {
- #workspaceCrates: readonly DenoWorkspaceCrate[];
- #workspaceRootDirPath: string;
-
- static get rootDirPath() {
- const currentDirPath = path.dirname(path.fromFileUrl(import.meta.url));
- return path.resolve(currentDirPath, "../../../");
- }
-
- static async load(): Promise<DenoWorkspace> {
- return new DenoWorkspace(
- await cargo.getMetadata(DenoWorkspace.rootDirPath),
- );
- }
-
- private constructor(metadata: cargo.CargoMetadata) {
- const crates = [];
- for (const memberId of metadata.workspace_members) {
- const pkg = metadata.packages.find((pkg) => pkg.id === memberId);
- if (!pkg) {
- throw new Error(`Could not find package with id ${memberId}`);
- }
- crates.push(new DenoWorkspaceCrate(this, pkg));
- }
-
- this.#workspaceCrates = crates;
- this.#workspaceRootDirPath = metadata.workspace_root;
- }
-
- get crates() {
- return this.#workspaceCrates;
- }
-
- /** Gets the dependency crates used for the first part of the release process. */
- getDependencyCrates() {
- return [
- this.getBenchUtilCrate(),
- this.getSerdeV8Crate(),
- this.getCoreCrate(),
- ...this.getExtCrates(),
- this.getRuntimeCrate(),
- ];
- }
-
- getSerdeV8Crate() {
- return this.getCrateByNameOrThrow("serde_v8");
- }
-
- getCliCrate() {
- return this.getCrateByNameOrThrow("deno");
- }
-
- getCoreCrate() {
- return this.getCrateByNameOrThrow("deno_core");
- }
-
- getRuntimeCrate() {
- return this.getCrateByNameOrThrow("deno_runtime");
- }
-
- getBenchUtilCrate() {
- return this.getCrateByNameOrThrow("deno_bench_util");
- }
-
- getExtCrates() {
- const extPath = path.join(this.#workspaceRootDirPath, "ext");
- return this.#workspaceCrates.filter((c) =>
- c.manifestPath.startsWith(extPath)
- );
- }
-
- getCrateByNameOrThrow(name: string) {
- const crate = this.#workspaceCrates.find((c) => c.name === name);
- if (!crate) {
- throw new Error(`Could not find crate: ${name}`);
- }
- return crate;
- }
-
- build() {
- return cargo.build(DenoWorkspace.rootDirPath);
- }
-
- updateLockFile() {
- return cargo.check(DenoWorkspace.rootDirPath);
- }
-}
-
-export class DenoWorkspaceCrate {
- #workspace: DenoWorkspace;
- #pkg: cargo.CargoPackageMetadata;
- #isUpdatingManifest = false;
-
- constructor(workspace: DenoWorkspace, pkg: cargo.CargoPackageMetadata) {
- this.#workspace = workspace;
- this.#pkg = pkg;
- }
-
- get manifestPath() {
- return this.#pkg.manifest_path;
- }
-
- get directoryPath() {
- return path.dirname(this.#pkg.manifest_path);
- }
-
- get name() {
- return this.#pkg.name;
- }
-
- get version() {
- return this.#pkg.version;
- }
-
- getDependencies() {
- const dependencies = [];
- for (const dependency of this.#pkg.dependencies) {
- const crate = this.#workspace.crates.find((c) =>
- c.name === dependency.name
- );
- if (crate != null) {
- dependencies.push(crate);
- }
- }
- return dependencies;
- }
-
- async isPublished() {
- const cratesIoMetadata = await getCratesIoMetadata(this.name);
- return cratesIoMetadata.versions.some((v) => v.num === this.version);
- }
-
- async publish() {
- if (await this.isPublished()) {
- console.log(`Already published ${this.name} ${this.version}`);
- return false;
- }
-
- console.log(`Publishing ${this.name} ${this.version}...`);
-
- // Sometimes a publish may fail due to the crates.io index
- // not being updated yet. Usually it will be resolved after
- // retrying, so try a few times before failing hard.
- return await withRetries({
- action: async () => {
- await cargo.publishCrate(this.directoryPath);
- return true;
- },
- retryCount: 5,
- retryDelaySeconds: 10,
- });
- }
-
- build() {
- return cargo.build(this.directoryPath);
- }
-
- updateLockFile() {
- return cargo.check(this.directoryPath);
- }
-
- increment(part: "major" | "minor" | "patch") {
- const newVersion = semver.parse(this.version)!.inc(part).toString();
- return this.setVersion(newVersion);
- }
-
- async setVersion(version: string) {
- console.log(`Setting ${this.name} to ${version}...`);
- for (const crate of this.#workspace.crates) {
- await crate.setDependencyVersion(this.name, version);
- }
- await this.#updateManifestVersion(version);
- }
-
- async setDependencyVersion(dependencyName: string, version: string) {
- const dependency = this.#pkg.dependencies.find((d) =>
- d.name === dependencyName
- );
- if (dependency != null) {
- await this.#updateManifestFile((fileText) => {
- // simple for now...
- const findRegex = new RegExp(
- `^(\\b${dependencyName}\\b\\s.*)"([=\\^])?[0-9]+[^"]+"`,
- "gm",
- );
- return fileText.replace(findRegex, `$1"${version}"`);
- });
-
- dependency.req = `^${version}`;
- }
- }
-
- async #updateManifestVersion(version: string) {
- await this.#updateManifestFile((fileText) => {
- const findRegex = new RegExp(
- `^(version\\s*=\\s*)"${this.#pkg.version}"$`,
- "m",
- );
- return fileText.replace(findRegex, `$1"${version}"`);
- });
- this.#pkg.version = version;
- }
-
- async #updateManifestFile(action: (fileText: string) => string) {
- if (this.#isUpdatingManifest) {
- throw new Error("Cannot update manifest while updating manifest.");
- }
- this.#isUpdatingManifest = true;
- try {
- const originalText = await Deno.readTextFile(this.#pkg.manifest_path);
- const newText = action(originalText);
- if (originalText === newText) {
- throw new Error(`The file didn't change: ${this.manifestPath}`);
- }
- await Deno.writeTextFile(this.manifestPath, newText);
- } finally {
- this.#isUpdatingManifest = false;
- }
- }
-}
diff --git a/tools/release/helpers/helpers.ts b/tools/release/helpers/helpers.ts
deleted file mode 100644
index 454a66373..000000000
--- a/tools/release/helpers/helpers.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-import type { DenoWorkspaceCrate } from "./deno_workspace.ts";
-
-export function getCratesPublishOrder(crates: DenoWorkspaceCrate[]) {
- const pendingCrates = [...crates];
- const sortedCrates = [];
-
- while (pendingCrates.length > 0) {
- for (let i = pendingCrates.length - 1; i >= 0; i--) {
- const crate = pendingCrates[i];
- const hasPendingDependency = crate.getDependencies()
- .some((c) => pendingCrates.includes(c));
- if (!hasPendingDependency) {
- sortedCrates.push(crate);
- pendingCrates.splice(i, 1);
- }
- }
- }
-
- return sortedCrates;
-}
-
-export function getGitLogFromTag(directory: string, tagName: string) {
- return runCommand({
- cwd: directory,
- cmd: ["git", "log", "--oneline", `${tagName}..`],
- });
-}
-
-const IGNORED_COMMIT_PREFIX = [
- "build",
- "chore",
- "ci",
- "docs",
- "refactor",
- "test",
-];
-
-export function formatGitLogForMarkdown(text: string) {
- return text.split(/\r?\n/)
- .map((line) => line.replace(/^[a-f0-9]{9} /i, "").trim())
- .filter((l) => {
- return !IGNORED_COMMIT_PREFIX.some((prefix) => l.startsWith(prefix)) &&
- l.length > 0;
- })
- .sort()
- .map((line) => `- ${line}`)
- .join("\n");
-}
-
-export async function runCommand(params: {
- cwd: string;
- cmd: string[];
-}) {
- const p = Deno.run({
- cwd: params.cwd,
- cmd: params.cmd,
- stderr: "piped",
- stdout: "piped",
- });
-
- const [status, stdout, stderr] = await Promise.all([
- p.status(),
- p.output(),
- p.stderrOutput(),
- ]);
- p.close();
-
- if (!status.success) {
- throw new Error(
- `Error executing ${params.cmd[0]}: ${new TextDecoder().decode(stderr)}`,
- );
- }
-
- return new TextDecoder().decode(stdout);
-}
-
-export async function withRetries<TReturn>(params: {
- action: () => Promise<TReturn>;
- retryCount: number;
- retryDelaySeconds: number;
-}) {
- for (let i = 0; i < params.retryCount; i++) {
- if (i > 0) {
- console.log(
- `Failed. Trying again in ${params.retryDelaySeconds} seconds...`,
- );
- await delay(params.retryDelaySeconds * 1000);
- console.log(`Attempt ${i + 1}/${params.retryCount}...`);
- }
- try {
- return await params.action();
- } catch (err) {
- console.error(err);
- }
- }
-
- throw new Error(`Failed after ${params.retryCount} attempts.`);
-}
-
-function delay(ms: number) {
- return new Promise((resolve) => setTimeout(resolve, ms));
-}
diff --git a/tools/release/helpers/mod.ts b/tools/release/helpers/mod.ts
deleted file mode 100644
index 2cf00c352..000000000
--- a/tools/release/helpers/mod.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-
-export * from "./cargo.ts";
-export * from "./crates_io.ts";
-export * from "./deno_workspace.ts";
-export {
- formatGitLogForMarkdown,
- getCratesPublishOrder,
- getGitLogFromTag,
-} from "./helpers.ts";