Skip to content

Commit 844cde6

Browse files
authoredNov 4, 2018
feat: fallback to tags if no meta-information file found (#275)
BREAKING CHANGE: if no package.json, bower.json, etc., is found, we now fallback to git tags
1 parent e86fe6b commit 844cde6

File tree

7 files changed

+118
-32
lines changed

7 files changed

+118
-32
lines changed
 

Diff for: ‎README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@
88

99
_Having problems? want to contribute? join our [community slack](http://devtoolscommunity.herokuapp.com)_.
1010

11-
> stop using `npm version`, use `standard-version` it rocks!
1211

13-
Automatic versioning and CHANGELOG generation, using GitHub's squash button and
12+
Automate versioning and CHANGELOG generation, with [semver](https://semver.org/) and
1413
[conventional commit messages](https://conventionalcommits.org).
1514

1615
_how it works:_
1716

1817
1. when you land commits on your `master` branch, select the _Squash and Merge_ option.
1918
2. add a title and body that follows the [Conventional Commits Specification](https://conventionalcommits.org).
20-
3. when you're ready to release to npm:
19+
3. when you're ready to release:
2120
1. `git checkout master; git pull origin master`
2221
2. run `standard-version`
23-
3. `git push --follow-tags origin master && npm publish`
22+
3. `git push --follow-tags origin master && npm publish
23+
_(or, `docker push`, `gem push`, etc.)_
2424

2525
`standard-version` does the following:
2626

27-
1. bumps the version in _package.json/bower.json_ (based on your commit history)
27+
1. bumps the version in metadata files (package.json, composer.json, etc).
2828
2. uses [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) to update _CHANGELOG.md_
2929
3. commits _package.json (et al.)_ and _CHANGELOG.md_
3030
4. tags a new release
@@ -181,7 +181,7 @@ Simply add the following to your package.json to configure lifecycle scripts:
181181
}
182182
```
183183

184-
As an example to change from using GitHub to track your items to using your projects Jira use a
184+
As an example to change from using GitHub to track your items to using your projects Jira use a
185185
`postchangelog` script to replace the url fragment containing 'https://github.com/`myproject`/issues/'
186186
with a link to your Jira - assuming you have already installed [replace](https://www.npmjs.com/package/replace)
187187
```json

Diff for: ‎command.js

+5
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ module.exports = require('yargs')
7272
default: defaults.dryRun,
7373
describe: 'See the commands that running standard-version would run'
7474
})
75+
.option('git-tag-fallback', {
76+
type: 'boolean',
77+
default: defaults.gitTagFallback,
78+
describe: `fallback to git tags for version, if no meta-information file is found (e.g., package.json)`
79+
})
7580
.check((argv) => {
7681
if (typeof argv.scripts !== 'object' || Array.isArray(argv.scripts)) {
7782
throw Error('scripts must be an object')

Diff for: ‎defaults.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
"tagPrefix": "v",
1010
"scripts": {},
1111
"skip": {},
12-
"dryRun": false
12+
"dryRun": false,
13+
"gitTagFallback": true
1314
}

Diff for: ‎index.js

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const latestSemverTag = require('./lib/latest-semver-tag')
12
const path = require('path')
23
const printError = require('./lib/print-error')
34

@@ -7,24 +8,33 @@ const commit = require('./lib/lifecycles/commit')
78
const tag = require('./lib/lifecycles/tag')
89

910
module.exports = function standardVersion (argv) {
10-
var pkg
11+
let pkg
1112
bump.pkgFiles.forEach((filename) => {
1213
if (pkg) return
1314
var pkgPath = path.resolve(process.cwd(), filename)
1415
try {
1516
pkg = require(pkgPath)
1617
} catch (err) {}
1718
})
18-
if (!pkg) {
19-
return Promise.reject(new Error('no package file found'))
20-
}
21-
var newVersion = pkg.version
22-
var defaults = require('./defaults')
23-
var args = Object.assign({}, defaults, argv)
19+
let newVersion
20+
let defaults = require('./defaults')
21+
let args = Object.assign({}, defaults, argv)
2422

2523
return Promise.resolve()
2624
.then(() => {
27-
return bump(args, pkg)
25+
if (!pkg && args.gitTagFallback) {
26+
return latestSemverTag()
27+
} else if (!pkg) {
28+
throw new Error('no package file found')
29+
} else {
30+
return pkg.version
31+
}
32+
})
33+
.then(version => {
34+
newVersion = version
35+
})
36+
.then(() => {
37+
return bump(args, newVersion)
2838
})
2939
.then((_newVersion) => {
3040
// if bump runs, it calculaes the new version that we
@@ -36,7 +46,7 @@ module.exports = function standardVersion (argv) {
3646
return commit(args, newVersion)
3747
})
3848
.then(() => {
39-
return tag(newVersion, pkg.private, args)
49+
return tag(newVersion, pkg ? pkg.private : false, args)
4050
})
4151
.catch((err) => {
4252
printError(args, err.message)

Diff for: ‎lib/latest-semver-tag.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const gitSemverTags = require('git-semver-tags')
2+
const semver = require('semver')
3+
4+
module.exports = function () {
5+
return new Promise((resolve, reject) => {
6+
gitSemverTags(function (err, tags) {
7+
if (err) return reject(err)
8+
else if (!tags.length) return resolve('1.0.0')
9+
// ensure that the largest semver tag is at the head.
10+
tags = tags.map(tag => { return semver.clean(tag) })
11+
tags.sort(semver.rcompare)
12+
return resolve(tags[0])
13+
})
14+
})
15+
}

Diff for: ‎lib/lifecycles/bump.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ const writeFile = require('../write-file')
1313

1414
var configsToUpdate = {}
1515

16-
function Bump (args, pkg) {
16+
function Bump (args, version) {
1717
// reset the cache of updated config files each
1818
// time we perform the version bump step.
1919
configsToUpdate = {}
2020

2121
if (args.skip.bump) return Promise.resolve()
22-
var newVersion = pkg.version
22+
var newVersion = version
2323
return runLifecycleScript(args, 'prerelease')
2424
.then(runLifecycleScript.bind(this, args, 'prebump'))
2525
.then((stdout) => {
@@ -28,8 +28,8 @@ function Bump (args, pkg) {
2828
})
2929
.then((release) => {
3030
if (!args.firstRelease) {
31-
var releaseType = getReleaseType(args.prerelease, release.releaseType, pkg.version)
32-
newVersion = semver.valid(releaseType) || semver.inc(pkg.version, releaseType, args.prerelease)
31+
var releaseType = getReleaseType(args.prerelease, release.releaseType, version)
32+
newVersion = semver.valid(releaseType) || semver.inc(version, releaseType, args.prerelease)
3333
updateConfigs(args, newVersion)
3434
} else {
3535
checkpoint(args, 'skip version bump on first release', [], chalk.red(figures.cross))

Diff for: ‎test.js

+67-12
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
'use strict'
44

5-
var shell = require('shelljs')
6-
var fs = require('fs')
7-
var path = require('path')
8-
var stream = require('stream')
9-
var mockGit = require('mock-git')
10-
var mockery = require('mockery')
11-
var semver = require('semver')
12-
var formatCommitMessage = require('./lib/format-commit-message')
13-
var cli = require('./command')
14-
var standardVersion = require('./index')
5+
const shell = require('shelljs')
6+
const fs = require('fs')
7+
const path = require('path')
8+
const stream = require('stream')
9+
const mockGit = require('mock-git')
10+
const mockery = require('mockery')
11+
const semver = require('semver')
12+
const formatCommitMessage = require('./lib/format-commit-message')
13+
const cli = require('./command')
14+
const standardVersion = require('./index')
1515

1616
require('chai').should()
1717

@@ -45,7 +45,6 @@ function writePackageJson (version, option) {
4545
option = option || {}
4646
var pkg = Object.assign(option, { version: version })
4747
fs.writeFileSync('package.json', JSON.stringify(pkg), 'utf-8')
48-
delete require.cache[require.resolve(path.join(process.cwd(), 'package.json'))]
4948
}
5049

5150
function writeBowerJson (version, option) {
@@ -96,6 +95,16 @@ function initInTempFolder () {
9695
shell.cd('tmp')
9796
shell.exec('git init')
9897
commit('root-commit')
98+
;['package.json',
99+
'manifest.json',
100+
'bower.json'
101+
].forEach(metadata => {
102+
try {
103+
delete require.cache[require.resolve(path.join(process.cwd(), metadata))]
104+
} catch (err) {
105+
// we haven't loaded the metadata file yet.
106+
}
107+
})
99108
writePackageJson('1.0.0')
100109
}
101110

@@ -746,7 +755,10 @@ describe('standard-version', function () {
746755
describe('without a package file to bump', function () {
747756
it('should exit with error', function () {
748757
shell.rm('package.json')
749-
return require('./index')({ silent: true })
758+
return require('./index')({
759+
silent: true,
760+
gitTagFallback: false
761+
})
750762
.catch((err) => {
751763
err.message.should.equal('no package file found')
752764
})
@@ -886,4 +898,47 @@ describe('standard-version', function () {
886898
})
887899
})
888900
})
901+
902+
describe('.gitignore', () => {
903+
beforeEach(function () {
904+
writeBowerJson('1.0.0')
905+
})
906+
907+
it('does not update files present in .gitignore', () => {
908+
fs.writeFileSync('.gitignore', 'bower.json', 'utf-8')
909+
910+
commit('feat: first commit')
911+
shell.exec('git tag -a v1.0.0 -m "my awesome first release"')
912+
commit('feat: new feature!')
913+
return require('./index')({ silent: true })
914+
.then(() => {
915+
JSON.parse(fs.readFileSync('bower.json', 'utf-8')).version.should.equal('1.0.0')
916+
getPackageVersion().should.equal('1.1.0')
917+
})
918+
})
919+
})
920+
921+
describe('gitTagFallback', () => {
922+
it('defaults to 1.0.0 if no tags in git history', () => {
923+
shell.rm('package.json')
924+
commit('feat: first commit')
925+
return require('./index')({ silent: true })
926+
.then(() => {
927+
const output = shell.exec('git tag')
928+
output.stdout.should.include('v1.1.0')
929+
})
930+
})
931+
932+
it('bases version on last tag, if tags are found', () => {
933+
shell.rm('package.json')
934+
shell.exec('git tag -a v5.0.0 -m "a release"')
935+
shell.exec('git tag -a v3.0.0 -m "another release"')
936+
commit('feat: another commit')
937+
return require('./index')({ silent: true })
938+
.then(() => {
939+
const output = shell.exec('git tag')
940+
output.stdout.should.include('v5.1.0')
941+
})
942+
})
943+
})
889944
})

0 commit comments

Comments
 (0)
Please sign in to comment.