From fd84fac60083514723caea1419bde746f94d5d3f Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Tue, 27 Nov 2018 20:01:15 +0000 Subject: [PATCH] feat: add fallback to environment variables 43 (#57) * feat: add fallback to environment variables, close #43 * chore: merging git and env fields * chore: bring mocked-env for better testing * use Ramda mergeWith * feat: combine git and env variables, tested * chore: better readme text --- README.md | 17 +++- __snapshots__/commit-info-spec.js | 31 ++++++-- package-lock.json | 90 ++++++++++++++-------- package.json | 5 +- src/commit-info-spec.js | 124 +++++++++++++++++++++--------- src/git-api.js | 3 +- src/index.js | 9 ++- src/utils-spec.js | 30 ++++++++ src/utils.js | 32 +++++++- 9 files changed, 260 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 0f789d0..1f5d0be 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,25 @@ commitInfo(folder) Notes: -- Code assumes there is `.git` folder and uses Git commands to get each property, like `git show -s --pretty=%B`, see [src/git-api.js](src/git-api.js) +- Code assumes there is `.git` folder and uses Git commands to get each property, like `git show -s --pretty=%B`, see [src/git-api.js](src/git-api.js). Note: there is fallback to environment variables. - Resolves with [Bluebird](https://github.com/petkaantonov/bluebird) promise. - Only uses Git commands, see [src/git-api.js](src/git-api.js) -- If a command fails, returns null for each property +- If a command fails, returns `null` for each property - If you need to debug, run with `DEBUG=commit-info` environment variable. +## Fallback environment variables + +If getting the commit information using `git` fails for some reason, you can provide the commit information by setting the environment variables. This module will look at the following environment variables as a fallback + +``` +branch: COMMIT_INFO_BRANCH +message: COMMIT_INFO_MESSAGE +email: COMMIT_INFO_EMAIL +author: COMMIT_INFO_AUTHOR +sha: COMMIT_INFO_SHA +remote: COMMIT_INFO_REMOTE +``` + ## Individual methods In addition to `commitInfo` this module also exposes individual promise-returning diff --git a/__snapshots__/commit-info-spec.js b/__snapshots__/commit-info-spec.js index 3bb299d..de592d1 100644 --- a/__snapshots__/commit-info-spec.js +++ b/__snapshots__/commit-info-spec.js @@ -1,13 +1,25 @@ -exports['commit-info returns information 1'] = { +exports['commit-info combination with environment variables has certain api 1'] = [ + "commitInfo", + "getBranch", + "getMessage", + "getEmail", + "getAuthor", + "getSha", + "getRemoteOrigin", + "getSubject", + "getBody" +] + +exports['commit-info combination with environment variables returns information 1'] = { "branch": "test-branch", - "message": "important commit", - "email": "me@foo.com", + "message": "some git message", + "email": "user@company.com", "author": "John Doe", "sha": "abc123", "remote": "git@github.com/repo" } -exports['commit-info has certain api 1'] = [ +exports['commit-info no environment variables has certain api 1'] = [ "commitInfo", "getBranch", "getMessage", @@ -19,7 +31,16 @@ exports['commit-info has certain api 1'] = [ "getBody" ] -exports['commit-info returns empty strings for missing info 1'] = { +exports['commit-info no environment variables returns information 1'] = { + "branch": "test-branch", + "message": "important commit", + "email": "me@foo.com", + "author": "John Doe", + "sha": "abc123", + "remote": "git@github.com/repo" +} + +exports['commit-info no environment variables returns nulls for missing fields 1'] = { "branch": "test-branch", "message": null, "email": "me@foo.com", diff --git a/package-lock.json b/package-lock.json index 7d3fbbe..5a42d4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1739,7 +1739,7 @@ }, "conventional-changelog-angular": { "version": "1.6.6", - "resolved": "http://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz", "integrity": "sha512-suQnFSqCxRwyBxY68pYTsFkG0taIdinHLNEAX5ivtw8bCRnIgnpvcHmlR/yjUyZIrNPYAoXlY1WiEKWgSE4BNg==", "dev": true, "requires": { @@ -2115,7 +2115,7 @@ }, "conventional-commits-filter": { "version": "1.1.6", - "resolved": "http://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-1.1.6.tgz", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-1.1.6.tgz", "integrity": "sha512-KcDgtCRKJCQhyk6VLT7zR+ZOyCnerfemE/CsR3iQpzRRFbLEs0Y6rwk3mpDvtOh04X223z+1xyJ582Stfct/0Q==", "dev": true, "requires": { @@ -2125,7 +2125,7 @@ }, "conventional-commits-parser": { "version": "2.1.7", - "resolved": "http://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-2.1.7.tgz", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-2.1.7.tgz", "integrity": "sha512-BoMaddIEJ6B4QVMSDu9IkVImlGOSGA1I2BQyOZHeLQ6qVOJLcLKn97+fL6dGbzWEiqDzfH4OkcveULmeq2MHFQ==", "dev": true, "requires": { @@ -2733,7 +2733,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -3288,7 +3288,7 @@ }, "dotenv": { "version": "4.0.0", - "resolved": "http://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", "dev": true }, @@ -3414,7 +3414,7 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -3485,7 +3485,7 @@ }, "eslint": { "version": "4.19.1", - "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { @@ -3531,7 +3531,7 @@ "dependencies": { "ansi-escapes": { "version": "3.1.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, @@ -4088,7 +4088,7 @@ }, "external-editor": { "version": "2.2.0", - "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { @@ -4288,13 +4288,13 @@ "dependencies": { "colors": { "version": "0.6.2", - "resolved": "http://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", "dev": true }, "commander": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=", "dev": true } @@ -4817,7 +4817,7 @@ }, "git-raw-commits": { "version": "1.3.6", - "resolved": "http://registry.npmjs.org/git-raw-commits/-/git-raw-commits-1.3.6.tgz", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-1.3.6.tgz", "integrity": "sha512-svsK26tQ8vEKnMshTDatSIQSMDdz8CxIIqKsvPqbtV23Etmw6VNaFAitu8zwZ0VrOne7FztwPyRLxK7/DIUTQg==", "dev": true, "requires": { @@ -4851,7 +4851,7 @@ }, "git-semver-tags": { "version": "1.3.6", - "resolved": "http://registry.npmjs.org/git-semver-tags/-/git-semver-tags-1.3.6.tgz", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-1.3.6.tgz", "integrity": "sha512-2jHlJnln4D/ECk9FxGEBh3k44wgYdWjWDtMmJPaecjoRmxKo3Y1Lh8GMYuOPu04CHw86NTAODchYjC5pnpMQig==", "dev": true, "requires": { @@ -5611,7 +5611,7 @@ }, "into-stream": { "version": "3.1.0", - "resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "dev": true, "requires": { @@ -5659,7 +5659,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -6658,7 +6658,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -6738,7 +6738,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -6976,6 +6976,35 @@ } } }, + "mocked-env": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/mocked-env/-/mocked-env-1.2.3.tgz", + "integrity": "sha512-dVTkv8YyLIXwzSN2mXNWf6s0pNbKtLAISja2dNRXPsm6Luy8aOpAfS7ezVNeFo7xBTDrbwrkaNfPwTAYAJzz1g==", + "dev": true, + "requires": { + "check-more-types": "2.24.0", + "debug": "3.2.6", + "lazy-ass": "1.6.0", + "ramda": "0.26.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, "modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", @@ -7553,7 +7582,7 @@ }, "semver": { "version": "4.3.6", - "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true } @@ -7803,7 +7832,7 @@ }, "p-cancelable": { "version": "0.4.1", - "resolved": "http://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true }, @@ -7814,7 +7843,7 @@ }, "p-is-promise": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", "dev": true }, @@ -8387,7 +8416,7 @@ "dependencies": { "ansi-escapes": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, @@ -8405,7 +8434,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -8437,7 +8466,7 @@ }, "inquirer": { "version": "0.12.0", - "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", "dev": true, "requires": { @@ -8509,7 +8538,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -8789,7 +8818,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { @@ -8813,8 +8842,7 @@ "ramda": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.0.tgz", - "integrity": "sha512-maK1XqpgsOo5DwjhROjqDvpm1vkphLQbpleVv+b3t5Y9uOQ0t8hTHT582+mDs7RLrex1kd4lWYizNXWLVjsq9w==", - "dev": true + "integrity": "sha512-maK1XqpgsOo5DwjhROjqDvpm1vkphLQbpleVv+b3t5Y9uOQ0t8hTHT582+mDs7RLrex1kd4lWYizNXWLVjsq9w==" }, "rc": { "version": "1.2.8", @@ -8966,7 +8994,7 @@ }, "regexpp": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "dev": true }, @@ -10083,13 +10111,13 @@ "dependencies": { "spdx-exceptions": { "version": "1.0.5", - "resolved": "http://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.5.tgz", "integrity": "sha1-nSGsTaS9tx0GD7dOWmdTHQMsu6Y=", "dev": true }, "spdx-license-ids": { "version": "1.2.2", - "resolved": "http://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true } @@ -11336,7 +11364,7 @@ }, "vue-eslint-parser": { "version": "2.0.3", - "resolved": "http://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", "integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 31b0a99..cfc15b8 100644 --- a/package.json +++ b/package.json @@ -81,10 +81,10 @@ "github-post-release": "1.13.1", "license-checker": "20.2.0", "mocha": "5.2.0", + "mocked-env": "1.2.3", "nsp": "2.8.1", "pre-git": "3.17.1", "prettier-standard": "8.0.1", - "ramda": "0.26.0", "semantic-release": "8.2.3", "simple-commit-message": "3.3.2", "snap-shot-it": "6.2.5", @@ -96,6 +96,7 @@ "check-more-types": "2.24.0", "debug": "4.1.0", "execa": "1.0.0", - "lazy-ass": "1.6.0" + "lazy-ass": "1.6.0", + "ramda": "0.26.0" } } diff --git a/src/commit-info-spec.js b/src/commit-info-spec.js index 7d77fc4..77c3755 100644 --- a/src/commit-info-spec.js +++ b/src/commit-info-spec.js @@ -7,6 +7,7 @@ const snapshot = require('snap-shot-it') const { gitCommands } = require('./git-api') const la = require('lazy-ass') const is = require('check-more-types') +const mockedEnv = require('mocked-env') describe('getBranch', () => { const { getBranch } = require('.') @@ -50,48 +51,99 @@ describe('getBranch', () => { }) describe('commit-info', () => { - const env = process.env + describe('no environment variables', () => { + let restoreEnvironment - beforeEach(() => { - process.env = {} - }) + beforeEach(() => { + restoreEnvironment = mockedEnv({}, { clear: true }) + }) - afterEach(() => { - process.env = env - }) + afterEach(() => { + restoreEnvironment() + }) - it('has certain api', () => { - const api = require('.') - snapshot(Object.keys(api)) - }) + it('has certain api', () => { + const api = require('.') + snapshot(Object.keys(api)) + }) - it('returns information', () => { - stubSpawnShellOnce(gitCommands.branch, 0, 'test-branch', '') - stubSpawnShellOnce(gitCommands.message, 0, 'important commit', '') - stubSpawnShellOnce(gitCommands.email, 0, 'me@foo.com', '') - stubSpawnShellOnce(gitCommands.author, 0, 'John Doe', '') - stubSpawnShellOnce(gitCommands.sha, 0, 'abc123', '') - stubSpawnShellOnce( - gitCommands.remoteOriginUrl, - 0, - 'git@github.com/repo', - '' - ) - return commitInfo().then(snapshot) - }) + it('returns information', () => { + stubSpawnShellOnce(gitCommands.branch, 0, 'test-branch', '') + stubSpawnShellOnce(gitCommands.message, 0, 'important commit', '') + stubSpawnShellOnce(gitCommands.email, 0, 'me@foo.com', '') + stubSpawnShellOnce(gitCommands.author, 0, 'John Doe', '') + stubSpawnShellOnce(gitCommands.sha, 0, 'abc123', '') + stubSpawnShellOnce( + gitCommands.remoteOriginUrl, + 0, + 'git@github.com/repo', + '' + ) + return commitInfo().then(snapshot) + }) - it('returns empty strings for missing info', () => { - stubSpawnShellOnce(gitCommands.branch, 0, 'test-branch', '') - stubSpawnShellOnce(gitCommands.message, 1, '', 'no message') - stubSpawnShellOnce(gitCommands.email, 0, 'me@foo.com', '') - stubSpawnShellOnce(gitCommands.author, 1, '', 'missing author') - stubSpawnShellOnce(gitCommands.sha, 0, 'abc123', '') - stubSpawnShellOnce(gitCommands.remoteOriginUrl, 1, '', 'no remote origin') - return commitInfo().then(snapshot) + it('returns nulls for missing fields', () => { + stubSpawnShellOnce(gitCommands.branch, 0, 'test-branch', '') + stubSpawnShellOnce(gitCommands.message, 1, '', 'no message') + stubSpawnShellOnce(gitCommands.email, 0, 'me@foo.com', '') + stubSpawnShellOnce(gitCommands.author, 1, '', 'missing author') + stubSpawnShellOnce(gitCommands.sha, 0, 'abc123', '') + stubSpawnShellOnce(gitCommands.remoteOriginUrl, 1, '', 'no remote origin') + return commitInfo() + .tap(info => { + la(info.message === null, 'message should be null', info) + la(info.author === null, 'author should be null', info) + la(info.remote === null, 'remoteOriginUrl should be null', info) + }) + .then(snapshot) + }) + + it('has getRemoteOrigin method', () => { + const { getRemoteOrigin } = require('.') + la(is.fn(getRemoteOrigin)) + }) }) - it('has getRemoteOrigin method', () => { - const { getRemoteOrigin } = require('.') - la(is.fn(getRemoteOrigin)) + describe('combination with environment variables', () => { + let restoreEnvironment + + beforeEach(() => { + restoreEnvironment = mockedEnv( + { + COMMIT_INFO_MESSAGE: 'some git message', + COMMIT_INFO_EMAIL: 'user@company.com' + }, + { clear: true } + ) + }) + + afterEach(() => { + restoreEnvironment() + }) + + it('has certain api', () => { + const api = require('.') + snapshot(Object.keys(api)) + }) + + it('returns information', () => { + stubSpawnShellOnce(gitCommands.branch, 0, 'test-branch', '') + stubSpawnShellOnce( + gitCommands.message, + 1, + '', + 'could not get Git message' + ) + stubSpawnShellOnce(gitCommands.email, 1, '', 'could not get Git email') + stubSpawnShellOnce(gitCommands.author, 0, 'John Doe', '') + stubSpawnShellOnce(gitCommands.sha, 0, 'abc123', '') + stubSpawnShellOnce( + gitCommands.remoteOriginUrl, + 0, + 'git@github.com/repo', + '' + ) + return commitInfo().then(snapshot) + }) }) }) diff --git a/src/git-api.js b/src/git-api.js index 4e04f7a..850026e 100644 --- a/src/git-api.js +++ b/src/git-api.js @@ -36,8 +36,7 @@ const runGitCommand = (gitCommand, pathToRepo) => { debug('running git command: %s', gitCommand) debug('in folder %s', pathToRepo) - return Promise.resolve() - .then(() => execa.shell(gitCommand, { cwd: pathToRepo })) + return Promise.try(() => execa.shell(gitCommand, { cwd: pathToRepo })) .then(prop('stdout')) .tap(stdout => debug('git stdout:', stdout)) .then(returnNullIfEmpty) diff --git a/src/index.js b/src/index.js index c11769f..a287f27 100644 --- a/src/index.js +++ b/src/index.js @@ -10,9 +10,9 @@ const { getSha, getRemoteOrigin } = require('./git-api') -const { getBranch } = require('./utils') - +const { getBranch, getCommitInfoFromEnvironment } = require('./utils') const Promise = require('bluebird') +const { mergeWith, or } = require('ramda') function commitInfo (folder) { folder = folder || process.cwd() @@ -25,6 +25,11 @@ function commitInfo (folder) { author: getAuthor(folder), sha: getSha(folder), remote: getRemoteOrigin(folder) + }).then(info => { + const envVariables = getCommitInfoFromEnvironment() + debug('git commit: %o', info) + debug('env commit: %o', envVariables) + return mergeWith(or, envVariables, info) }) } diff --git a/src/utils-spec.js b/src/utils-spec.js index e25a273..6daff6b 100644 --- a/src/utils-spec.js +++ b/src/utils-spec.js @@ -1,9 +1,39 @@ 'use strict' const la = require('lazy-ass') +const is = require('check-more-types') +const { mergeWith, or } = require('ramda') /* eslint-env mocha */ describe('utils', () => { + describe('getFields', () => { + const { getFields } = require('./utils') + + it('returns list of fields', () => { + const fields = getFields() + la(is.strings(fields), fields) + }) + }) + + describe('Object.assign', () => { + it('replaces empty strings with non-empty', () => { + const o = Object.assign({}, { foo: '' }, { foo: 'foo' }) + la(o.foo === 'foo', o) + }) + + it('overwrites first string', () => { + const o = Object.assign({}, { foo: 'foo' }, { foo: '' }) + la(o.foo === '', o) + }) + }) + + describe('R.mergeWith', () => { + it('keeps non-empty string', () => { + const o = mergeWith(or, { foo: 'foo' }, { foo: '' }) + la(o.foo === 'foo', o) + }) + }) + describe('firstFoundValue', () => { const { firstFoundValue } = require('./utils') diff --git a/src/utils.js b/src/utils.js index dc0a17f..6e7ff6d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -8,6 +8,13 @@ function firstFoundValue (keys, object = process.env) { return found ? object[found] : null } +const getValue = name => o => { + if (name in o) { + return o[name] + } + return null +} + /** * Uses "git" command to find the current branch * @@ -20,7 +27,30 @@ function getBranch (pathToRepo) { return getGitBranch(pathToRepo) } +/** + * Looks up commit information from environment keys. + */ +function getCommitInfoFromEnvironment (env = process.env) { + return { + branch: getValue('COMMIT_INFO_BRANCH')(env), + message: getValue('COMMIT_INFO_MESSAGE')(env), + email: getValue('COMMIT_INFO_EMAIL')(env), + author: getValue('COMMIT_INFO_AUTHOR')(env), + sha: getValue('COMMIT_INFO_SHA')(env), + remote: getValue('COMMIT_INFO_REMOTE')(env) + } +} + +/** + * Returns list of Git properties that this module searches for + */ +function getFields () { + return ['branch', 'message', 'email', 'author', 'sha', 'remote'] +} + module.exports = { firstFoundValue, - getBranch + getBranch, + getCommitInfoFromEnvironment, + getFields }