Fixes #542 Add previous tag option (#550)

This commit is contained in:
Nick Cipollo
2025-09-02 15:56:40 -04:00
committed by GitHub
parent 98d25d4189
commit e87de4c2e4
8 changed files with 99 additions and 21 deletions

View File

@@ -49,6 +49,7 @@ const updateOnlyUnreleased = false
const url = TEST_URLS.UPLOAD_URL
const makeLatest = "legacy"
const generatedReleaseBody = "test release notes"
const previousTag = "v1.0.0"
describe("Action", () => {
beforeEach(() => {
@@ -68,7 +69,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -89,7 +90,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -131,7 +132,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
`${createBody}\n${generatedReleaseBody}`,
@@ -147,12 +148,31 @@ describe("Action", () => {
assertAssetUrlsApplied({})
})
it("creates release with combined body and generated release notes using previous tag", async () => {
const action = createAction(false, false, false, true, false, createBody, true, createDraft, updateBody, previousTag)
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, previousTag)
expect(createMock).toHaveBeenCalledWith(
tag,
`${createBody}\n${generatedReleaseBody}`,
commit,
discussionCategory,
createDraft,
makeLatest,
createName,
createPrerelease
)
expect(uploadMock).not.toHaveBeenCalled()
})
it("creates release but does not upload if no artifact", async () => {
const action = createAction(false, false, false, true, false, "")
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -175,7 +195,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -204,7 +224,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -228,7 +248,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -294,7 +314,7 @@ describe("Action", () => {
expect(error).toEqual("error")
}
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -395,7 +415,7 @@ describe("Action", () => {
expect(error).toEqual(expectedError)
}
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(createMock).toHaveBeenCalledWith(
tag,
generatedReleaseBody,
@@ -478,7 +498,7 @@ describe("Action", () => {
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, undefined)
expect(updateMock).toHaveBeenCalledWith(
id,
tag,
@@ -498,6 +518,26 @@ describe("Action", () => {
})
})
it("updates release with combined body and generated release notes using previous tag", async () => {
const action = createAction(true, true, false, true, false, "", true, createDraft, updateBody, previousTag)
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag, previousTag)
expect(updateMock).toHaveBeenCalledWith(
id,
tag,
`${updateBody}\n${generatedReleaseBody}`,
commit,
discussionCategory,
updateDraft,
makeLatest,
updateName,
updatePrerelease
)
expect(uploadMock).toHaveBeenCalledWith(artifacts, releaseId, url)
})
it("updates release but does not upload if no artifact", async () => {
const action = createAction(true, false, false, true, false, "", true, createDraft, "")
@@ -737,7 +777,8 @@ describe("Action", () => {
createdReleaseBody = createBody,
immutableCreate = true,
createdDraft = createDraft,
updatedReleaseBody = updateBody
updatedReleaseBody = updateBody,
generateReleaseNotesPreviousTag: string | undefined = undefined
): Action {
let inputArtifact: Artifact[]
@@ -809,6 +850,7 @@ describe("Action", () => {
commit,
discussionCategory,
generateReleaseNotes,
generateReleaseNotesPreviousTag: generateReleaseNotesPreviousTag,
immutableCreate: immutableCreate,
makeLatest: makeLatest,
owner: "owner",

View File

@@ -200,6 +200,18 @@ describe("Inputs", () => {
})
})
describe("generateReleaseNotesPreviousTag", () => {
it("returns the previous tag when provided", function () {
mockGetInput.mockReturnValue("v1.0.0")
expect(inputs.generateReleaseNotesPreviousTag).toBe("v1.0.0")
})
it("returns undefined when omitted", function () {
mockGetInput.mockReturnValue("")
expect(inputs.generateReleaseNotesPreviousTag).toBeUndefined()
})
})
describe("immutableCreate", () => {
it("returns false by default", function () {
mockGetInput.mockReturnValue("")

View File

@@ -47,6 +47,10 @@ inputs:
description: 'Indicates if release notes should be automatically generated.'
required: false
default: 'false'
generateReleaseNotesPreviousTag:
description: 'An optional previous tag to use when generating release notes. This will limit the release notes to changes between the two tags.'
required: false
default: ''
immutableCreate:
description: 'Indicates if immutable release creation should be used. When enabled, the action will first create a draft, upload artifacts, then publish the release.'
required: false

16
dist/index.js vendored
View File

@@ -168,7 +168,7 @@ class Action {
if (!shouldGenerateReleaseNotes) {
return body;
}
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
const response = await this.releases.generateReleaseNotes(this.inputs.tag, this.inputs.generateReleaseNotesPreviousTag);
const releaseNotes = response.data.body;
if (!body || body.trim() === "") {
return releaseNotes;
@@ -867,6 +867,10 @@ class CoreInputs {
const generate = core.getInput("generateReleaseNotes");
return generate == "true";
}
get generateReleaseNotesPreviousTag() {
const previousTag = core.getInput("generateReleaseNotesPreviousTag");
return previousTag || undefined;
}
get immutableCreate() {
const immutable = core.getInput("immutableCreate");
return immutable == "true";
@@ -1107,12 +1111,16 @@ class GithubReleases {
repo: this.inputs.repo,
});
}
async generateReleaseNotes(tag) {
return this.git.rest.repos.generateReleaseNotes({
async generateReleaseNotes(tag, previousTag) {
const params = {
owner: this.inputs.owner,
repo: this.inputs.repo,
tag_name: tag,
});
};
if (previousTag) {
params.previous_tag_name = previousTag;
}
return this.git.rest.repos.generateReleaseNotes(params);
}
async getByTag(tag) {
return this.git.rest.repos.getReleaseByTag({

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -197,7 +197,7 @@ export class Action {
return body
}
const response = await this.releases.generateReleaseNotes(this.inputs.tag)
const response = await this.releases.generateReleaseNotes(this.inputs.tag, this.inputs.generateReleaseNotesPreviousTag)
const releaseNotes = response.data.body
if (!body || body.trim() === "") {

View File

@@ -15,6 +15,7 @@ export interface Inputs {
readonly createdReleaseName?: string
readonly discussionCategory?: string
readonly generateReleaseNotes: boolean
readonly generateReleaseNotesPreviousTag?: string
readonly immutableCreate: boolean
readonly makeLatest?: "legacy" | "true" | "false" | undefined
readonly omitBodyDuringUpdate: boolean
@@ -138,6 +139,11 @@ export class CoreInputs implements Inputs {
return generate == "true"
}
get generateReleaseNotesPreviousTag(): string | undefined {
const previousTag = core.getInput("generateReleaseNotesPreviousTag")
return previousTag || undefined
}
get immutableCreate(): boolean {
const immutable = core.getInput("immutableCreate")
return immutable == "true"

View File

@@ -36,7 +36,7 @@ export interface Releases {
getByTag(tag: string): Promise<ReleaseByTagResponse>
generateReleaseNotes(tag: string): Promise<GenerateReleaseNotesResponse>
generateReleaseNotes(tag: string, previousTag?: string): Promise<GenerateReleaseNotesResponse>
listArtifactsForRelease(releaseId: number): Promise<ListReleaseAssetsResponseData>
@@ -106,12 +106,18 @@ export class GithubReleases implements Releases {
})
}
async generateReleaseNotes(tag: string): Promise<GenerateReleaseNotesResponse> {
return this.git.rest.repos.generateReleaseNotes({
async generateReleaseNotes(tag: string, previousTag?: string): Promise<GenerateReleaseNotesResponse> {
const params: any = {
owner: this.inputs.owner,
repo: this.inputs.repo,
tag_name: tag,
})
}
if (previousTag) {
params.previous_tag_name = previousTag
}
return this.git.rest.repos.generateReleaseNotes(params)
}
async getByTag(tag: string): Promise<ReleaseByTagResponse> {