mirror of
https://github.com/denoland/deno.git
synced 2024-11-29 16:30:56 -05:00
chore(tools): use automation scripts from automation repo (#13796)
This commit is contained in:
parent
9acf7ed7cb
commit
e33522b87a
10 changed files with 87 additions and 461 deletions
|
@ -1,6 +1,6 @@
|
||||||
#!/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
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
import { DenoWorkspace } from "./helpers/mod.ts";
|
import { DenoWorkspace } from "./deno_workspace.ts";
|
||||||
|
|
||||||
const workspace = await DenoWorkspace.load();
|
const workspace = await DenoWorkspace.load();
|
||||||
|
|
||||||
|
@ -8,4 +8,5 @@ for (const crate of workspace.getDependencyCrates()) {
|
||||||
await crate.increment("minor");
|
await crate.increment("minor");
|
||||||
}
|
}
|
||||||
|
|
||||||
await workspace.updateLockFile();
|
// update the lock file
|
||||||
|
await workspace.getCliCrate().cargoCheck();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo --allow-net=crates.io
|
#!/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.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
import { DenoWorkspace, getCratesPublishOrder } from "./helpers/mod.ts";
|
import { DenoWorkspace } from "./deno_workspace.ts";
|
||||||
|
import { getCratesPublishOrder } from "./deps.ts";
|
||||||
|
|
||||||
const workspace = await DenoWorkspace.load();
|
const workspace = await DenoWorkspace.load();
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run=cargo,git
|
#!/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.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
import {
|
import { DenoWorkspace } from "./deno_workspace.ts";
|
||||||
DenoWorkspace,
|
|
||||||
formatGitLogForMarkdown,
|
|
||||||
getGitLogFromTag,
|
|
||||||
} from "./helpers/mod.ts";
|
|
||||||
|
|
||||||
const workspace = await DenoWorkspace.load();
|
const workspace = await DenoWorkspace.load();
|
||||||
|
const repo = workspace.repo;
|
||||||
|
|
||||||
const cliCrate = workspace.getCliCrate();
|
const cliCrate = workspace.getCliCrate();
|
||||||
const originalVersion = cliCrate.version;
|
const originalVersion = cliCrate.version;
|
||||||
|
|
||||||
// increment the version
|
// increment the version
|
||||||
await cliCrate.increment(getVersionIncrement());
|
await cliCrate.promptAndIncrement();
|
||||||
await workspace.updateLockFile();
|
// update the lock file
|
||||||
|
await cliCrate.cargoCheck();
|
||||||
|
|
||||||
// output the Releases.md markdown text
|
// output the Releases.md markdown text
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -21,24 +19,13 @@ console.log(
|
||||||
);
|
);
|
||||||
console.log(await getReleasesMdText());
|
console.log(await getReleasesMdText());
|
||||||
|
|
||||||
function getVersionIncrement() {
|
|
||||||
if (confirm("Increment patch?")) {
|
|
||||||
return "patch";
|
|
||||||
} else if (confirm("Increment minor?")) {
|
|
||||||
return "minor";
|
|
||||||
} else if (confirm("Increment major?")) {
|
|
||||||
return "major";
|
|
||||||
} else {
|
|
||||||
throw new Error("No decision.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getReleasesMdText() {
|
async function getReleasesMdText() {
|
||||||
const gitLogOutput = await getGitLogFromTag(
|
const gitLog = await repo.getGitLogFromTags(
|
||||||
DenoWorkspace.rootDirPath,
|
"upstream",
|
||||||
`v${originalVersion}`,
|
`v${originalVersion}`,
|
||||||
|
undefined,
|
||||||
);
|
);
|
||||||
const formattedGitLog = formatGitLogForMarkdown(gitLogOutput);
|
const formattedGitLog = gitLog.formatForReleaseMarkdown();
|
||||||
const formattedDate = getFormattedDate(new Date());
|
const formattedDate = getFormattedDate(new Date());
|
||||||
|
|
||||||
return `### ${cliCrate.version} / ${formattedDate}\n\n` +
|
return `### ${cliCrate.version} / ${formattedDate}\n\n` +
|
||||||
|
|
70
tools/release/deno_workspace.ts
Normal file
70
tools/release/deno_workspace.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import { path, Repo } from "./deps.ts";
|
||||||
|
|
||||||
|
export class DenoWorkspace {
|
||||||
|
#repo: Repo;
|
||||||
|
|
||||||
|
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 Repo.load("deno", DenoWorkspace.rootDirPath),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(repo: Repo) {
|
||||||
|
this.#repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
get repo() {
|
||||||
|
return this.#repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
get crates() {
|
||||||
|
return this.#repo.crates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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.getCrate("serde_v8");
|
||||||
|
}
|
||||||
|
|
||||||
|
getCliCrate() {
|
||||||
|
return this.getCrate("deno");
|
||||||
|
}
|
||||||
|
|
||||||
|
getCoreCrate() {
|
||||||
|
return this.getCrate("deno_core");
|
||||||
|
}
|
||||||
|
|
||||||
|
getRuntimeCrate() {
|
||||||
|
return this.getCrate("deno_runtime");
|
||||||
|
}
|
||||||
|
|
||||||
|
getBenchUtilCrate() {
|
||||||
|
return this.getCrate("deno_bench_util");
|
||||||
|
}
|
||||||
|
|
||||||
|
getExtCrates() {
|
||||||
|
const extPath = path.join(this.#repo.folderPath, "ext");
|
||||||
|
return this.crates.filter((c) => c.manifestPath.startsWith(extPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
getCrate(name: string) {
|
||||||
|
return this.#repo.getCrate(name);
|
||||||
|
}
|
||||||
|
}
|
3
tools/release/deps.ts
Normal file
3
tools/release/deps.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
export * from "https://raw.githubusercontent.com/denoland/automation/0.2.0/mod.ts";
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -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";
|
|
Loading…
Reference in a new issue