Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/commands/inc/major.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export const major = {
build,
});
await writeVersionFile(current);
await postVersionHook(
const hookWarnings = await postVersionHook(
args,
previous,
current,
);
await printVersion(args, current, args.json);
await printVersion(args, current, args.json, hookWarnings);
},
};
4 changes: 2 additions & 2 deletions src/commands/inc/minor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export const minor = {
build,
});
await writeVersionFile(current);
await postVersionHook(
const hookWarnings = await postVersionHook(
args,
previous,
current,
);
await printVersion(args, current, args.json);
await printVersion(args, current, args.json, hookWarnings);
},
};
4 changes: 2 additions & 2 deletions src/commands/inc/none.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export const none = {
build,
});
await writeVersionFile(current);
await postVersionHook(
const hookWarnings = await postVersionHook(
args,
previous,
current,
);
await printVersion(args, current, args.json);
await printVersion(args, current, args.json, hookWarnings);
},
};
4 changes: 2 additions & 2 deletions src/commands/inc/patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export const patch = {
build,
});
await writeVersionFile(current);
await postVersionHook(
const hookWarnings = await postVersionHook(
args,
previous,
current,
);
await printVersion(args, current, args.json);
await printVersion(args, current, args.json, hookWarnings);
},
};
4 changes: 2 additions & 2 deletions src/commands/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ export const set = {
const previous = await readVersionFile();
const version = value ? parse(value) : previous ? previous : parse("0.1.0");
await writeVersionFile(version);
await postVersionHook(
const hookWarnings = await postVersionHook(
args,
previous,
version,
);
await printVersion(args, version, args.json);
await printVersion(args, version, args.json, hookWarnings);
},
};
6 changes: 6 additions & 0 deletions src/hooks/hooks.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ export type VersionConfig = {
post?: PostHook[];
};
};

export type HookWarning = {
kind: PostHookKind;
file: string;
reason: string;
};
110 changes: 109 additions & 1 deletion src/hooks/post.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { parse } from "semver";
import { assertEquals } from "@std/assert";
import { resolvesNext, stub } from "testing/mock";
import { assertSpyCalls, resolvesNext, stub } from "testing/mock";
import * as YAML from "yaml";
import { IContext } from "../context.ts";
import { postVersionHook } from "./post.ts";
Expand Down Expand Up @@ -45,6 +45,114 @@ Deno.test("yml or yaml", async () => {
}
});

Deno.test("hook target file missing is a warning, not a failure", async () => {
const notFound = new Deno.errors.NotFound(
"No such file or directory (os error 2): readfile '.github/README.md'",
);
const context: IContext = {
githubDir: ".github",
hooks: {
patch: async () => await undefined,
replace: async () => await undefined,
regexp: () => {
throw notFound;
},
},
};
const stubs = [
stub(
Deno,
"stat",
resolvesNext<Deno.FileInfo>([
{ isFile: true } as Deno.FileInfo, // version.yml
]),
),
stub(
Deno,
"readTextFile",
resolvesNext([
YAML.stringify({
on: {
post: [{
kind: "regexp",
file: ".github/README.md",
pattern: "\\d+\\.\\d+\\.\\d+",
}],
},
}),
]),
),
stub(context.hooks, "patch"),
stub(context.hooks, "replace"),
];
try {
const warnings = await postVersionHook(
context,
parse("1.0.0"),
parse("1.2.3"),
);
assertEquals(warnings, [{
kind: "regexp",
file: ".github/README.md",
reason: notFound.message,
}]);
} finally {
stubs.forEach((s) => s.restore());
}
});

Deno.test("remaining hooks still run after one hook's file is missing", async () => {
const notFound = new Deno.errors.NotFound("not found");
const context: IContext = {
githubDir: ".github",
hooks: {
patch: async () => await undefined,
replace: () => {
throw notFound;
},
regexp: async () => await undefined,
},
};
const stubs = [
stub(
Deno,
"stat",
resolvesNext<Deno.FileInfo>([
{ isFile: true } as Deno.FileInfo, // version.yml
]),
),
stub(
Deno,
"readTextFile",
resolvesNext([
YAML.stringify({
on: {
post: [
{ kind: "replace", file: "missing.txt" },
{ kind: "patch", file: "test/example.csproj" },
],
},
}),
]),
),
stub(context.hooks, "regexp"),
];
const patchStub = stub(context.hooks, "patch");
try {
const warnings = await postVersionHook(
context,
parse("1.0.0"),
parse("1.2.3"),
);
assertEquals(warnings.length, 1);
assertEquals(warnings[0].file, "missing.txt");
assertSpyCalls(patchStub, 1);
} finally {
patchStub.restore();
stubs.forEach((s) => s.restore());
}
});

Deno.test("custom config", async () => {
const context: IContext = {
config: ".github/version-test.yml",
Expand Down
64 changes: 41 additions & 23 deletions src/hooks/post.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as YAML from "yaml";
import { HookError } from "../errors/mod.ts";
import { exists } from "../util/exists.ts";
import { PostHookKind, VersionConfig } from "./hooks.interfaces.ts";
import {
HookWarning,
PostHookKind,
VersionConfig,
} from "./hooks.interfaces.ts";
import { IContext } from "../context.ts";
import { SemVer } from "semver";

Expand All @@ -15,7 +19,8 @@ export async function postVersionHook(
context: IContext,
previous: SemVer,
current: SemVer,
) {
): Promise<HookWarning[]> {
const warnings: HookWarning[] = [];
const versionConfig = await getVersionConfig(context);
if (versionConfig) {
console.log(`Invoking post_version hook...`);
Expand All @@ -29,31 +34,44 @@ export async function postVersionHook(

for (const hook of postHooks) {
const { kind } = hook;
switch (kind) {
case PostHookKind.Replace:
await context.hooks.replace(hook.file, previous, current);
break;
case PostHookKind.Patch:
await context.hooks.patch(hook.file, current, hook.format);
break;
case PostHookKind.RegExp:
await context.hooks.regexp(
hook.file,
current,
hook.pattern,
hook.flags,
hook.format,
hook.prefix,
);
break;
default:
throw new HookError(
"post_hook",
`unknown hook kind ${kind}`,
try {
switch (kind) {
case PostHookKind.Replace:
await context.hooks.replace(hook.file, previous, current);
break;
case PostHookKind.Patch:
await context.hooks.patch(hook.file, current, hook.format);
break;
case PostHookKind.RegExp:
await context.hooks.regexp(
hook.file,
current,
hook.pattern,
hook.flags,
hook.format,
hook.prefix,
);
break;
default:
throw new HookError(
"post_hook",
`unknown hook kind ${kind}`,
);
}
} catch (err) {
if (err instanceof Deno.errors.NotFound) {
const reason = err instanceof Error ? err.message : String(err);
console.warn(
`warning: post_version hook (${kind}) skipped, file not found: ${hook.file}`,
);
warnings.push({ kind, file: hook.file, reason });
} else {
throw err;
}
}
}
}
return warnings;
}

async function getVersionConfig(context: IContext) {
Expand Down
5 changes: 5 additions & 0 deletions src/util/version.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as path from "path";
import { format, parse, SemVer } from "semver";
import { IContext } from "../context.ts";
import { HookWarning } from "../hooks/hooks.interfaces.ts";
import { semverFormats } from "./variant.ts";

export const DEFAULT_VERSION = parse("0.1.0");
Expand All @@ -25,6 +26,7 @@ export async function printVersion(
context: IContext,
semver: SemVer,
forceJson = false,
hookWarnings: HookWarning[] = [],
) {
const formatted = format(semver);
const { major, minor, patch, prerelease = [], build = [] } = semver;
Expand All @@ -40,6 +42,9 @@ export async function printVersion(
build: b,
dotnet,
docker,
...hookWarnings.length > 0
? { hook_warnings: JSON.stringify(hookWarnings) }
: {},

// Adding these for backwards compatibility, do not remove or add more
// todo: remove on next major version
Expand Down
Loading