diff --git a/README.md b/README.md index 218c317..5683a0a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ This action will create a github release and optionally upload an artifact to it - **replacesArtifacts**: Indicates if existing release artifacts should be replaced. Defaults to true. - **tag**: An optional tag for the release. If this is omitted the git ref will be used (if it is a tag). - **token**: (**Required**) The Github token. Typically this will be `${{ secrets.GITHUB_TOKEN }}`. +- **omitBodyDuringUpdate**: Indicates if the release body should be omitted during updates. The body will still be applied for newly created releases. This will preserve the existing body during updates. +- **omitNameDuringUpdate**: Indicates if the release name should be omitted during updates. The name will still be applied for newly created releases. This will preserve the existing name during updates. ## Example This example will create a release when tag is pushed: diff --git a/__tests__/Action.test.ts b/__tests__/Action.test.ts index 0975071..0632c84 100644 --- a/__tests__/Action.test.ts +++ b/__tests__/Action.test.ts @@ -16,17 +16,19 @@ const artifacts = [ new Artifact('a/art1'), new Artifact('b/art2') ] -const artifactData = Buffer.from('blob', 'utf-8') -const body = 'body' + +const createBody = 'createBody' +const createName = 'createName' const commit = 'commit' const draft = true const id = 100 -const name = 'name' const prerelease = true const releaseId = 101 const replacesArtifacts = true const tag = 'tag' const token = 'token' +const updateBody = 'updateBody' +const updateName = 'updateName' const url = 'http://api.example.com' describe("Action", () => { @@ -43,7 +45,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) expect(uploadMock).not.toBeCalled() }) @@ -54,7 +56,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -70,7 +72,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -80,7 +82,7 @@ describe("Action", () => { await action.perform() - expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -95,7 +97,7 @@ describe("Action", () => { expect(error).toEqual("error") } - expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) expect(uploadMock).not.toBeCalled() }) @@ -136,7 +138,7 @@ describe("Action", () => { expect(error).toEqual("error") } - expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease) + expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) expect(uploadMock).not.toBeCalled() }) @@ -151,7 +153,7 @@ describe("Action", () => { expect(error).toEqual("error") } - expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) + expect(createMock).toBeCalledWith(tag, createBody, commit, draft, createName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -168,7 +170,7 @@ describe("Action", () => { await action.perform() - expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease) + expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -178,7 +180,7 @@ describe("Action", () => { await action.perform() - expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease) + expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) expect(uploadMock).not.toBeCalled() }) @@ -188,7 +190,7 @@ describe("Action", () => { await action.perform() - expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease) + expect(updateMock).toBeCalledWith(id, tag, updateBody, commit, draft, updateName, prerelease) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url) }) @@ -238,15 +240,16 @@ describe("Action", () => { return { allowUpdates: allowUpdates, artifacts: inputArtifact, - body: body, + createdReleaseBody: createBody, + createdReleaseName: createName, commit: commit, draft: draft, - name: name, prerelease: prerelease, replacesArtifacts: replacesArtifacts, tag: tag, token: token, - readArtifact: () => artifactData + updatedReleaseBody: updateBody, + updatedReleaseName: updateName } }) const MockUploader = jest.fn(() => { @@ -261,4 +264,4 @@ describe("Action", () => { return new Action(inputs, releases, uploader) } -}) \ No newline at end of file +}) diff --git a/__tests__/ErrorMessage.test.ts b/__tests__/ErrorMessage.test.ts index ec8bb4f..ce0dfc8 100644 --- a/__tests__/ErrorMessage.test.ts +++ b/__tests__/ErrorMessage.test.ts @@ -30,7 +30,6 @@ describe('ErrorMessage', () => { }) it('generates message with errors', () => { - const resource = "release" const error = { message: 'something bad happened', errors: [ @@ -68,4 +67,4 @@ describe('ErrorMessage', () => { const errorMessage = new ErrorMessage(error) expect(errorMessage.status).toBe(404) }) -}) \ No newline at end of file +}) diff --git a/__tests__/Inputs.test.ts b/__tests__/Inputs.test.ts index a7275cf..d364378 100644 --- a/__tests__/Inputs.test.ts +++ b/__tests__/Inputs.test.ts @@ -91,12 +91,12 @@ describe('Inputs', () => { }) }) - describe('body', () => { + describe('createdReleaseBody', () => { it('returns input body', () => { mockGetInput .mockReturnValueOnce('false') .mockReturnValueOnce('body') - expect(inputs.body).toBe('body') + expect(inputs.createdReleaseBody).toBe('body') }) it('returns body file contents', () => { @@ -106,7 +106,7 @@ describe('Inputs', () => { .mockReturnValueOnce('a/path') mockReadFileSync.mockReturnValue('file') - expect(inputs.body).toBe('file') + expect(inputs.createdReleaseBody).toBe('file') }) it('returns empty', () => { @@ -114,14 +114,38 @@ describe('Inputs', () => { .mockReturnValueOnce('false') .mockReturnValueOnce('') .mockReturnValueOnce('') - expect(inputs.body).toBe('') + expect(inputs.createdReleaseBody).toBe('') }) - it('returns null when omitted', () => { + it('returns undefined when omitted', () => { mockGetInput .mockReturnValueOnce('true') .mockReturnValueOnce('body') - expect(inputs.body).toBeUndefined() + expect(inputs.createdReleaseBody).toBeUndefined() + }) + }) + + describe('createdReleaseName', () => { + it('returns input name', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('name') + expect(inputs.createdReleaseName).toBe('name') + }) + + it('returns undefined when omitted', () => { + mockGetInput + .mockReturnValueOnce('true') + .mockReturnValueOnce('name') + expect(inputs.createdReleaseBody).toBeUndefined() + }) + + it('returns tag', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('') + context.ref = 'refs/tags/sha-tag' + expect(inputs.createdReleaseName).toBe('sha-tag') }) }) @@ -136,30 +160,6 @@ describe('Inputs', () => { }) }) - describe('name', () => { - it('returns input name', () => { - mockGetInput - .mockReturnValueOnce('false') - .mockReturnValueOnce('name') - expect(inputs.name).toBe('name') - }) - - it('returns null when omitted', () => { - mockGetInput - .mockReturnValueOnce('true') - .mockReturnValueOnce('name') - expect(inputs.body).toBeUndefined() - }) - - it('returns tag', () => { - mockGetInput - .mockReturnValueOnce('false') - .mockReturnValueOnce('') - context.ref = 'refs/tags/sha-tag' - expect(inputs.name).toBe('sha-tag') - }) - }) - describe('prerelase', () => { it('returns false', () => { expect(inputs.prerelease).toBe(false) @@ -202,6 +202,87 @@ describe('Inputs', () => { }) }) + describe('updatedReleaseBody', () => { + it('returns input body', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('false') + .mockReturnValueOnce('body') + expect(inputs.updatedReleaseBody).toBe('body') + }) + + it('returns body file contents', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('false') + .mockReturnValueOnce('') + .mockReturnValueOnce('a/path') + mockReadFileSync.mockReturnValue('file') + + expect(inputs.updatedReleaseBody).toBe('file') + }) + + it('returns empty', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('false') + .mockReturnValueOnce('') + .mockReturnValueOnce('') + expect(inputs.updatedReleaseBody).toBe('') + }) + + it('returns undefined when omitted', () => { + mockGetInput + .mockReturnValueOnce('true') + .mockReturnValueOnce('false') + .mockReturnValueOnce('body') + expect(inputs.updatedReleaseBody).toBeUndefined() + }) + + it('returns undefined when omitted for update', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('true') + .mockReturnValueOnce('body') + expect(inputs.updatedReleaseBody).toBeUndefined() + }) + }) + + describe('updatedReleaseName', () => { + it('returns input name', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('false') + .mockReturnValueOnce('name') + expect(inputs.updatedReleaseName).toBe('name') + }) + + it('returns undefined when omitted', () => { + mockGetInput + .mockReturnValueOnce('true') + .mockReturnValueOnce('false') + .mockReturnValueOnce('name') + expect(inputs.updatedReleaseName).toBeUndefined() + }) + + it('returns undefined when omitted for update', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('true') + .mockReturnValueOnce('name') + expect(inputs.updatedReleaseName).toBeUndefined() + }) + + it('returns tag', () => { + mockGetInput + .mockReturnValueOnce('false') + .mockReturnValueOnce('false') + .mockReturnValueOnce('') + context.ref = 'refs/tags/sha-tag' + expect(inputs.updatedReleaseName).toBe('sha-tag') + }) + }) + function createGlobber(): ArtifactGlobber { const MockGlobber = jest.fn(() => { return { diff --git a/action.yml b/action.yml index 96b00b6..fb49912 100644 --- a/action.yml +++ b/action.yml @@ -40,11 +40,19 @@ inputs: required: false default: '' omitBody: - description: 'Indicates if the release body should be omitted. This is primarily useful for preserving the release body during updates.' + description: 'Indicates if the release body should be omitted.' + required: false + default: 'false' + omitBodyDuringUpdate: + description: 'Indicates if the release body should be omitted during updates. The body will still be applied for newly created releases. This will preserve the existing body during updates.' required: false default: 'false' omitName: - description: 'Indicates if the release name should be omitted. This is primarily useful for preserving the release name during updates.' + description: 'Indicates if the release name should be omitted.' + required: false + default: 'false' + omitNameDuringUpdate: + description: 'Indicates if the release name should be omitted during updates. The name will still be applied for newly created releases. This will preserve the existing name during updates.' required: false default: 'false' prerelease: diff --git a/lib/Action.js b/lib/Action.js index 50fe4bd..c5acae4 100644 --- a/lib/Action.js +++ b/lib/Action.js @@ -36,7 +36,7 @@ class Action { } } async updateRelease(id) { - const response = await this.releases.update(id, this.inputs.tag, this.inputs.body, this.inputs.commit, this.inputs.draft, this.inputs.name, this.inputs.prerelease); + const response = await this.releases.update(id, this.inputs.tag, this.inputs.updatedReleaseBody, this.inputs.commit, this.inputs.draft, this.inputs.updatedReleaseName, this.inputs.prerelease); return response.data; } noPublishedRelease(error) { @@ -61,7 +61,7 @@ class Action { return (_a = draftRelease) === null || _a === void 0 ? void 0 : _a.id; } async createRelease() { - const response = await this.releases.create(this.inputs.tag, this.inputs.body, this.inputs.commit, this.inputs.draft, this.inputs.name, this.inputs.prerelease); + const response = await this.releases.create(this.inputs.tag, this.inputs.createdReleaseBody, this.inputs.commit, this.inputs.draft, this.inputs.createdReleaseName, this.inputs.prerelease); return response.data; } } diff --git a/lib/Inputs.js b/lib/Inputs.js index a6db0b0..81c44e8 100644 --- a/lib/Inputs.js +++ b/lib/Inputs.js @@ -33,9 +33,15 @@ class CoreInputs { } return []; } - get body() { - if (CoreInputs.omitBody()) + get createdReleaseBody() { + if (CoreInputs.omitBody) return undefined; + return this.body; + } + static get omitBody() { + return core.getInput('omitBody') == 'true'; + } + get body() { const body = core.getInput('body'); if (body) { return body; @@ -46,27 +52,27 @@ class CoreInputs { } return ''; } - static omitBody() { - return core.getInput('omitBody') == 'true'; - } get commit() { return core.getInput('commit'); } - get draft() { - const draft = core.getInput('draft'); - return draft == 'true'; + get createdReleaseName() { + if (CoreInputs.omitName) + return undefined; + return this.name; + } + static get omitName() { + return core.getInput('omitName') == 'true'; } get name() { - if (CoreInputs.omitName()) - return undefined; const name = core.getInput('name'); if (name) { return name; } return this.tag; } - static omitName() { - return core.getInput('omitName') == 'true'; + get draft() { + const draft = core.getInput('draft'); + return draft == 'true'; } get prerelease() { const preRelease = core.getInput('prerelease'); @@ -91,6 +97,22 @@ class CoreInputs { get token() { return core.getInput('token', { required: true }); } + get updatedReleaseBody() { + if (CoreInputs.omitBody || CoreInputs.omitBodyDuringUpdate) + return undefined; + return this.body; + } + static get omitBodyDuringUpdate() { + return core.getInput('omitBodyDuringUpdate') == 'true'; + } + get updatedReleaseName() { + if (CoreInputs.omitName || CoreInputs.omitNameDuringUpdate) + return undefined; + return this.name; + } + static get omitNameDuringUpdate() { + return core.getInput('omitNameDuringUpdate') == 'true'; + } stringFromFile(path) { return fs_1.readFileSync(path, 'utf-8'); } diff --git a/src/Action.ts b/src/Action.ts index 00a1291..e763a99 100644 --- a/src/Action.ts +++ b/src/Action.ts @@ -47,10 +47,10 @@ export class Action { const response = await this.releases.update( id, this.inputs.tag, - this.inputs.body, + this.inputs.updatedReleaseBody, this.inputs.commit, this.inputs.draft, - this.inputs.name, + this.inputs.updatedReleaseName, this.inputs.prerelease ) @@ -83,13 +83,13 @@ export class Action { private async createRelease(): Promise { const response = await this.releases.create( this.inputs.tag, - this.inputs.body, + this.inputs.createdReleaseBody, this.inputs.commit, this.inputs.draft, - this.inputs.name, + this.inputs.createdReleaseName, this.inputs.prerelease ) return response.data } -} \ No newline at end of file +} diff --git a/src/Inputs.ts b/src/Inputs.ts index 7b9cba4..c7ac953 100644 --- a/src/Inputs.ts +++ b/src/Inputs.ts @@ -7,14 +7,16 @@ import {Artifact} from './Artifact'; export interface Inputs { readonly allowUpdates: boolean readonly artifacts: Artifact[] - readonly body?: string readonly commit: string + readonly createdReleaseBody?: string + readonly createdReleaseName?: string readonly draft: boolean - readonly name?: string readonly prerelease: boolean readonly replacesArtifacts: boolean readonly tag: string readonly token: string + readonly updatedReleaseBody?: string + readonly updatedReleaseName?: string } export class CoreInputs implements Inputs { @@ -47,9 +49,16 @@ export class CoreInputs implements Inputs { return [] } - get body(): string | undefined { - if (CoreInputs.omitBody()) return undefined + get createdReleaseBody(): string | undefined { + if (CoreInputs.omitBody) return undefined + return this.body + } + private static get omitBody(): boolean { + return core.getInput('omitBody') == 'true' + } + + private get body() : string | undefined { const body = core.getInput('body') if (body) { return body @@ -63,22 +72,20 @@ export class CoreInputs implements Inputs { return '' } - private static omitBody(): boolean { - return core.getInput('omitBody') == 'true' - } - get commit(): string { return core.getInput('commit') } - get draft(): boolean { - const draft = core.getInput('draft') - return draft == 'true' + get createdReleaseName(): string | undefined { + if (CoreInputs.omitName) return undefined + return this.name } - get name(): string | undefined { - if (CoreInputs.omitName()) return undefined + private static get omitName(): boolean { + return core.getInput('omitName') == 'true' + } + private get name(): string | undefined { const name = core.getInput('name') if (name) { return name @@ -87,8 +94,9 @@ export class CoreInputs implements Inputs { return this.tag } - private static omitName(): boolean { - return core.getInput('omitName') == 'true' + get draft(): boolean { + const draft = core.getInput('draft') + return draft == 'true' } get prerelease(): boolean { @@ -120,6 +128,24 @@ export class CoreInputs implements Inputs { return core.getInput('token', {required: true}) } + get updatedReleaseBody(): string | undefined { + if (CoreInputs.omitBody || CoreInputs.omitBodyDuringUpdate) return undefined + return this.body + } + + private static get omitBodyDuringUpdate(): boolean { + return core.getInput('omitBodyDuringUpdate') == 'true' + } + + get updatedReleaseName(): string | undefined { + if (CoreInputs.omitName || CoreInputs.omitNameDuringUpdate) return undefined + return this.name + } + + private static get omitNameDuringUpdate(): boolean { + return core.getInput('omitNameDuringUpdate') == 'true' + } + stringFromFile(path: string): string { return readFileSync(path, 'utf-8') }