diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f52760ca2..2243f24ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: npm ci - run: npm run test - run: npm run check diff --git a/src/action.ts b/src/action.ts index 2a073169e..a1339e1bf 100644 --- a/src/action.ts +++ b/src/action.ts @@ -5,12 +5,14 @@ import { generateNotes } from '@semantic-release/release-notes-generator'; import { getBranchFromRef, isPr, + isPrereleaseBranch, getCommits, getLatestPrereleaseTag, getLatestTag, getValidTags, mapCustomReleaseRules, mergeWithDefaultChangelogRules, + getIdentifier, } from './utils'; import { createTag } from './github'; import { Await } from './ts'; @@ -38,13 +40,18 @@ export default async function main() { mappedReleaseRules = mapCustomReleaseRules(customReleaseRules); } - const { GITHUB_REF, GITHUB_SHA } = process.env; + const { GITHUB_REF, GITHUB_SHA, GITHUB_EVENT_NAME } = process.env; if (!GITHUB_REF) { core.setFailed('Missing GITHUB_REF.'); return; } + if (!GITHUB_EVENT_NAME) { + core.setFailed('Missing GITHUB_EVENT_NAME'); + return; + } + const commitRef = commitSha || GITHUB_SHA; if (!commitRef) { core.setFailed('Missing commit_sha or GITHUB_SHA.'); @@ -55,17 +62,22 @@ export default async function main() { const isReleaseBranch = releaseBranches .split(',') .some((branch) => currentBranch.match(branch)); - const isPreReleaseBranch = preReleaseBranches - .split(',') - .some((branch) => currentBranch.match(branch)); - const isPullRequest = isPr(GITHUB_REF); + const isPreReleaseBranch = isPrereleaseBranch( + preReleaseBranches, + currentBranch + ); + const isPullRequest = isPr(GITHUB_EVENT_NAME); const isPrerelease = !isReleaseBranch && !isPullRequest && isPreReleaseBranch; // Sanitize identifier according to // https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions - const identifier = ( - appendToPreReleaseTag ? appendToPreReleaseTag : currentBranch - ).replace(/[^a-zA-Z0-9-]/g, '-'); + const identifier = getIdentifier( + appendToPreReleaseTag, + currentBranch, + isPullRequest, + isPrerelease, + commitRef + ); const prefixRegex = new RegExp(`^${tagPrefix}`); @@ -181,7 +193,11 @@ export default async function main() { return; } - newVersion = incrementedVersion; + if (isPullRequest) { + newVersion = `${incrementedVersion}-${identifier}`; + } else { + newVersion = incrementedVersion; + } } core.info(`New version is ${newVersion}.`); diff --git a/src/utils.ts b/src/utils.ts index 05b1247f3..614009bff 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -49,8 +49,20 @@ export function getBranchFromRef(ref: string) { return ref.replace('refs/heads/', ''); } -export function isPr(ref: string) { - return ref.includes('refs/pull/'); +export function isPr(eventName: string) { + return eventName.includes('pull_request'); +} + +export function isPrereleaseBranch( + preReleaseBranches: string, + currentBranch: string +) { + if (preReleaseBranches) { + return preReleaseBranches + .split(',') + .some((branch) => currentBranch.match(branch)); + } + return false; } export function getLatestTag( @@ -139,3 +151,23 @@ export function mergeWithDefaultChangelogRules( return Object.values(mergedRules).filter((rule) => !!rule.section); } + +export function getIdentifier( + appendToPreReleaseTag: string, + currentBranch: string, + isPullRequest: boolean, + isPrerelease: boolean, + commitRef: string +): string { + // On prerelease: Sanitize identifier according to + // https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions + let identifier: string; + if (isPullRequest) { + // On pull request, use commit SHA for identifier + return commitRef.slice(0, 7).replace(/[^a-zA-Z0-9-]/g, '-'); + } + identifier = ( + appendToPreReleaseTag ? appendToPreReleaseTag : currentBranch + ).replace(/[^a-zA-Z0-9-]/g, '-'); + return identifier; +} diff --git a/tests/action.test.ts b/tests/action.test.ts index 413e7bfae..9e505a527 100644 --- a/tests/action.test.ts +++ b/tests/action.test.ts @@ -8,6 +8,7 @@ import { setCommitSha, setInput, setRepository, + setEventName, } from './helper.test'; jest.spyOn(core, 'debug').mockImplementation(() => {}); @@ -27,12 +28,14 @@ const mockSetOutput = jest .mockImplementation(() => {}); const mockSetFailed = jest.spyOn(core, 'setFailed'); +const commitSha = '79e0ea271c26aa152beef77c3275ff7b8f8d8274'; describe('github-tag-action', () => { beforeEach(() => { jest.clearAllMocks(); setBranch('master'); - setCommitSha('79e0ea271c26aa152beef77c3275ff7b8f8d8274'); + setCommitSha(commitSha); + setEventName('push'); loadDefaultInputs(); }); @@ -222,6 +225,7 @@ describe('github-tag-action', () => { jest.clearAllMocks(); setBranch('release'); setInput('release_branches', 'release'); + setEventName('push'); }); it('does create patch tag', async () => { @@ -484,6 +488,7 @@ describe('github-tag-action', () => { /* * Then */ + expect(mockCreateTag).not.toBeCalled(); expect(mockSetFailed).not.toBeCalled(); }); @@ -873,4 +878,50 @@ describe('github-tag-action', () => { expect(mockSetFailed).not.toBeCalled(); }); }); + + describe('pull requests', () => { + beforeEach(() => { + jest.clearAllMocks(); + setBranch('branch-with-my-first-fix'); + setEventName('pull_request'); + }); + + it('does create new version with commit sha suffix on pull request', async () => { + /* + * Given + */ + const commits = [{ message: 'fix: this is my first fix', hash: null }]; + jest + .spyOn(utils, 'getCommits') + .mockImplementation(async (sha) => commits); + + const validTags = [ + { + name: 'v1.2.3', + commit: { sha: '012345', url: '' }, + zipball_url: '', + tarball_url: 'string', + node_id: 'string', + }, + ]; + jest + .spyOn(utils, 'getValidTags') + .mockImplementation(async () => validTags); + + /* + * When + */ + await action(); + + /* + * Then + */ + expect(mockSetOutput).toHaveBeenCalledWith( + 'new_version', + `1.2.4-${commitSha.slice(0, 7)}` + ); + expect(mockCreateTag).not.toHaveBeenCalledWith(); + expect(mockSetFailed).not.toBeCalled(); + }); + }); }); diff --git a/tests/helper.test.ts b/tests/helper.test.ts index d56b50be5..99cf5feb1 100644 --- a/tests/helper.test.ts +++ b/tests/helper.test.ts @@ -18,6 +18,10 @@ export function setCommitSha(sha: string) { process.env['GITHUB_SHA'] = sha; } +export function setEventName(eventName: string) { + process.env['GITHUB_EVENT_NAME'] = eventName; +} + export function setInput(key: string, value: string) { process.env[`INPUT_${key.toUpperCase()}`] = value; } diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 417d8791e..eb04d9385 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -27,16 +27,16 @@ describe('utils', () => { expect(branch).toEqual('master'); }); - it('test if ref is PR', () => { + it('test if triggering event is PR', () => { /* * Given */ - const remoteRef = 'refs/pull/123/merge'; + const eventName = 'pull_request'; /* * When */ - const isPullRequest = utils.isPr(remoteRef); + const isPullRequest = utils.isPr(eventName); /* * Then