diff --git a/README.md b/README.md index 68b35a6..41b436f 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![Coverage Status](https://coveralls.io/repos/github/jacob-meacham/serverless-plugin-git-variables/badge.svg?branch=develop)](https://coveralls.io/github/jacob-meacham/serverless-plugin-git-variables?branch=develop) [![Build Status](https://travis-ci.org/jacob-meacham/serverless-plugin-git-variables.svg?branch=develop)](https://travis-ci.org/jacob-meacham/serverless-plugin-git-variables) -Expose git variables (HEAD description, branch name, short commit hash, message, and if the local repo has changed files) to your serverless services. -Moreover, it adds GIT related environment variables and tags (GIT_COMMIT_SHORT, GIT_COMMIT_LONG, GIT_BRANCH, GIT_IS_DIRTY, GIT_REPOSITORY) for each defined function in the serverless file. You can disable this by adding the following custom variable in your serverless.yml file: +Expose git variables (HEAD description, branch name, short commit hash, message, git tags, and if the local repo has changed files) to your serverless services. +Moreover, it adds GIT related environment variables and tags (GIT_COMMIT_SHORT, GIT_COMMIT_LONG, GIT_BRANCH, GIT_IS_DIRTY, GIT_REPOSITORY, GIT_TAGS) for each defined function in the serverless file. You can disable this by adding the following custom variable in your serverless.yml file: ``` custom: @@ -13,14 +13,17 @@ custom: # Usage ```yaml +custom: + gitDescription: ${git:repository} - ${git:branch} - ${git:tags} + functions: processEventBatch: name: ${self:provider.stage}-${self:service}-process-event-batch - description: ${git:repository} - ${git:branch} - ${git:describe} - ${git:sha1} + description: ${self:custom.gitDescription} processEventBatch2: name: ${self:provider.stage}-${self:service}-process-event-batch-2 - description: ${git:repository} - ${git:describeLight} - ${git:branch} + description: ${self:custom.gitDescription} plugins: - serverless-plugin-git-variables @@ -48,12 +51,19 @@ Annotated tags are shown by both `describe` and `describeLight`, only `describeL For more information on annotated and lightweight tags go to the [git documentation on tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging). +## tags + +The tags (`${git:tags}`) is used to get info about which git tags (separated by comma) are pointing to current commit and if none it will show commit ID as fallback. + # Serverless Version Support * If you're using serverless 1.12.x or below, use the 1.x.x version of this plugin. * This plugin is currently broken for serverless versions between 1.13 and 1.15 (inclusive). * If you're using serverless 1.16.x or above, use the >=2.x.x version of this plugin. # Version History +* 3.4.0 + - Add user name / email (Thanks to @JordanReiter) + - Add git tag information (Thanks to @navrkald) * 3.3.3 - Update dependencies thanks to dependabot * 3.3.2 diff --git a/lib/index.js b/lib/index.js index c878efa..2aefe0a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -38,11 +38,13 @@ var _path = require('path'); var _path2 = _interopRequireDefault(_path); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var _os = require('os'); + +var _os2 = _interopRequireDefault(_os); -// TODO: Consider using nodegit instead -const GIT_PREFIX = 'git'; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +const GIT_PREFIX = 'git'; // TODO: Consider using nodegit instead class ServerlessGitVariables { constructor(serverless, options) { this.serverless = serverless; @@ -100,6 +102,12 @@ class ServerlessGitVariables { case 'message': value = yield _exec('git log -1 --pretty=%B'); break; + case 'user': + value = yield _exec('git config user.name'); + break; + case 'email': + value = yield _exec('git config user.email'); + break; case 'isDirty': const writeTree = yield _exec('git write-tree'); const changes = yield _exec(`git diff-index ${writeTree} --`); @@ -109,6 +117,13 @@ class ServerlessGitVariables { const pathName = yield _exec('git rev-parse --show-toplevel'); value = _path2.default.basename(pathName); break; + case 'tags': + value = yield _exec('git tag --points-at HEAD'); + value = value.split(_os2.default.EOL).join(','); + if (value === '') { + value = yield _exec('git rev-parse --short HEAD'); + } + break; default: throw new Error(`Git variable ${variable} is unknown. Candidates are 'describe', 'describeLight', 'sha1', 'commit', 'branch', 'message', 'repository'`); } @@ -138,6 +153,7 @@ class ServerlessGitVariables { const branch = yield _this3._getValue('branch'); const isDirty = yield _this3._getValue('isDirty'); const repository = yield _this3._getValue('repository'); + const gitTagsOrCommit = yield _this3._getValue('tags'); for (const functionName of _this3.serverless.service.getAllFunctions()) { const func = _this3.serverless.service.getFunction(functionName); @@ -147,6 +163,7 @@ class ServerlessGitVariables { _this3.exportGitVariable(func, 'GIT_BRANCH', branch); _this3.exportGitVariable(func, 'GIT_IS_DIRTY', isDirty); _this3.exportGitVariable(func, 'GIT_REPOSITORY', repository); + _this3.exportGitVariable(func, 'GIT_TAGS', gitTagsOrCommit); } })(); } diff --git a/package.json b/package.json index 54cac52..0c26862 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-plugin-git-variables", - "version": "3.3.3", + "version": "3.4.0", "engines": { "node": ">=7.0" }, diff --git a/src/index.js b/src/index.js index 67d2539..a555de7 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ // TODO: Consider using nodegit instead import childProcess from 'child_process' import path from 'path' +import os from 'os' const GIT_PREFIX = 'git' @@ -66,6 +67,12 @@ export default class ServerlessGitVariables { case 'message': value = await _exec('git log -1 --pretty=%B') break + case 'user': + value = await _exec('git config user.name') + break + case 'email': + value = await _exec('git config user.email') + break case 'isDirty': const writeTree = await _exec('git write-tree') const changes = await _exec(`git diff-index ${writeTree} --`) @@ -75,6 +82,13 @@ export default class ServerlessGitVariables { const pathName = await _exec('git rev-parse --show-toplevel') value = path.basename(pathName) break + case 'tags': + value = await _exec('git tag --points-at HEAD') + value = value.split(os.EOL).join(',') + if (value === '') { + value = await _exec('git rev-parse --short HEAD') + } + break default: throw new Error(`Git variable ${variable} is unknown. Candidates are 'describe', 'describeLight', 'sha1', 'commit', 'branch', 'message', 'repository'`) } @@ -100,6 +114,7 @@ export default class ServerlessGitVariables { const branch = await this._getValue('branch') const isDirty = await this._getValue('isDirty') const repository = await this._getValue('repository') + const gitTagsOrCommit = await this._getValue('tags') for (const functionName of this.serverless.service.getAllFunctions()) { const func = this.serverless.service.getFunction(functionName) @@ -109,6 +124,7 @@ export default class ServerlessGitVariables { this.exportGitVariable(func, 'GIT_BRANCH', branch) this.exportGitVariable(func, 'GIT_IS_DIRTY', isDirty) this.exportGitVariable(func, 'GIT_REPOSITORY', repository) + this.exportGitVariable(func, 'GIT_TAGS', gitTagsOrCommit) } } diff --git a/test/index.spec.js b/test/index.spec.js index 3760b98..f5a839c 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -3,6 +3,7 @@ import process from 'process' import tmp from 'tmp' import fs from 'fs-extra' import Serverless from 'serverless' +import childProcess from 'child_process' import ServerlessGitVariables from '../src' @@ -61,6 +62,10 @@ test.serial('Inserts variables', async t => { sls.service.custom.message = '${git:message}' // eslint-disable-line sls.service.custom.describeLight = '${git:describeLight}' // eslint-disable-line sls.service.custom.repository = '${git:repository}' // eslint-disable-line + sls.service.custom.gitUser = '${git:user}' // eslint-disable-line + sls.service.custom.gitEmail = '${git:email}' // eslint-disable-line + sls.service.custom.tags = '${git:tags}' // eslint-disable-line + await sls.variables.populateService() t.is(sls.service.custom.sha1, '90440bd') @@ -70,6 +75,65 @@ test.serial('Inserts variables', async t => { t.is(sls.service.custom.describe2, 'my_tag-1-g90440bd') t.is(sls.service.custom.message, 'Another commit') t.is(sls.service.custom.describeLight, 'my_tag-1-g90440bd') + t.is(sls.service.custom.gitUser, 'Full User') + t.is(sls.service.custom.gitEmail, 'full@example.com') + t.is(sls.service.custom.tags, '90440bd') +}) + +test.serial('One tag on HEAD', async t => { + fs.copySync('test/resources/full_repo/git', `${t.context.tmpDir}/.git`) + process.chdir(t.context.tmpDir) + + await childProcess.exec('git checkout master') + + const sls = buildSls() + sls.service.custom.describe = '${git:describe}' // eslint-disable-line + sls.service.custom.sha1 = '${git:sha1}' // eslint-disable-line + sls.service.custom.commit = '${git:commit}' // eslint-disable-line + sls.service.custom.branch = '${git:branch}' // eslint-disable-line + sls.service.custom.describe2 = '${git:describe}' // eslint-disable-line + sls.service.custom.message = '${git:message}' // eslint-disable-line + sls.service.custom.describeLight = '${git:describeLight}' // eslint-disable-line + sls.service.custom.repository = '${git:repository}' // eslint-disable-line + sls.service.custom.tags = '${git:tags}' // eslint-disable-line + await sls.variables.populateService() + + t.is(sls.service.custom.sha1, 'ef5f068') + t.is(sls.service.custom.commit, 'ef5f0683654427ff38d43836098f6336d73c4576') + t.is(sls.service.custom.branch, 'master') + t.is(sls.service.custom.describe, 'my_tag') + t.is(sls.service.custom.describe2, 'my_tag') + t.is(sls.service.custom.message, 'Initial') + t.is(sls.service.custom.describeLight, 'my_tag') + t.is(sls.service.custom.tags, 'my_tag') +}) + +test.serial('Multiple tags on HEAD', async t => { + fs.copySync('test/resources/full_repo/git', `${t.context.tmpDir}/.git`) + process.chdir(t.context.tmpDir) + + await childProcess.exec('git checkout branch_with_tags') + + const sls = buildSls() + sls.service.custom.describe = '${git:describe}' // eslint-disable-line + sls.service.custom.sha1 = '${git:sha1}' // eslint-disable-line + sls.service.custom.commit = '${git:commit}' // eslint-disable-line + sls.service.custom.branch = '${git:branch}' // eslint-disable-line + sls.service.custom.describe2 = '${git:describe}' // eslint-disable-line + sls.service.custom.message = '${git:message}' // eslint-disable-line + sls.service.custom.describeLight = '${git:describeLight}' // eslint-disable-line + sls.service.custom.repository = '${git:repository}' // eslint-disable-line + sls.service.custom.tags = '${git:tags}' // eslint-disable-line + await sls.variables.populateService() + + t.is(sls.service.custom.sha1, '1335258') + t.is(sls.service.custom.commit, '1335258f70f45c6243bc674df830cd0ec7c3c714') + t.is(sls.service.custom.branch, 'branch_with_tags') + t.is(sls.service.custom.describe, 'my_tag-1-g1335258') + t.is(sls.service.custom.describe2, 'my_tag-1-g1335258') + t.is(sls.service.custom.message, 'Commit with tags.') + t.is(sls.service.custom.describeLight, 'tag1') + t.is(sls.service.custom.tags, 'tag1,tag2') }) test('Returns cached value as promise', async t => { @@ -108,11 +172,42 @@ test.serial('Env variables defined', async t => { t.is(func.environment.GIT_COMMIT_LONG, '90440bdc8eb3b2fa20bc578f411cf4b725ae0a25') t.is(func.environment.GIT_BRANCH, 'another_branch') t.is(func.environment.GIT_IS_DIRTY, 'false') + t.is(func.environment.GIT_TAGS, '90440bd') t.is(func.tags.GIT_COMMIT_SHORT, '90440bd') t.is(func.tags.GIT_COMMIT_LONG, '90440bdc8eb3b2fa20bc578f411cf4b725ae0a25') t.is(func.tags.GIT_BRANCH, 'another_branch') t.is(func.tags.GIT_IS_DIRTY, 'false') + t.is(func.tags.GIT_TAGS, '90440bd') +}) + +test.serial('User/Email not exported', async t => { + fs.copySync('test/resources/full_repo/git', `${t.context.tmpDir}/.git`) + process.chdir(t.context.tmpDir) + + const func = { + name: 'myFunction', + environment: {} + } + + const fakeServerless = { + service: { + getAllFunctions: () => [func.name], + getFunction: name => func + }, + variables: { + getValueFromSource: () => 'fake' + } + } + + const plugin = new ServerlessGitVariables(fakeServerless, {}) + await plugin.exportGitVariables() + + t.is(func.environment.GIT_USER, undefined) + t.is(func.environment.GIT_EMAIL, undefined) + + t.is(func.tags.GIT_USER, undefined) + t.is(func.tags.GIT_EMAIL, undefined) }) test.serial('Disabling export of env variables', async t => { @@ -141,6 +236,7 @@ test.serial('Disabling export of env variables', async t => { t.is(func.environment.GIT_COMMIT_LONG, undefined) t.is(func.environment.GIT_BRANCH, undefined) t.is(func.environment.GIT_IS_DIRTY, undefined) + t.is(func.environment.GIT_TAGS, undefined) t.is(func.tags, undefined) }) diff --git a/test/resources/full_repo/git/COMMIT_EDITMSG b/test/resources/full_repo/git/COMMIT_EDITMSG index 7281884..f778e67 100644 --- a/test/resources/full_repo/git/COMMIT_EDITMSG +++ b/test/resources/full_repo/git/COMMIT_EDITMSG @@ -1 +1 @@ -Another commit +Commit with tags. diff --git a/test/resources/full_repo/git/config b/test/resources/full_repo/git/config index 6c9406b..e38ac42 100644 --- a/test/resources/full_repo/git/config +++ b/test/resources/full_repo/git/config @@ -5,3 +5,6 @@ logallrefupdates = true ignorecase = true precomposeunicode = true +[user] + name = Full User + email = full@example.com diff --git a/test/resources/full_repo/git/logs/HEAD b/test/resources/full_repo/git/logs/HEAD index b7f08e4..6b8c9bc 100644 --- a/test/resources/full_repo/git/logs/HEAD +++ b/test/resources/full_repo/git/logs/HEAD @@ -1,3 +1,9 @@ 0000000000000000000000000000000000000000 ef5f0683654427ff38d43836098f6336d73c4576 Jacob Meacham 1492298738 -0700 commit (initial): Initial ef5f0683654427ff38d43836098f6336d73c4576 ef5f0683654427ff38d43836098f6336d73c4576 Jacob Meacham 1492298745 -0700 checkout: moving from master to another_branch ef5f0683654427ff38d43836098f6336d73c4576 90440bdc8eb3b2fa20bc578f411cf4b725ae0a25 Jacob Meacham 1492298755 -0700 commit: Another commit +90440bdc8eb3b2fa20bc578f411cf4b725ae0a25 ef5f0683654427ff38d43836098f6336d73c4576 David Navrkal 1571233570 +0200 checkout: moving from another_branch to master +ef5f0683654427ff38d43836098f6336d73c4576 ef5f0683654427ff38d43836098f6336d73c4576 David Navrkal 1571233581 +0200 checkout: moving from master to branch_with_tags +ef5f0683654427ff38d43836098f6336d73c4576 90440bdc8eb3b2fa20bc578f411cf4b725ae0a25 David Navrkal 1571233629 +0200 checkout: moving from branch_with_tags to another_branch +90440bdc8eb3b2fa20bc578f411cf4b725ae0a25 ef5f0683654427ff38d43836098f6336d73c4576 David Navrkal 1571233695 +0200 checkout: moving from another_branch to branch_with_tags +ef5f0683654427ff38d43836098f6336d73c4576 1335258f70f45c6243bc674df830cd0ec7c3c714 David Navrkal 1571233707 +0200 commit: Commit with tags. +1335258f70f45c6243bc674df830cd0ec7c3c714 90440bdc8eb3b2fa20bc578f411cf4b725ae0a25 David Navrkal 1571234561 +0200 checkout: moving from branch_with_tags to another_branch diff --git a/test/resources/full_repo/git/logs/refs/heads/branch_with_tags b/test/resources/full_repo/git/logs/refs/heads/branch_with_tags new file mode 100644 index 0000000..c740f24 --- /dev/null +++ b/test/resources/full_repo/git/logs/refs/heads/branch_with_tags @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 ef5f0683654427ff38d43836098f6336d73c4576 David Navrkal 1571233581 +0200 branch: Created from HEAD +ef5f0683654427ff38d43836098f6336d73c4576 1335258f70f45c6243bc674df830cd0ec7c3c714 David Navrkal 1571233707 +0200 commit: Commit with tags. diff --git a/test/resources/full_repo/git/objects/13/35258f70f45c6243bc674df830cd0ec7c3c714 b/test/resources/full_repo/git/objects/13/35258f70f45c6243bc674df830cd0ec7c3c714 new file mode 100644 index 0000000..f4d4721 --- /dev/null +++ b/test/resources/full_repo/git/objects/13/35258f70f45c6243bc674df830cd0ec7c3c714 @@ -0,0 +1,3 @@ +xK +1D]Mw:t#c; U=(xqXUUSdah" +TCΆP*wg7*J qJ0-PH΋vf8w_-B9\<{:D=".M[oWhܘ/,I` \ No newline at end of file diff --git a/test/resources/full_repo/git/refs/heads/branch_with_tags b/test/resources/full_repo/git/refs/heads/branch_with_tags new file mode 100644 index 0000000..bbb041e --- /dev/null +++ b/test/resources/full_repo/git/refs/heads/branch_with_tags @@ -0,0 +1 @@ +1335258f70f45c6243bc674df830cd0ec7c3c714 diff --git a/test/resources/full_repo/git/refs/tags/tag1 b/test/resources/full_repo/git/refs/tags/tag1 new file mode 100644 index 0000000..bbb041e --- /dev/null +++ b/test/resources/full_repo/git/refs/tags/tag1 @@ -0,0 +1 @@ +1335258f70f45c6243bc674df830cd0ec7c3c714 diff --git a/test/resources/full_repo/git/refs/tags/tag2 b/test/resources/full_repo/git/refs/tags/tag2 new file mode 100644 index 0000000..bbb041e --- /dev/null +++ b/test/resources/full_repo/git/refs/tags/tag2 @@ -0,0 +1 @@ +1335258f70f45c6243bc674df830cd0ec7c3c714 diff --git a/test/resources/simple_repo/git/config b/test/resources/simple_repo/git/config index 6c9406b..a0b2e00 100644 --- a/test/resources/simple_repo/git/config +++ b/test/resources/simple_repo/git/config @@ -5,3 +5,7 @@ logallrefupdates = true ignorecase = true precomposeunicode = true + +[user] + name = Simple User + email = simple@example.com \ No newline at end of file