Skip to content

Commit

Permalink
fix(github): support multiple releases
Browse files Browse the repository at this point in the history
  • Loading branch information
Wroud committed Sep 22, 2024
1 parent ee8d1f9 commit afb329d
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 74 deletions.
115 changes: 63 additions & 52 deletions packages/ci/src/publishGithubRelease.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Octokit } from "@octokit/rest";
import { getGitLastSemverTag, getGitPrefixedTag } from "@wroud/git";
import { getGitLastSemverTags, getGitPrefixedTag } from "@wroud/git";
import { readPackageJson } from "./readPackageJson.js";
import semver from "semver";
import { readChangelogForVersion } from "./readChangelogForVersion.js";
import { execa } from "execa";

export interface IPublishGithubReleaseOptions {
auth?: any;
Expand All @@ -27,70 +28,80 @@ export async function publishGithubRelease({
authStrategy,
});

const tag = await getGitLastSemverTag({
prefix,
});

if (!tag) {
console.log("No release tag found");
return;
}
const tagsToRelease: string[] = [];

if (dryRun) {
console.log(`Checking release for tag ${tag}`);
} else {
try {
const release = await octokit.repos.getReleaseByTag({
owner,
repo: repository,
tag,
});
for await (const tag of getGitLastSemverTags({
prefix,
})) {
if (dryRun) {
console.log(`Checking release for tag ${tag}`);
tagsToRelease.push(tag);
break;
} else {
try {
const release = await octokit.repos.getReleaseByTag({
owner,
repo: repository,
tag,
});

if (release.status === 200) {
console.log(`Release ${tag} already exists`);
return;
}
} catch (e: any) {
if (e.status !== 404) {
throw e;
if (release.status === 200) {
console.log(`Release ${tag} already exists`);
break;
}
} catch (e: any) {
if (e.status !== 404) {
throw e;
}
tagsToRelease.push(tag);
}
}
}

const { name, version } = await readPackageJson();

if (!version) {
throw new Error("Version not found in package.json");
if (!tagsToRelease.length) {
console.log("No tags to release");
return;
}

if (dryRun) {
console.log("Check if tag matches version", tag, version);
tagsToRelease.reverse();

for (const tag of tagsToRelease) {
await execa("git", ["checkout", tag]);
const { name, version } = await readPackageJson();

if (tag !== getGitPrefixedTag(version, prefix)) {
console.error(`Tag ${tag} does not match version ${version}`);
if (!version) {
throw new Error("Version not found in package.json");
}
} else {
if (tag !== getGitPrefixedTag(version, prefix)) {
throw new Error(`Tag ${tag} does not match version ${version}`);

if (dryRun) {
console.log("Check if tag matches version", tag, version);

if (tag !== getGitPrefixedTag(version, prefix)) {
console.error(`Tag ${tag} does not match version ${version}`);
}
} else {
if (tag !== getGitPrefixedTag(version, prefix)) {
throw new Error(`Tag ${tag} does not match version ${version}`);
}
}
}

const body = await readChangelogForVersion({ version });
const body = await readChangelogForVersion({ version });

const options = {
owner,
repo: repository,
tag_name: tag,
name: `${name}@${version}`,
body,
draft: false,
prerelease: (semver.parse(version)?.prerelease || []).length > 0,
};
const options = {
owner,
repo: repository,
tag_name: tag,
name: `${name}@${version}`,
body,
draft: false,
prerelease: (semver.parse(version)?.prerelease || []).length > 0,
};

if (dryRun) {
console.log("Creating release", options);
} else {
await octokit.repos.createRelease(options);
if (dryRun) {
console.log("Creating release", options);
} else {
await octokit.repos.createRelease(options);
}
console.log(`${options.name} released`);
}
console.log(`Release ${tag} created`);
}
25 changes: 3 additions & 22 deletions packages/git/src/getGitLastSemverTag.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { execa } from "execa";
import semverRegex from "semver-regex";
import { validateGitEnvironment } from "./validateGitEnvironment.js";
import { defaultTagPrefix } from "./defaultTagPrefix.js";
import { getGitLastSemverTags } from "./getGitLastSemverTags.js";

interface IGitGetLastTagOptions {
to?: string;
Expand All @@ -12,25 +10,8 @@ export async function getGitLastSemverTag({
to,
prefix = defaultTagPrefix,
}: IGitGetLastTagOptions = {}): Promise<string | null> {
await validateGitEnvironment();
try {
const args = ["tag", "--list", `${prefix}*`];

if (to) {
args.push("--merged", to);
}

args.push("--sort=-v:refname");
for await (const tag of execa("git", args)) {
if (
tag.startsWith(prefix) &&
semverRegex().test(tag.slice(prefix.length))
) {
return tag;
}
}
} catch (e: any) {
console.error(e);
for await (const tag of getGitLastSemverTags({ to, prefix })) {
return tag;
}
return null;
}
35 changes: 35 additions & 0 deletions packages/git/src/getGitLastSemverTags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { execa } from "execa";
import semverRegex from "semver-regex";
import { validateGitEnvironment } from "./validateGitEnvironment.js";
import { defaultTagPrefix } from "./defaultTagPrefix.js";

interface IGitGetLastTagsOptions {
to?: string;
prefix?: string;
}

export async function* getGitLastSemverTags({
to,
prefix = defaultTagPrefix,
}: IGitGetLastTagsOptions = {}): AsyncGenerator<string> {
await validateGitEnvironment();
try {
const args = ["tag", "--list", `${prefix}*`];

if (to) {
args.push("--merged", to);
}

args.push("--sort=-v:refname");
for await (const tag of execa("git", args)) {
if (
tag.startsWith(prefix) &&
semverRegex().test(tag.slice(prefix.length))
) {
yield tag;
}
}
} catch (e: any) {
console.error(e);
}
}
1 change: 1 addition & 0 deletions packages/git/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export * from "./IGitCommitInfo.js";
export * from "./IGitTrailer.js";
export * from "./getGitCommits.js";
export * from "./getGitLastSemverTag.js";
export * from "./getGitLastSemverTags.js";
export * from "./getGitPrefixedTag.js";
export * from "./IGitLink.js";

0 comments on commit afb329d

Please sign in to comment.