Fixes #548 Add support body + generated release notes (#549)

This commit is contained in:
Nick Cipollo
2025-09-02 12:27:56 -04:00
committed by GitHub
parent 571fe81601
commit d3601261f8
4 changed files with 104 additions and 40 deletions

View File

@@ -85,7 +85,7 @@ describe("Action", () => {
})
it("creates release with generated release notes that override existing body", async () => {
const action = createAction(false, false, false, true, false, "existing body")
const action = createAction(false, false, false, true, false, "")
await action.perform()
@@ -126,8 +126,29 @@ describe("Action", () => {
assertAssetUrlsApplied({})
})
it("creates release with combined body and generated release notes", async () => {
const action = createAction(false, false, false, true, false, createBody)
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(createMock).toHaveBeenCalledWith(
tag,
`${createBody}\n${generatedReleaseBody}`,
commit,
discussionCategory,
createDraft,
makeLatest,
createName,
createPrerelease
)
expect(uploadMock).not.toHaveBeenCalled()
assertOutputApplied()
assertAssetUrlsApplied({})
})
it("creates release but does not upload if no artifact", async () => {
const action = createAction(false, false)
const action = createAction(false, false, false, true, false, "")
await action.perform()
@@ -148,7 +169,7 @@ describe("Action", () => {
})
it("creates release if no release exists to update", async () => {
const action = createAction(true, true)
const action = createAction(true, true, false, true, false, "")
const error = { status: 404 }
getMock.mockRejectedValue(error)
@@ -174,7 +195,7 @@ describe("Action", () => {
})
it("creates release if no draft releases", async () => {
const action = createAction(true, true)
const action = createAction(true, true, false, true, false, "")
const error = { status: 404 }
getMock.mockRejectedValue(error)
listMock.mockResolvedValue({
@@ -203,7 +224,7 @@ describe("Action", () => {
})
it("creates release then uploads artifact", async () => {
const action = createAction(false, true)
const action = createAction(false, true, false, true, false, "")
await action.perform()
@@ -263,7 +284,7 @@ describe("Action", () => {
})
it("throws error when create fails", async () => {
const action = createAction(false, true)
const action = createAction(false, true, false, true, false, "")
createMock.mockRejectedValue("error")
expect.hasAssertions()
@@ -337,7 +358,7 @@ describe("Action", () => {
})
it("throws error when update fails", async () => {
const action = createAction(true, true)
const action = createAction(true, true, false, true, false, "", true, createDraft, "")
updateMock.mockRejectedValue("error")
@@ -363,7 +384,7 @@ describe("Action", () => {
})
it("throws error when upload fails", async () => {
const action = createAction(false, true)
const action = createAction(false, true, false, true, false, "")
const expectedError = { status: 404 }
uploadMock.mockRejectedValue(expectedError)
@@ -389,7 +410,7 @@ describe("Action", () => {
})
it("updates draft release", async () => {
const action = createAction(true, true)
const action = createAction(true, true, false, true, false, "", true, createDraft, "")
const error = { status: 404 }
getMock.mockRejectedValue(error)
listMock.mockResolvedValue({
@@ -452,8 +473,33 @@ describe("Action", () => {
})
})
it("updates release with combined body and generated release notes", async () => {
const action = createAction(true, true, false, true, false, "", true, createDraft, updateBody)
await action.perform()
expect(genReleaseNotesMock).toHaveBeenCalledWith(tag)
expect(updateMock).toHaveBeenCalledWith(
id,
tag,
`${updateBody}\n${generatedReleaseBody}`,
commit,
discussionCategory,
updateDraft,
makeLatest,
updateName,
updatePrerelease
)
expect(uploadMock).toHaveBeenCalledWith(artifacts, releaseId, url)
assertOutputApplied()
assertAssetUrlsApplied({
"art1": "https://github.com/owner/repo/releases/download/v1.0.0/art1",
"art2": "https://github.com/owner/repo/releases/download/v1.0.0/art2",
})
})
it("updates release but does not upload if no artifact", async () => {
const action = createAction(true, false)
const action = createAction(true, false, false, true, false, "", true, createDraft, "")
await action.perform()
@@ -474,7 +520,7 @@ describe("Action", () => {
})
it("updates release then uploads artifact", async () => {
const action = createAction(true, true)
const action = createAction(true, true, false, true, false, "", true, createDraft, "")
await action.perform()
@@ -530,7 +576,7 @@ describe("Action", () => {
})
it("does not publish immutable release when immutableCreate is false", async () => {
const action = createAction(false, true, false, true, false, createBody, false, false)
const action = createAction(false, true, false, true, false, "", false, false)
await action.perform()
@@ -550,7 +596,7 @@ describe("Action", () => {
})
it("does not publish immutable release when createdDraft is true", async () => {
const action = createAction(false, true, false, true, false, createBody, true, true)
const action = createAction(false, true, false, true, false, "", true, true)
await action.perform()
@@ -570,7 +616,7 @@ describe("Action", () => {
})
it("publishes immutable release when immutableCreate is true and createdDraft is false", async () => {
const action = createAction(false, true, false, true, false, createBody, true, false)
const action = createAction(false, true, false, true, false, "", true, false)
const immutableReleaseResponse = {
data: {
id: 999,
@@ -615,7 +661,7 @@ describe("Action", () => {
})
it("publishes immutable release when allowUpdates is true but release does not exist", async () => {
const action = createAction(true, true, false, true, false, createBody, true, false)
const action = createAction(true, true, false, true, false, "", true, false)
const error = { status: 404 }
getMock.mockRejectedValue(error)
listMock.mockResolvedValue({ data: [] }) // No draft releases found
@@ -690,7 +736,8 @@ describe("Action", () => {
omitBodyDuringUpdate = false,
createdReleaseBody = createBody,
immutableCreate = true,
createdDraft = createDraft
createdDraft = createDraft,
updatedReleaseBody = updateBody
): Action {
let inputArtifact: Artifact[]
@@ -773,7 +820,7 @@ describe("Action", () => {
tag,
token,
updatedDraft: updateDraft,
updatedReleaseBody: updateBody,
updatedReleaseBody: updatedReleaseBody,
updatedReleaseName: updateName,
updatedPrerelease: updatePrerelease,
updateOnlyUnreleased: updateOnlyUnreleased,

27
dist/index.js vendored
View File

@@ -118,20 +118,12 @@ class Action {
return draftRelease?.id;
}
async updateRelease(id) {
let releaseBody = this.inputs.updatedReleaseBody;
if (this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate) {
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
releaseBody = response.data.body;
}
const releaseBody = await this.combineBodyWithReleaseNotes(this.inputs.updatedReleaseBody, true);
const releaseResponse = await this.releases.update(id, this.inputs.tag, releaseBody, this.inputs.commit, this.inputs.discussionCategory, this.inputs.updatedDraft, this.inputs.makeLatest, this.inputs.updatedReleaseName, this.inputs.updatedPrerelease);
await this.processReleaseArtifactsAndOutputs(releaseResponse, false);
}
async createRelease() {
let releaseBody = this.inputs.createdReleaseBody;
if (this.inputs.generateReleaseNotes) {
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
releaseBody = response.data.body;
}
const releaseBody = await this.combineBodyWithReleaseNotes(this.inputs.createdReleaseBody, false);
// If immutableCreate is enabled we need to start with a draft release
const draft = this.inputs.createdDraft || this.inputs.immutableCreate;
const releaseResponse = await this.releases.create(this.inputs.tag, releaseBody, this.inputs.commit, this.inputs.discussionCategory, draft, this.inputs.makeLatest, this.inputs.createdReleaseName, this.inputs.createdPrerelease);
@@ -168,6 +160,21 @@ class Action {
this.inputs.discussionCategory, false, // We want to publish the release, set draft to false
this.inputs.makeLatest, this.inputs.createdReleaseName, this.inputs.createdPrerelease);
}
async combineBodyWithReleaseNotes(body, isUpdate) {
// Determine if we should generate release notes based on operation type
const shouldGenerateReleaseNotes = isUpdate
? this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate
: this.inputs.generateReleaseNotes;
if (!shouldGenerateReleaseNotes) {
return body;
}
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
const releaseNotes = response.data.body;
if (!body || body.trim() === "") {
return releaseNotes;
}
return `${body}\n${releaseNotes}`;
}
setOutputs(releaseData, assetUrls) {
this.outputs.applyReleaseData(releaseData);
this.outputs.applyAssetUrls(assetUrls);

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -105,12 +105,7 @@ export class Action {
}
private async updateRelease(id: number) {
let releaseBody = this.inputs.updatedReleaseBody
if (this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate) {
const response = await this.releases.generateReleaseNotes(this.inputs.tag)
releaseBody = response.data.body
}
const releaseBody = await this.combineBodyWithReleaseNotes(this.inputs.updatedReleaseBody, true)
const releaseResponse = await this.releases.update(
id,
@@ -128,12 +123,7 @@ export class Action {
}
private async createRelease() {
let releaseBody = this.inputs.createdReleaseBody
if (this.inputs.generateReleaseNotes) {
const response = await this.releases.generateReleaseNotes(this.inputs.tag)
releaseBody = response.data.body
}
const releaseBody = await this.combineBodyWithReleaseNotes(this.inputs.createdReleaseBody, false)
// If immutableCreate is enabled we need to start with a draft release
const draft = this.inputs.createdDraft || this.inputs.immutableCreate
@@ -197,6 +187,26 @@ export class Action {
)
}
private async combineBodyWithReleaseNotes(body: string | undefined, isUpdate: boolean): Promise<string | undefined> {
// Determine if we should generate release notes based on operation type
const shouldGenerateReleaseNotes = isUpdate
? this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate
: this.inputs.generateReleaseNotes
if (!shouldGenerateReleaseNotes) {
return body
}
const response = await this.releases.generateReleaseNotes(this.inputs.tag)
const releaseNotes = response.data.body
if (!body || body.trim() === "") {
return releaseNotes
}
return `${body}\n${releaseNotes}`
}
private setOutputs(releaseData: any, assetUrls: Record<string, string>): void {
this.outputs.applyReleaseData(releaseData)
this.outputs.applyAssetUrls(assetUrls)