From d5ce851d69309b726c7d41b4bb79edcace15d790 Mon Sep 17 00:00:00 2001 From: Paul Hatcherian <1835615+PaulHatch@users.noreply.github.com> Date: Mon, 9 Dec 2019 22:23:58 -0500 Subject: [PATCH] Support short version tags; fix tests (MAJOR) --- .github/workflows/test.yml | 2 +- dist/index.js | 123 ++++++++++++++++++++++++------------- index.js | 4 +- index.test.js | 18 +++++- 4 files changed, 97 insertions(+), 50 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6e11ee4..b256d82 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: - name: NPM Install run: npm ci - name: Test - run: npm test + run: git config --global user.name "Test User" && git config --global user.email "test@example.com" && npm test - name: Package run: npm run package - name: Run Action diff --git a/dist/index.js b/dist/index.js index b756857..65b5ce4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -640,82 +640,117 @@ const eol = __webpack_require__(87).EOL; const cmd = async (command, ...args) => { let output = ''; - const options = {}; + const options = { + silent: true + }; options.listeners = { - silent: true, stdout: (data) => { output += data.toString(); } }; + await exec.exec(command, args, options) - .catch(err => core.error(err)); + .catch(err => { core.error(`${command} ${args.join(' ')} failed: ${err}`); throw err; }); return output; }; async function run() { try { - const remotePrefix = 'origin/'; + const remote = await cmd('git', 'remote'); + const remoteExists = remote !== ''; + const remotePrefix = remoteExists ? 'origin/' : ''; - const releasePattern = `${remotePrefix}${core.getInput('release_branch', { required: true })}/*`; + const tagPrefix = core.getInput('tag_prefix', { required: true }); + const branch = `${remotePrefix}${core.getInput('branch', { required: true })}`; const majorPattern = core.getInput('major_pattern', { required: true }); const minorPattern = core.getInput('minor_pattern', { required: true }); - const mainBranch = `${remotePrefix}${core.getInput('main_branch', { required: true })}`; - let major = 0, minor = 0, patch = 0; + const releasePattern = `refs/tags/${tagPrefix}*`; + let major = 0, minor = 0, patch = 0, increment = 0; - let branches = await cmd( + let tag = (await cmd( 'git', - `branch`, - `-r`, - `--list`, + `for-each-ref`, `--format='%(refname:short)'`, `--sort=-committerdate`, releasePattern - ); + )).split(eol)[0].trim().replace(/'/g, ""); - var root; - if (branches === '') { - // no release branches yet, use the initial commit as the root - root = await cmd('git', `rev-list`, `--max-parents=0`, mainBranch); + let root; + if (tag === '') { + const isEmpty = (await cmd('git', `status`)).includes('No commits yet'); + if (isEmpty) { + // empty repo + core.info('Version is 0.0.0+0'); + core.setOutput("version", '0.0.0+0'); + core.setOutput("major", '0'); + core.setOutput("minor", '0'); + core.setOutput("patch", '0'); + core.setOutput("increment", '0'); + return; + } else { + // no release tags yet, use the initial commit as the root + root = ''; + } } else { - // find the merge base between the last - var releaseBranch = branches.split(eol)[0]; - var versionValues = releaseBranch.split('/')[1].split('.'); - major = parseInt(versionValues[0]); - minor = parseInt(versionValues[1]); - patch = parseInt(versionValues[2]); + // parse the version tag + let tagParts = tag.split('/'); + let versionValues = tagParts[tagParts.length - 1] + .substr(tagPrefix.length) + .split('.'); - root = await cmd('git', `merge-base`, releaseBranch, mainBranch); + major = parseInt(versionValues[0]); + minor = versionValues.length > 1 ? parseInt(versionValues[1]) : 0; + patch = versionValues.length > 2 ? parseInt(versionValues[2]) : 0; + + if (isNaN(major) || isNaN(minor) || isNaN(patch)) { + throw `Invalid tag ${tag}`; + } + + root = await cmd('git', `merge-base`, tag, branch); } root = root.trim(); - let history = (await cmd('git', 'log', '--pretty="%s"', root, mainBranch)).split(eol); + const log = await cmd( + 'git', + 'log', + '--pretty="%s"', + '--author-date-order', + root === '' ? branch : `${root}..${branch}`); - patch++; - var increment = history.length; - for (var i = 0; i < history.length; i++) { - if (history[i].indexOf(majorPattern) !== -1) { - major++; - minor = 0; - patch = 0; - increment = i + 1; - break; - } else if (history[i].indexOf(minorPattern) !== -1) { - minor++; - patch = 0; - increment = i + 1; - break; - } + let history = log + .trim() + .split(eol) + .reverse(); + + // Discover the change time from the history log by finding the oldest log + // that could set the version. + + const majorIndex = history.findIndex(x => x.includes(majorPattern)); + const minorIndex = history.findIndex(x => x.includes(minorPattern)); + + if (majorIndex !== -1) { + increment = history.length - (majorIndex + 1); + patch = 0; + minor = 0; + major++; + } else if (minorIndex !== -1) { + increment = history.length - (minorIndex + 1); + patch = 0; + minor++; + } else { + increment = history.length - 1; + patch++; } let version = `${major}.${minor}.${patch}`; core.info(`Version is ${version}+${increment}`); core.setOutput("version", version); - core.setOutput("major", major); - core.setOutput("minor", minor); - core.setOutput("patch", patch); - core.setOutput("increment", increment); + core.setOutput("major", major.toString()); + core.setOutput("minor", minor.toString()); + core.setOutput("patch", patch.toString()); + core.setOutput("increment", increment.toString()); } catch (error) { - console.log(error); + core.error(error); core.setFailed(error.message); } } diff --git a/index.js b/index.js index f85a9c6..3dfe4cc 100644 --- a/index.js +++ b/index.js @@ -62,8 +62,8 @@ async function run() { .split('.'); major = parseInt(versionValues[0]); - minor = parseInt(versionValues[1]); - patch = parseInt(versionValues[2]); + minor = versionValues.length > 1 ? parseInt(versionValues[1]) : 0; + patch = versionValues.length > 2 ? parseInt(versionValues[2]) : 0; if (isNaN(major) || isNaN(minor) || isNaN(patch)) { throw `Invalid tag ${tag}`; diff --git a/index.test.js b/index.test.js index 2b48a00..d906b47 100644 --- a/index.test.js +++ b/index.test.js @@ -50,7 +50,7 @@ test('Empty repository version is correct', () => { expect(result).toMatch('Version is 0.0.0+0'); repo.clean(); -}) +}); test('Repository with commits shows increment', () => { const repo = createTestRepo(); // 0.0.0+0 @@ -62,7 +62,7 @@ test('Repository with commits shows increment', () => { expect(result).toMatch('Version is 0.0.1+1'); repo.clean(); -}) +}); test('Minor update bumps minor version and resets increment', () => { const repo = createTestRepo(); // 0.0.0+0 @@ -103,7 +103,6 @@ test('Multiple major commits are idempotent', () => { repo.clean(); }); - test('Minor commits after a major commit are ignored', () => { const repo = createTestRepo(); // 0.0.0+0 @@ -230,3 +229,16 @@ test('Merged tags do not affect version', () => { repo.clean(); }); + +test('Version tags do not require all three version numbers', () => { + const repo = createTestRepo(); // 0.0.0+0 + + repo.makeCommit('Initial Commit (MAJOR)'); // 1.0.0+0 + repo.exec('git tag v1'); + repo.makeCommit(`Second Commit`); // 1.0.1+0 + const result = repo.runAction(); + + expect(result).toMatch('Version is 1.0.1+0'); + + repo.clean(); +})