Skip to content

Commit

Permalink
feat: rewrite so it works, but with Travis only
Browse files Browse the repository at this point in the history
  • Loading branch information
boennemann committed Feb 17, 2017
1 parent 51e7d75 commit 71f7f2d
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 126 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]

end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
*.log
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# greenkeeper-shrinkwrap

> Enabling shrinkwrap support for Greenkeeper
> Enabling shrinkwrap support for Greenkeeper via Travis CI
[![Build Status](https://travis-ci.org/greenkeeperio/greenkeeper-shrinkwrap.svg?branch=master)](https://travis-ci.org/greenkeeperio/greenkeeper-shrinkwrap)
[![Dependency Status](https://david-dm.org/greenkeeperio/greenkeeper-shrinkwrap/master.svg)](https://david-dm.org/greenkeeperio/greenkeeper-shrinkwrap/master)
Expand All @@ -14,34 +14,35 @@

After [enabling Greenkeeper for your repository](https://github.com/greenkeeperio/greenkeeper#getting-started-with-greenkeeper) you can use this package to make it work with shrinkwrapped projects.

1. [Create a GitHub access token with push access to your repository](https://github.com/settings/tokens) and make it available to your CI server's environment as `GH_TOKEN`.
1. [Create a GitHub access token with push access to your repository](https://github.com/settings/tokens) and make it available to Travis CI's environment as `GH_TOKEN`.

2. Configure your CI server to run `greenkeeper-shrinkwrap` right after it `npm install`ed your dependencies.
1. Add `greenkeeper-shrinkwrap` to your project as a devDependency. `npm install --save-dev greenkeeper-shrinkwrap`

1. Configure Travis CI to run `greenkeeper-shrinkwrap-update` right before it `npm install`s your dependencies.

```yml
before_install: greenkeeper-shrinkwrap-update
```
1. Configure Travis CI to run `greenkeeper-shrinkwrap-upload` right after it executed your tests.

```yml
# Travis CI example
before_script:
- npm install -g greenkeeper-shrinkwrap
- greenkeeper-shrinkwrap
after_script: greenkeeper-shrinkwrap-update
```

That's it.

### Testing multiple node versions

For example on Travis CI it is common to test multiple node versions and therefor have multiple test runs. In this case you should still update the shrinkwrap file for every build job, but only upload it once.
This is why these two steps are available as individual commands: `greenkeeper-shrinkwrap-update` and `greenkeeper-shrinkwrap-upload`.
It is common to test multiple node versions and therefor have multiple test jobs for one build. In this case the shrinkwrap will automatically be updated for every job, but only uploaded for the first one.

```yml
# Travis CI example
node_js:
- 6
- 4
- 5
before_script:
- npm install -g greenkeeper-shrinkwrap
- greenkeeper-shrinkwrap-update
# This will only run on the node version 4 job
- if [[ $TRAVIS_JOB_NUMBER = "${TRAVIS_BUILD_NUMBER}.1" ]]; then greenkeeper-shrinkwrap-upload; fi
before_install: greenkeeper-shrinkwrap-update
# Only the node version 6 job will upload the shrinkwrap
after_script: greenkeeper-shrinkwrap-upload
```

## How does it work
Expand Down
3 changes: 0 additions & 3 deletions index.js

This file was deleted.

44 changes: 22 additions & 22 deletions lib/extract-dependency.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
var exec = require('child_process').exec

var _ = require('lodash')
const _ = require('lodash')

// extract updated dependency/version combo from branch name
module.exports = function (pkg, callback) {
exec('git rev-parse --abbrev-ref HEAD', function (err, stdout) {
if (err) throw err
module.exports = function extractDependency (pkg, branch) {
const config = pkg.greenkeeper || {}
const branchPrefix = config.branchPrefix || 'greenkeeper/'

var branch = stdout.trim()
var config = pkg.greenkeeper || {}
var branchPrefix = config.branchPrefix || 'greenkeeper-'
if (!branch.startsWith(branchPrefix)) throw new Error('Not a Greenkeeper pull request.')

if (!_.startsWith(branch, branchPrefix)) callback(new Error('Not a Greenkeeper pull request.'))
const allDependencyTypes = _.pick(pkg, [
'dependencies',
'devDependencies',
'optionalDependencies'
])

var dependency = pkg.dependencies && _(pkg.dependencies)
.mapValues(function (version, name) {
return {
version: version,
name: name
}
})
.find(function (dependency) {
return branch === branchPrefix + dependency.name + '-' + dependency.version.replace(/(>|<|\^|~|=)/g, '')
const allDependencies = _.flatten(_.map(allDependencyTypes, (dependencies, type) => {
return _.map(dependencies, (range, name) => {
const version = range.replace(/(>|<|\^|~|=)/g, '')
const prefix = range.replace(version, '')
return {name, range, type, version, prefix}
})
}))

if (!dependency) callback(new Error('No dependency changed.'))

callback(null, dependency)
const dependency = _.find(allDependencies, (dependency) => {
return branch === branchPrefix + dependency.name + '-' + dependency.version
})

if (!dependency) throw new Error('No dependency changed.')

return dependency
}
57 changes: 35 additions & 22 deletions lib/update-shrinkwrap.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
var exec = require('child_process').exec

var _ = require('lodash')
var semver = require('semver')
var series = require('run-series')

module.exports = function (dependency, commitMessage, callback) {
var updateMessage = commitMessage + '\n\nshrinkwrap updated by https://npm.im/greenkeeper-shrinkwrap'

series([
_.partial(exec, 'git reset HEAD^ --hard'),
_.partial(exec, 'npm install --save ' + dependency.name + '@' + dependency.version),
function (callback) {
exec('npm --version', function (err, version) {
if (err) return callback(err)
if (semver.gte(version, '3.0.0')) return callback(null)
exec('npm shrinkwrap', callback)
})
},
_.partial(exec, 'git add {package,npm-shrinkwrap}.json'),
_.partial(exec, 'git commit -m "' + updateMessage + '"')
], callback)
const exec = require('child_process').execSync

const semver = require('semver')

const flags = {
'dependencies': '-S',
'devDependencies': '-D',
'optionalDependencies': '-O'
}

module.exports = function updateShrinkwrap (dependency, commitMessage, callback) {
const updateMessage = commitMessage + '\n\nshrinkwrap updated by https://npm.im/greenkeeper-shrinkwrap'

if (semver.lt(exec('npm --version').toString().trim(), '3.0.0')) {
// update the shrinkwrap
exec('npm shrinkwrap')

// add it to the greenkeeper commit
exec('git add npm-shrinkwrap.json')
exec(`git commit --amend -m "${updateMessage}"`)
return
}

// revert the commit done by greenkeeper
exec('git reset HEAD^ --hard')

const flag = flags[dependency.type]
const prefix = `--save-prefix="${dependency.prefix}"`

// correctly reinstall the package so the shrinkwrap is updated
exec(`npm install ${flag} ${prefix} ${dependency.name}@${dependency.version}`)

// commit again
exec('git add {package,npm-shrinkwrap}.json')
exec(`git commit -m "${updateMessage}"`)
}
17 changes: 8 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
{
"name": "greenkeeper-shrinkwrap",
"description": "Your shrinkwrap, up to date, all the time",
"version": "0.0.0",
"version": "0.0.0-development",
"author": "Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)",
"bin": {
"greenkeeper-shrinkwrap": "index.js",
"greenkeeper-shrinkwrap-update": "update.js",
"greenkeeper-shrinkwrap-upload": "upload.js"
},
"bugs": {
"url": "https://github.com/greenkeeperio/greenkeeper-shrinkwrap/issues"
},
"dependencies": {
"github-slug": "^1.1.0",
"lodash": "^4.8.2",
"lodash": "^4.17.4",
"require-relative": "^0.8.7",
"run-series": "^1.1.4",
"semver": "^5.1.0"
"semver": "^5.3.0"
},
"devDependencies": {
"standard": "^6.0.8"
"standard": "^8.6.0"
},
"homepage": "http://greenkeeper.io",
"engines": {
"node": ">=4"
},
"homepage": "https://greenkeeper.io",
"license": "Apache-2.0",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/greenkeeperio/greenkeeper-shrinkwrap.git"
Expand Down
65 changes: 33 additions & 32 deletions update.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
#!/usr/bin/env node

var exec = require('child_process').exec
var fs = require('fs')
const fs = require('fs')

var relative = require('require-relative')
const relative = require('require-relative')

var extractDependency = require('./lib/extract-dependency')
var updateShrinkwrap = require('./lib/update-shrinkwrap')
const extractDependency = require('./lib/extract-dependency')
const updateShrinkwrap = require('./lib/update-shrinkwrap')

var pkg = relative('./package.json')
const pkg = relative('./package.json')

module.exports = function (callback) {
const env = process.env

module.exports = function update () {
try {
fs.readFileSync('./npm-shrinkwrap.json')
} catch (e) {
console.error('Without a shrinkwrap file present there is no need to run this script.')
process.exit(1)
throw new Error('Without a shrinkwrap file present there is no need to run this script.')
}

if (env.TRAVIS !== 'true') {
throw new Error('This script hast to run in an Travis CI environment')
}

if (env.TRAVIS_PULL_REQUEST !== 'false') {
return console.error('This script needs to run in a branch build, not a PR')
}

const commitMessage = env.TRAVIS_COMMIT_MESSAGE

if (/shrinkwrap updated/mig.test(commitMessage)) {
return console.error('Nothing to do, shrinkwrap already updated.')
}

try {
var dependency = extractDependency(pkg, env.TRAVIS_BRANCH)
} catch (err) {
// these are expected failures
return console.error(err.message)
}

exec('git log -1 --pretty=%B', function (err, commitMessage) {
if (err) throw err

if (/shrinkwrap updated/mig.test(commitMessage)) {
console.error('Nothing to do, shrinkwrap already updated.')
process.exit(0)
}

extractDependency(pkg, function (err, dependency) {
// these are expected failures
if (err) {
console.error(err.message)
process.exit(0)
}

updateShrinkwrap(dependency, commitMessage, function (err) {
if (err) throw err

console.log('shrinkwrap file successfully updated')
callback && callback()
})
})
})
updateShrinkwrap(dependency, commitMessage)

console.log('Shrinkwrap file updated')
}

if (require.main === module) module.exports()
31 changes: 9 additions & 22 deletions upload.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
#!/usr/bin/env node

var exec = require('child_process').exec
const exec = require('child_process').execSync

var _ = require('lodash')
var series = require('run-series')
var slug = require('github-slug')
const env = process.env

var token = process.env.GH_TOKEN
module.exports = function upload () {
if (!env.TRAVIS_JOB_NUMBER.endsWith('.1')) return console.error('Only running on first build job')

module.exports = function () {
if (!token) throw new Error('GitHub token required.')
if (!env.GH_TOKEN) throw new Error('Please provide a GitHub token as "GH_TOKEN" environment variable')

series([
function (callback) {
slug('./', function (err, slug) {
if (err) return callback(err)
exec('git remote set gk-origin https://' + token + '@github.com/' + slug, callback)
})
},
_.partial(exec, 'git config user.email "support@greenkeeper.io"'),
_.partial(exec, 'git config user.name "greenkeeperio-bot"'),
_.partial(exec, 'git push gk-origin HEAD --force')
], function (err) {
if (err) throw err

console.log('shrinkwrap file successfully uploaded')
})
exec(`git remote set gk-origin https://${env.GH_TOKEN}@github.com/${env.TRAVIS_REPO_SLUG}`)
exec('git config user.email "support@greenkeeper.io"')
exec('git config user.name "greenkeeperio[bot]"')
exec(`git push gk-origin HEAD:${env.TRAVIS_BRANCH} --force`)
}

if (require.main === module) module.exports()

0 comments on commit 71f7f2d

Please sign in to comment.