Skip to content

Commit

Permalink
feat: add generate from latest tag
Browse files Browse the repository at this point in the history
  • Loading branch information
pocesar committed Jul 11, 2023
1 parent c9b46fe commit bbaeef1
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 13 deletions.
11 changes: 11 additions & 0 deletions __tests__/util.test.ts
Expand Up @@ -52,6 +52,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
})
);
});
Expand All @@ -72,6 +73,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
})
);
});
Expand All @@ -92,6 +94,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
})
);
});
Expand Down Expand Up @@ -125,6 +128,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand All @@ -150,6 +154,7 @@ describe("util", () => {
input_target_commitish: "affa18ef97bc9db20076945705aba8c516139abd",
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand All @@ -174,6 +179,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: "releases",
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand All @@ -199,6 +205,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: true,
input_previous_tag: undefined,
}
);
});
Expand Down Expand Up @@ -227,6 +234,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand All @@ -253,6 +261,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand All @@ -278,6 +287,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand All @@ -302,6 +312,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_previous_tag: undefined,
}
);
});
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Expand Up @@ -43,6 +43,10 @@ inputs:
generate_release_notes:
description: "Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes."
required: false
previous_tag:
description: "The tag name of the previous release. If not specified, the previous tag will be detected automatically."
required: false
default: ""
append_body:
description: "Append to existing body instead of overwriting it. Default is false."
required: false
Expand Down
107 changes: 94 additions & 13 deletions src/github.ts
Expand Up @@ -44,7 +44,6 @@ export interface Releaser {
prerelease: boolean | undefined;
target_commitish: string | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }>;

updateRelease(params: {
Expand All @@ -58,13 +57,21 @@ export interface Releaser {
draft: boolean | undefined;
prerelease: boolean | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }>;

allReleases(params: {
owner: string;
repo: string;
}): AsyncIterableIterator<{ data: Release[] }>;

getLatestTag(params: {
owner: string;
repo: string;
}): Promise<undefined | string>;

generateReleaseBody(
params: Parameters<GitHub["rest"]["repos"]["generateReleaseNotes"]>[0]
): Promise<string>;
}

export class GitHubReleaser implements Releaser {
Expand All @@ -91,9 +98,11 @@ export class GitHubReleaser implements Releaser {
prerelease: boolean | undefined;
target_commitish: string | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }> {
return this.github.rest.repos.createRelease(params);
return this.github.rest.repos.createRelease({
...params,
generate_release_notes: false,
});
}

updateRelease(params: {
Expand All @@ -107,9 +116,11 @@ export class GitHubReleaser implements Releaser {
draft: boolean | undefined;
prerelease: boolean | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }> {
return this.github.rest.repos.updateRelease(params);
return this.github.rest.repos.updateRelease({
...params,
generate_release_notes: false,
});
}

allReleases(params: {
Expand All @@ -121,6 +132,41 @@ export class GitHubReleaser implements Releaser {
this.github.rest.repos.listReleases.endpoint.merge(updatedParams)
);
}

async getLatestTag(params: {
owner: string;
repo: string;
}): Promise<undefined | string> {
try {
const release = await this.github.rest.repos.getLatestRelease(params);

if (!release?.data) {
return;
}

return release.data.tag_name;
} catch (e) {
console.error(e);

return;
}
}

async generateReleaseBody(
params: Parameters<GitHub["rest"]["repos"]["generateReleaseNotes"]>[0]
): Promise<string> {
try {
const { data } = await this.github.rest.repos.generateReleaseNotes(params);

if (!data.body) {
throw new Error("No release body generated");
}

return data.body;
} catch (e) {
throw e;
}
}
}

export const asset = (path: string): ReleaseAsset => {
Expand Down Expand Up @@ -196,8 +242,38 @@ export const release = async (
? config.github_ref.replace("refs/tags/", "")
: "");

const previous_tag = config.input_previous_tag;
const discussion_category_name = config.input_discussion_category_name;
const generate_release_notes = config.input_generate_release_notes;

const latestTag: string | undefined = !previous_tag
? await releaser.getLatestTag({
owner,
repo,
})
: undefined;

if (latestTag) {
console.log(`Latest tag related to a release is ${latestTag}`);
}

const tag_name = tag;

let body: string = generate_release_notes
? await releaser.generateReleaseBody({
owner,
repo,
tag_name,
previous_tag_name: previous_tag || latestTag,
})
: "";

if (generate_release_notes && previous_tag || latestTag) {
console.log(`Will generate release notes using ${previous_tag || latestTag} as previous tag`);
}

body = body ? `${body}\n` : "";

try {
// you can't get a an existing draft by tag
// so we must find one in the list of all releases
Expand Down Expand Up @@ -232,19 +308,20 @@ export const release = async (
target_commitish = existingRelease.data.target_commitish;
}

const tag_name = tag;
const name = config.input_name || existingRelease.data.name || tag;
// revisit: support a new body-concat-strategy input for accumulating
// body parts as a release gets updated. some users will likely want this while
// others won't previously this was duplicating content for most which
// no one wants
const workflowBody = releaseBody(config) || "";
const existingReleaseBody = existingRelease.data.body || "";
let body: string;

if (config.input_append_body && workflowBody && existingReleaseBody) {
body = existingReleaseBody + "\n" + workflowBody;
console.log('➕ Appending existing release body');
body = body + existingReleaseBody + "\n" + workflowBody;
} else {
body = workflowBody || existingReleaseBody;
console.log(`➕ Using ${workflowBody ? 'workflow body' : 'existing release body'}`);
body = body + (workflowBody || existingReleaseBody);
}

const draft =
Expand All @@ -267,14 +344,19 @@ export const release = async (
draft,
prerelease,
discussion_category_name,
generate_release_notes,
});
return release.data;
} catch (error) {
if (error.status === 404) {
const tag_name = tag;
const name = config.input_name || tag;
const body = releaseBody(config);
const workflowBody = releaseBody(config) || "";

if (config.input_append_body && workflowBody) {
console.log('➕ Appending existing release body');
body = body + workflowBody;
}

const draft = config.input_draft;
const prerelease = config.input_prerelease;
const target_commitish = config.input_target_commitish;
Expand All @@ -296,7 +378,6 @@ export const release = async (
prerelease,
target_commitish,
discussion_category_name,
generate_release_notes,
});
return release.data;
} catch (error) {
Expand Down
2 changes: 2 additions & 0 deletions src/util.ts
Expand Up @@ -19,6 +19,7 @@ export interface Config {
input_discussion_category_name?: string;
input_generate_release_notes?: boolean;
input_append_body?: boolean;
input_previous_tag?: string;
}

export const uploadUrl = (url: string): string => {
Expand Down Expand Up @@ -70,6 +71,7 @@ export const parseConfig = (env: Env): Config => {
env.INPUT_DISCUSSION_CATEGORY_NAME || undefined,
input_generate_release_notes: env.INPUT_GENERATE_RELEASE_NOTES == "true",
input_append_body: env.INPUT_APPEND_BODY == "true",
input_previous_tag: env.INPUT_PREVIOUS_TAG?.trim() || undefined,
};
};

Expand Down

0 comments on commit bbaeef1

Please sign in to comment.