diff --git a/README.md b/README.md index a570d9b..af7e9b6 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This action will create a github release and optionally upload an artifact to it - **body**: An optional body for the release. - **bodyFile**: An optional body file for the release. This should be the path to the file. - **commit**: An optional commit reference. This will be used to create the tag if it does not exist. +- **discussionCategory**: When provided this will generate a discussion of the specified category. The category must exist otherwise this will cause the action to fail. This isn't used with draft releases. - **draft**: Optionally marks this release as a draft release. Set to `true` to enable. - **name**: An optional name for the release. If this is omitted the tag will be used. - **omitBody**: Indicates if the release body should be omitted. diff --git a/__tests__/Action.test.ts b/__tests__/Action.test.ts index 6351c07..8a98a9d 100644 --- a/__tests__/Action.test.ts +++ b/__tests__/Action.test.ts @@ -17,10 +17,10 @@ const artifacts = [ new Artifact('b/art2') ] -const artifactErrorsFailBuild = false const createBody = 'createBody' const createName = 'createName' const commit = 'commit' +const discussionCategory = 'discussionCategory' const draft = true const id = 100 const prerelease = true @@ -46,7 +46,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, discussionCategory, draft, createName, prerelease) expect(uploadMock).not.toBeCalled() }) @@ -57,7 +57,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, discussionCategory, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -73,7 +73,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, discussionCategory, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -83,7 +83,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, discussionCategory, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -98,7 +98,7 @@ describe("Action", () => { expect(error).toEqual("error") } - expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, discussionCategory, draft, createName, prerelease) expect(uploadMock).not.toBeCalled() }) @@ -139,22 +139,32 @@ describe("Action", () => { expect(error).toEqual("error") } - expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) + expect(updateMock).toBeCalledWith( + id, + tag, + updateBody, + commit, + discussionCategory, + draft, + updateName, + prerelease + ) expect(uploadMock).not.toBeCalled() }) it('throws error when upload fails', async () => { const action = createAction(false, true) - uploadMock.mockRejectedValue("error") + const expectedError = {status: 404} + uploadMock.mockRejectedValue(expectedError) expect.hasAssertions() try { await action.perform() } catch (error) { - expect(error).toEqual("error") + expect(error).toEqual(expectedError) } - expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, discussionCategory, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -171,7 +181,16 @@ describe("Action", () => { await action.perform() - expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) + expect(updateMock).toBeCalledWith( + id, + tag, + updateBody, + commit, + discussionCategory, + draft, + updateName, + prerelease + ) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -181,7 +200,16 @@ describe("Action", () => { await action.perform() - expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) + expect(updateMock).toBeCalledWith( + id, + tag, + updateBody, + commit, + discussionCategory, + draft, + updateName, + prerelease + ) expect(uploadMock).not.toBeCalled() }) @@ -191,7 +219,16 @@ describe("Action", () => { await action.perform() - expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) + expect(updateMock).toBeCalledWith( + id, + tag, + updateBody, + commit, + discussionCategory, + draft, + updateName, + prerelease + ) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -245,6 +282,7 @@ describe("Action", () => { createdReleaseBody: createBody, createdReleaseName: createName, commit: commit, + discussionCategory: discussionCategory, draft: draft, owner: "owner", prerelease: prerelease, diff --git a/__tests__/Inputs.test.ts b/__tests__/Inputs.test.ts index eb350be..73d5450 100644 --- a/__tests__/Inputs.test.ts +++ b/__tests__/Inputs.test.ts @@ -179,6 +179,18 @@ describe('Inputs', () => { }) }) + describe('discussionCategory', () => { + it('returns category', () => { + mockGetInput.mockReturnValue('Release') + expect(inputs.discussionCategory).toBe('Release') + }) + + it('returns undefined', () => { + mockGetInput.mockReturnValue('') + expect(inputs.discussionCategory).toBe(undefined) + }) + }) + describe('draft', () => { it('returns false', () => { expect(inputs.draft).toBe(false) diff --git a/__tests__/Integration.test.ts b/__tests__/Integration.test.ts index a7f8950..bc9a2bb 100644 --- a/__tests__/Integration.test.ts +++ b/__tests__/Integration.test.ts @@ -9,7 +9,7 @@ import {FileArtifactGlobber} from "../src/ArtifactGlobber"; // This test is currently intended to be manually run during development. To run: // - Make sure you have an environment variable named GITHUB_TOKEN assigned to your token // - Remove skip from the test below -describe.skip('Integration Test', () => { +describe('Integration Test', () => { let action: Action beforeEach(() => { @@ -37,8 +37,9 @@ describe.skip('Integration Test', () => { artifactErrorsFailBuild: false, artifacts: artifacts(), createdReleaseBody: "This release was generated by release-action's integration test", - createdReleaseName: "Releases Action Integration Test", + createdReleaseName: "Releases Action Integration Test 2", commit: "", + discussionCategory: 'Release', draft: false, owner: "ncipollo", prerelease: false, @@ -47,7 +48,7 @@ describe.skip('Integration Test', () => { tag: "release-action-test", token: getToken(), updatedReleaseBody: "This release was generated by release-action's integration test", - updatedReleaseName: "Releases Action Integration Test" + updatedReleaseName: "Releases Action Integration Test 2" } }) return new MockInputs(); diff --git a/action.yml b/action.yml index 5c86176..40457f9 100644 --- a/action.yml +++ b/action.yml @@ -34,6 +34,10 @@ inputs: commit: description: "An optional commit reference. This will be used to create the tag if it does not exist." required: false + default: '' + discussionCategory: + description: "When provided this will generate a discussion of the specified category. The category must exist otherwise this will cause the action to fail. This isn't used with draft releases" + required: false default: '' draft: description: "Optionally marks this release as a draft release. Set to true to enable." diff --git a/lib/Action.js b/lib/Action.js index 83ca0b1..33c5d73 100644 --- a/lib/Action.js +++ b/lib/Action.js @@ -31,27 +31,33 @@ class Action { createOrUpdateRelease() { return __awaiter(this, void 0, void 0, function* () { if (this.inputs.allowUpdates) { + let getResponse; try { - const getResponse = yield this.releases.getByTag(this.inputs.tag); - return yield this.updateRelease(getResponse.data.id); + getResponse = yield this.releases.getByTag(this.inputs.tag); } catch (error) { - if (Action.noPublishedRelease(error)) { - return yield this.updateDraftOrCreateRelease(); - } - else { - throw error; - } + return yield this.checkForMissingReleaseError(error); } + return yield this.updateRelease(getResponse.data.id); } else { return yield this.createRelease(); } }); } + checkForMissingReleaseError(error) { + return __awaiter(this, void 0, void 0, function* () { + if (Action.noPublishedRelease(error)) { + return yield this.updateDraftOrCreateRelease(); + } + else { + throw error; + } + }); + } updateRelease(id) { return __awaiter(this, void 0, void 0, function* () { - return yield this.releases.update(id, this.inputs.tag, this.inputs.updatedReleaseBody, this.inputs.commit, this.inputs.draft, this.inputs.updatedReleaseName, this.inputs.prerelease); + return yield this.releases.update(id, this.inputs.tag, this.inputs.updatedReleaseBody, this.inputs.commit, this.inputs.discussionCategory, this.inputs.draft, this.inputs.updatedReleaseName, this.inputs.prerelease); }); } static noPublishedRelease(error) { @@ -80,7 +86,7 @@ class Action { } createRelease() { return __awaiter(this, void 0, void 0, function* () { - return yield this.releases.create(this.inputs.tag, this.inputs.createdReleaseBody, this.inputs.commit, this.inputs.draft, this.inputs.createdReleaseName, this.inputs.prerelease); + return yield this.releases.create(this.inputs.tag, this.inputs.createdReleaseBody, this.inputs.commit, this.inputs.discussionCategory, this.inputs.draft, this.inputs.createdReleaseName, this.inputs.prerelease); }); } } diff --git a/lib/Inputs.js b/lib/Inputs.js index 0f7e8c2..108e269 100644 --- a/lib/Inputs.js +++ b/lib/Inputs.js @@ -77,6 +77,13 @@ class CoreInputs { return undefined; return this.name; } + get discussionCategory() { + const category = core.getInput('discussionCategory'); + if (category) { + return category; + } + return undefined; + } static get omitName() { return core.getInput('omitName') == 'true'; } diff --git a/lib/Releases.js b/lib/Releases.js index 0948fce..a33f049 100644 --- a/lib/Releases.js +++ b/lib/Releases.js @@ -15,12 +15,13 @@ class GithubReleases { this.inputs = inputs; this.git = git; } - create(tag, body, commitHash, draft, name, prerelease) { + create(tag, body, commitHash, discussionCategory, draft, name, prerelease) { return __awaiter(this, void 0, void 0, function* () { // noinspection TypeScriptValidateJSTypes return this.git.repos.createRelease({ body: body, name: name, + discussion_category_name: discussionCategory, draft: draft, owner: this.inputs.owner, prerelease: prerelease, @@ -65,13 +66,14 @@ class GithubReleases { }); }); } - update(id, tag, body, commitHash, draft, name, prerelease) { + update(id, tag, body, commitHash, discussionCategory, draft, name, prerelease) { return __awaiter(this, void 0, void 0, function* () { // noinspection TypeScriptValidateJSTypes return this.git.repos.updateRelease({ release_id: id, body: body, name: name, + discussion_category_name: discussionCategory, draft: draft, owner: this.inputs.owner, prerelease: prerelease, diff --git a/src/Action.ts b/src/Action.ts index 4144117..bf8552b 100644 --- a/src/Action.ts +++ b/src/Action.ts @@ -1,5 +1,5 @@ import {Inputs} from "./Inputs"; -import {CreateReleaseResponse, Releases, UpdateReleaseResponse} from "./Releases"; +import {CreateReleaseResponse, ReleaseByTagResponse, Releases, UpdateReleaseResponse} from "./Releases"; import {ArtifactUploader} from "./ArtifactUploader"; import {GithubError} from "./GithubError"; @@ -27,20 +27,26 @@ export class Action { private async createOrUpdateRelease(): Promise { if (this.inputs.allowUpdates) { + let getResponse: ReleaseByTagResponse try { - const getResponse = await this.releases.getByTag(this.inputs.tag) - return await this.updateRelease(getResponse.data.id) + getResponse = await this.releases.getByTag(this.inputs.tag) } catch (error) { - if (Action.noPublishedRelease(error)) { - return await this.updateDraftOrCreateRelease() - } else { - throw error - } + return await this.checkForMissingReleaseError(error) } + + return await this.updateRelease(getResponse.data.id) } else { return await this.createRelease() } } + + private async checkForMissingReleaseError(error: Error) : Promise { + if (Action.noPublishedRelease(error)) { + return await this.updateDraftOrCreateRelease() + } else { + throw error + } + } private async updateRelease(id: number): Promise { return await this.releases.update( @@ -48,6 +54,7 @@ export class Action { this.inputs.tag, this.inputs.updatedReleaseBody, this.inputs.commit, + this.inputs.discussionCategory, this.inputs.draft, this.inputs.updatedReleaseName, this.inputs.prerelease @@ -82,6 +89,7 @@ export class Action { this.inputs.tag, this.inputs.createdReleaseBody, this.inputs.commit, + this.inputs.discussionCategory, this.inputs.draft, this.inputs.createdReleaseName, this.inputs.prerelease diff --git a/src/Inputs.ts b/src/Inputs.ts index 1bc1614..dde882b 100644 --- a/src/Inputs.ts +++ b/src/Inputs.ts @@ -11,6 +11,7 @@ export interface Inputs { readonly commit: string readonly createdReleaseBody?: string readonly createdReleaseName?: string + readonly discussionCategory?: string readonly draft: boolean readonly owner: string readonly prerelease: boolean @@ -66,7 +67,7 @@ export class CoreInputs implements Inputs { return core.getInput('omitBody') == 'true' } - private get body() : string | undefined { + private get body(): string | undefined { const body = core.getInput('body') if (body) { return body @@ -89,6 +90,14 @@ export class CoreInputs implements Inputs { return this.name } + get discussionCategory(): string | undefined { + const category = core.getInput('discussionCategory') + if (category) { + return category + } + return undefined + } + private static get omitName(): boolean { return core.getInput('omitName') == 'true' } @@ -162,7 +171,7 @@ export class CoreInputs implements Inputs { } get updatedReleaseName(): string | undefined { - if (CoreInputs.omitName || CoreInputs.omitNameDuringUpdate) return undefined + if (CoreInputs.omitName || CoreInputs.omitNameDuringUpdate) return undefined return this.name } diff --git a/src/Releases.ts b/src/Releases.ts index cdf4baa..2d6803e 100644 --- a/src/Releases.ts +++ b/src/Releases.ts @@ -15,6 +15,7 @@ export interface Releases { tag: string, body?: string, commitHash?: string, + discussionCategory?: string, draft?: boolean, name?: string, prerelease?: boolean @@ -33,6 +34,7 @@ export interface Releases { tag: string, body?: string, commitHash?: string, + discussionCategory?: string, draft?: boolean, name?: string, prerelease?: boolean @@ -61,6 +63,7 @@ export class GithubReleases implements Releases { tag: string, body?: string, commitHash?: string, + discussionCategory?: string, draft?: boolean, name?: string, prerelease?: boolean @@ -69,6 +72,7 @@ export class GithubReleases implements Releases { return this.git.repos.createRelease({ body: body, name: name, + discussion_category_name: discussionCategory, draft: draft, owner: this.inputs.owner, prerelease: prerelease, @@ -118,6 +122,7 @@ export class GithubReleases implements Releases { tag: string, body?: string, commitHash?: string, + discussionCategory?: string, draft?: boolean, name?: string, prerelease?: boolean @@ -127,6 +132,7 @@ export class GithubReleases implements Releases { release_id: id, body: body, name: name, + discussion_category_name: discussionCategory, draft: draft, owner: this.inputs.owner, prerelease: prerelease,