Skip to content

Commit

Permalink
Add tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-meacham committed Apr 16, 2017
1 parent a6d8ef1 commit 0f9f9bc
Show file tree
Hide file tree
Showing 6 changed files with 1,129 additions and 889 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
@@ -1,5 +1,5 @@
language: node_js
node_js:
- '6'
- '7'
script: npm run build
after_success: npm run ci:coverage
5 changes: 4 additions & 1 deletion package.json
Expand Up @@ -58,8 +58,11 @@
"eslint-plugin-ava": "4.0.1",
"eslint-plugin-promise": "3.4.0",
"eslint-plugin-standard": "2.0.1",
"fs-extra": "2.1.2",
"nyc": "10.0.0",
"rimraf": "2.5.4"
"rimraf": "2.5.4",
"serverless": "1.11.0",
"tmp": "0.0.31"
},
"peerDependencies": {
"serverless": ">=1.6.0"
Expand Down
74 changes: 45 additions & 29 deletions src/index.js
Expand Up @@ -4,48 +4,64 @@ import childProcess from 'child_process'

const GIT_PREFIX = 'git'

const resolvedValues = {}

async function getValueFromGit(variable) {
if (resolvedValues[variable]) {
return resolvedValues[variable]
}

function exec(cmd, options = { timeout: 1000 }) {
return new Promise((resolve, reject) => {
childProcess.exec(cmd, options, (err, stdout, stder) => {
if (err) {
reject(err)
} else {
resolve(stdout)
}
})
async function _exec(cmd, options = { timeout: 1000 }) {
return new Promise((resolve, reject) => {
childProcess.exec(cmd, options, (err, stdout) => {
if (err) {
reject(err)
} else {
resolve(stdout.trim())
}
})
}

switch (variable) {
case 'describe':
return exec('git describe')
case 'sha1':
return exec('git rev-parse --short')
case 'branch':
return exec('git rev-parse --abbrev-ref HEAD')
default:
throw new Error(`Git variable ${variable} is unknown. Candidates are 'describe', 'sha1', 'branch'`)
}
})
}

export default class ServerlessGitVariables {
constructor(serverless, options) {
this.resolvedValues = {}
const delegate = serverless.variables.getValueFromSource.bind(serverless.variables)

serverless.variables.getValueFromSource = (variableString) => {
if (variableString.startsWith(`${GIT_PREFIX}:`)) {
const variable = variableString.split(`${GIT_PREFIX}:`)[1]
return deasyncPromise(getValueFromGit(variable))
return this._getValueFromGitSync(variable)
}

return delegate(variableString)
}
}

_getValueFromGitSync(variable) {
if (this.resolvedValues[variable]) {
return this.resolvedValues[variable]
}

return deasyncPromise(this._getValueFromGit(variable))
}

async _getValueFromGit(variable) {
let value = null
switch (variable) {
case 'describe':
value = await _exec('git describe')
break
case 'sha1':
value = await _exec('git rev-parse --short HEAD')
break
case 'branch':
value = await _exec('git rev-parse --abbrev-ref HEAD')
break
default:
throw new Error(`Git variable ${variable} is unknown. Candidates are 'describe', 'sha1', 'branch'`)
}

// TODO: Figure out why if I don't log, the deasync promise
// never resolves. Catching it in the debugger or logging
// causes it to work fine.
process.stdout.write('')

// Cache before returning
this.resolvedValues[variable] = value
return value
}
}
72 changes: 72 additions & 0 deletions test/index.spec.js
@@ -0,0 +1,72 @@
import test from 'ava'
import process from 'process'
import tmp from 'tmp'
import fs from 'fs-extra'
import Serverless from 'serverless'

import ServerlessGitVariables from '../src'

function buildSls() {
const sls = new Serverless()
sls.pluginManager.addPlugin(ServerlessGitVariables)
sls.init()

return sls
}

test.beforeEach(t => {
t.context.initalDir = process.cwd()
})

test.beforeEach(t => {
t.context.tmpDir = tmp.dirSync({ unsafeCleanup: true }).name
})

test.afterEach.always(t => {
process.chdir(t.context.initalDir)
})

test('Variables are passed through', t => {
const sls = buildSls()
sls.service.custom.myVar = 'myVar'
sls.service.custom.myResoledVar = '${self:custom.myVar}' // eslint-disable-line

sls.variables.populateService()
t.is(sls.service.custom.myResoledVar, 'myVar')
})

test('Throws on bad key', t => {
const sls = buildSls()
sls.service.custom.myVar = '${git:badKey}' // eslint-disable-line
t.throws(() => {
sls.variables.populateService()
}, /Error: Git variable badKey is unknown.*/)
})

test('Throws on bad git command', t => {
fs.copySync('test/resources/simple_repo/git', `${t.context.tmpDir}/.git`)
process.chdir(t.context.tmpDir)

const sls = buildSls()
sls.service.custom.describe = '${git:describe}' // eslint-disable-line
t.throws(() => {
sls.variables.populateService()
}, /Error: Command failed: git describe/)
})

test('Inserts variables', t => {
fs.copySync('test/resources/full_repo/git', `${t.context.tmpDir}/.git`)
process.chdir(t.context.tmpDir)

const sls = buildSls()
sls.service.custom.describe = '${git:describe}' // eslint-disable-line
sls.service.custom.sha1 = '${git:sha1}' // eslint-disable-line
sls.service.custom.branch = '${git:branch}' // eslint-disable-line
sls.service.custom.describe2 = '${git:describe}' // eslint-disable-line
sls.variables.populateService()

t.is(sls.service.custom.sha1, '90440bd')
t.is(sls.service.custom.branch, 'another_branch')
t.is(sls.service.custom.describe, 'my_tag-1-g90440bd')
t.is(sls.service.custom.describe2, 'my_tag-1-g90440bd')
})
Empty file removed test/resources/non_repo/.gitkeep
Empty file.

0 comments on commit 0f9f9bc

Please sign in to comment.