Skip to content

Commit 8780686

Browse files
authored
Merge pull request #67 from thefrontside/fix-signoff-workflow
fix the signoff workflow
2 parents c3ed4ec + d8390a8 commit 8780686

7 files changed

Lines changed: 82 additions & 31 deletions

File tree

.github/workflows/shipit.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ jobs:
2222
run: |
2323
deno task rel:init
2424
deno task rel:shipit
25+
git push origin 'refs/notes/*:refs/notes/*'
26+
git push origin --tags

tasks/rel/cmd/shipit.ts

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,23 @@
1-
import { parse, yaml } from "../deps.ts";
1+
import { parse } from "../deps.ts";
22
import { sh } from "../exec.ts";
3-
import * as $notes from "../notes.ts";
3+
4+
import * as $signoffs from "../signoffs.ts";
45

56
const flags = parse(Deno.args, {
67
"boolean": "dry-run",
78
});
89

910
const dryRun = flags["dry-run"] ?? false;
1011

11-
for await (let note of $notes.all("shipit")) {
12-
let releases = yaml.parse(note.content);
13-
for (let tag of Object.values(releases) as string[]) {
12+
for await (let signoff of $signoffs.untagged()) {
13+
for (let tag of signoff.releases) {
1414
if (dryRun) {
15-
console.log(`[DRY] git tag ${tag} ${note.targetId}`);
15+
console.log(`[DRY] git tag ${tag} ${signoff.commitId}`);
1616
} else {
17-
await sh(["git", "tag", tag, note.targetId]);
17+
await sh(["git", "tag", tag, signoff.commitId]);
1818
}
1919
}
20-
}
21-
22-
const cleanup = [
23-
["git", "push", "origin", ":refs/notes/shipit"],
24-
["git", "push", "origin", "--tags"],
25-
];
26-
27-
if (!dryRun) {
28-
for (let cmd of cleanup) {
29-
await sh(cmd);
20+
if (!dryRun) {
21+
await $signoffs.complete(signoff);
3022
}
31-
} else {
32-
console.log(cleanup.map((cmd) => `[DRY] ${cmd.join(" ")}`).join("\n"));
3323
}

tasks/rel/cmd/signoff.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { parse, yaml } from "../deps.ts";
1+
import { parse } from "../deps.ts";
22
import * as $releases from "../releases.ts";
3-
import * as $notes from "../notes.ts";
3+
import * as $signoffs from "../signoffs.ts";
44

55
const flags = parse(Deno.args, {
66
"string": ["pre"],
@@ -20,13 +20,8 @@ let next = await $releases.next(String(lineage), prerelease);
2020

2121
if (!$releases.eq(current, next)) {
2222
console.log(`Signoff: ${next.lineage.name}@${next.version}`);
23-
await $notes.upsert("shipit", (content) => {
24-
let current = content ? yaml.parse(content) : {};
25-
return yaml.stringify({
26-
...current,
27-
[lineage]: next.tag,
28-
});
29-
});
23+
24+
await $signoffs.signoff(next);
3025
} else {
3126
console.warn("Nothing to sign off.");
3227
}

tasks/rel/notes.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ import * as $git from "./git.ts";
55

66
export type Upsert = (content?: string) => string;
77

8-
export async function upsert(ref: string, fn: Upsert): Promise<void> {
9-
let current = await read(ref);
8+
export async function upsert(
9+
ref: string,
10+
fn: Upsert,
11+
commitId?: string,
12+
): Promise<void> {
13+
let current = await read(ref, commitId);
1014
let next = fn(current ? current.content : void 0);
11-
await write(ref, next);
15+
await write(ref, next, commitId);
1216
}
1317

1418
export async function read(

tasks/rel/ops.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ export async function* filter<T>(
1313
}
1414
}
1515

16+
export async function* map<T, R>(
17+
items: AsyncGenerator<T>,
18+
fn: (value: T) => Promise<R>,
19+
): AsyncGenerator<R> {
20+
for await (let item of items) {
21+
yield await fn(item);
22+
}
23+
}
24+
1625
export async function* until<T>(
1726
items: AsyncGenerator<T>,
1827
limit: Predicate<T>,

tasks/rel/signoffs.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import type { Release, Signoff } from "./types.ts";
2+
import * as $git from "./git.ts";
3+
import * as $notes from "./notes.ts";
4+
import { filter, map, until } from "./ops.ts";
5+
import { yaml } from "./deps.ts";
6+
7+
export function untagged(): AsyncGenerator<Signoff> {
8+
let signoffs = filter(
9+
map($git.history(), async (commit) => {
10+
let note = await $notes.read("signoffs", commit.id);
11+
return note
12+
? {
13+
...yaml.parse(note.content),
14+
commitId: commit.id,
15+
} as Signoff
16+
: null;
17+
}),
18+
(signoff) => Promise.resolve(!!signoff),
19+
) as AsyncGenerator<Signoff>;
20+
return until(signoffs, (signoff) => Promise.resolve(!!signoff.taggedAt));
21+
}
22+
23+
export async function signoff(release: Release): Promise<void> {
24+
await $notes.upsert("signoffs", (content) => {
25+
let current = content ? yaml.parse(content) : {
26+
releases: [],
27+
};
28+
return yaml.stringify({
29+
...current,
30+
releases: current.releases.concat(release.tag),
31+
});
32+
});
33+
}
34+
35+
export async function complete(signoff: Signoff): Promise<void> {
36+
await $notes.upsert("signoffs", (content) => {
37+
let current = content ? yaml.parse(content) : {
38+
releases: [],
39+
};
40+
return yaml.stringify({
41+
...current,
42+
taggedAt: new Date().toISOString(),
43+
});
44+
}, signoff.commitId);
45+
}

tasks/rel/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,9 @@ export interface Idempotent<T> {
3939
redundant: boolean;
4040
value: T;
4141
}
42+
43+
export interface Signoff {
44+
commitId: string;
45+
releases: string[];
46+
taggedAt?: string;
47+
}

0 commit comments

Comments
 (0)