Repository: conventional-changelog/standard-version
Pull request #148 (2016-11-26 23:59:14)

feat: add support for bumping version # in bower.json
working from @lexich's foundation, this pull adds support for bumping version # in multiple config files in a generic way.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/9010452/badge)](https://coveralls.io/builds/9010452)

Coverage remained the same at 100.0% when pulling **4036c833caa1e063c4dc42017ddc7fba635224f0 on bower** into **5c543a12ce3d9956d4b43ee1d2bbfeee3f22d90d on master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/9010458/badge)](https://coveralls.io/builds/9010458)

Coverage remained the same at 100.0% when pulling **02ffec8c6055506d19a90045494ff29e40182eb2 on bower** into **5c543a12ce3d9956d4b43ee1d2bbfeee3f22d90d on master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/9010515/badge)](https://coveralls.io/builds/9010515)

Coverage remained the same at 100.0% when pulling **9cff7898e584a7071b322935e82440a30f2a2e60 on bower** into **70b20c8793e63483eb76e95c6495f03b8dd3dd89 on master**.


Patch:
diff --git a/README.md b/README.md
index 2c509a5..3e9e3bb 100644
--- a/README.md
+++ b/README.md
@@ -23,9 +23,9 @@ _how it works:_
 
 `standard-version` does the following:
 
-1. bumps the version in _package.json_ (based on your commit history)
+1. bumps the version in _package.json/bower.json_ (based on your commit history)
 2. uses [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) to update _CHANGELOG.md_
-3. commits _package.json_ and _CHANGELOG.md_
+3. commits _package.json (et al.)_ and _CHANGELOG.md_
 4. tags a new release
 
 ## Installation
@@ -77,7 +77,7 @@ npm run release -- --first-release
 standard-version --first-release
 ```
 
-This will tag a release **without bumping the version in package.json**.
+This will tag a release **without bumping the version in package.json (_et al._)**.
 
 When ready, push the git tag and `npm publish` your first release. \o/
 
diff --git a/index.js b/index.js
index 906d2e7..4960439 100755
--- a/index.js
+++ b/index.js
@@ -15,7 +15,6 @@ module.exports = function standardVersion (argv, done) {
   var pkgPath = path.resolve(process.cwd(), './package.json')
   var pkg = require(pkgPath)
   var defaults = require('./defaults')
-
   var args = objectAssign({}, defaults, argv)
 
   bumpVersion(args.releaseAs, function (err, release) {
@@ -29,11 +28,7 @@ module.exports = function standardVersion (argv, done) {
     if (!args.firstRelease) {
       var releaseType = getReleaseType(args.prerelease, release.releaseType, pkg.version)
       newVersion = semver.inc(pkg.version, releaseType, args.prerelease)
-
-      checkpoint(args, 'bumping version in package.json from %s to %s', [pkg.version, newVersion])
-
-      pkg.version = newVersion
-      fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8')
+      updateConfigs(args, newVersion)
     } else {
       checkpoint(args, 'skip version bump on first release', [], chalk.red(figures.cross))
     }
@@ -52,6 +47,37 @@ module.exports = function standardVersion (argv, done) {
   })
 }
 
+/**
+ * attempt to update the version # in a collection of common config
+ * files, e.g., package.json, bower.json.
+ *
+ * @param argv config object
+ * @param newVersion version # to update to.
+ * @return {string}
+ */
+var configsToUpdate = {}
+function updateConfigs (args, newVersion) {
+  configsToUpdate[path.resolve(process.cwd(), './package.json')] = false
+  configsToUpdate[path.resolve(process.cwd(), './bower.json')] = false
+  Object.keys(configsToUpdate).forEach(function (configPath) {
+    try {
+      var stat = fs.lstatSync(configPath)
+      if (stat.isFile()) {
+        var config = require(configPath)
+        var filename = path.basename(configPath)
+        config.version = newVersion
+        fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8')
+        checkpoint(args, 'bumping version in ' + filename + ' from %s to %s', [config.version, newVersion])
+        // flag any config files that we modify the version # for
+        // as having been updated.
+        configsToUpdate[configPath] = true
+      }
+    } catch (err) {
+      if (err.code !== 'ENOENT') console.warn(err.message)
+    }
+  })
+}
+
 function getReleaseType (prerelease, expectedReleaseType, currentVersion) {
   if (isString(prerelease)) {
     if (isInPrerelease(currentVersion)) {
@@ -160,7 +186,6 @@ function outputChangelog (argv, cb) {
 
 function handledExec (argv, cmd, errorCb, successCb) {
   // Exec given cmd and handle possible errors
-
   exec(cmd, function (err, stdout, stderr) {
     // If exec returns content in stderr, but no error, print it as a warning
     // If exec returns an error, print it and exit with return code 1
@@ -178,14 +203,19 @@ function commit (argv, newVersion, cb) {
   var msg = 'committing %s'
   var args = [argv.infile]
   var verify = argv.verify === false || argv.n ? '--no-verify ' : ''
-  if (!argv.firstRelease) {
-    msg += ' and %s'
-    args.unshift('package.json')
-  }
+  var toAdd = ''
+  // commit any of the config files that we've updated
+  // the version # for.
+  Object.keys(configsToUpdate).forEach(function (p) {
+    if (configsToUpdate[p]) {
+      msg += ' and %s'
+      args.unshift(path.basename(p))
+      toAdd += ' ' + path.relative(process.cwd(), p)
+    }
+  })
   checkpoint(argv, msg, args)
-
-  handledExec(argv, 'git add package.json ' + argv.infile, cb, function () {
-    handledExec(argv, 'git commit ' + verify + (argv.sign ? '-S ' : '') + (argv.commitAll ? '' : ('package.json ' + argv.infile)) + ' -m "' + formatCommitMessage(argv.message, newVersion) + '"', cb, function () {
+  handledExec(argv, 'git add' + toAdd + ' ' + argv.infile, cb, function () {
+    handledExec(argv, 'git commit ' + verify + (argv.sign ? '-S ' : '') + (argv.commitAll ? '' : (argv.infile + toAdd)) + ' -m "' + formatCommitMessage(argv.message, newVersion) + '"', cb, function () {
       cb()
     })
   })


Test patch:
diff --git a/test.js b/test.js
index f7cb8cd..af217bc 100644
--- a/test.js
+++ b/test.js
@@ -49,6 +49,12 @@ function writePackageJson (version, option) {
   delete require.cache[require.resolve(path.join(process.cwd(), 'package.json'))]
 }
 
+function writeBowerJson (version, option) {
+  option = option || {}
+  var bower = objectAssign(option, { version: version })
+  fs.writeFileSync('bower.json', JSON.stringify(bower), 'utf-8')
+}
+
 function writeGitPreCommitHook () {
   fs.writeFileSync('.git/hooks/pre-commit', '#!/bin/sh\necho "precommit ran"\nexit 1', 'utf-8')
   fs.chmodSync('.git/hooks/pre-commit', '755')
@@ -152,7 +158,7 @@ describe('cli', function () {
           var captured = shell.cat('gitcapture.log').stdout.split('\n').map(function (line) {
             return line ? JSON.parse(line) : line
           })
-          captured[captured.length - 3].should.deep.equal(['commit', '-S', 'package.json', 'CHANGELOG.md', '-m', 'chore(release): 1.0.1'])
+          captured[captured.length - 3].should.deep.equal(['commit', '-S', 'CHANGELOG.md', 'package.json', '-m', 'chore(release): 1.0.1'])
           captured[captured.length - 2].should.deep.equal(['tag', '-s', 'v1.0.1', '-m', 'chore(release): 1.0.1'])
 
           unmock()
@@ -480,4 +486,22 @@ describe('standard-version', function () {
       done()
     })
   })
+
+  describe('bower.json support', function () {
+    beforeEach(function () {
+      writeBowerJson('1.0.0')
+    })
+
+    it('bumps verson # in bower.json', function (done) {
+      commit('feat: first commit')
+      shell.exec('git tag -a v1.0.0 -m "my awesome first release"')
+      commit('feat: new feature!')
+      require('./index')({silent: true}, function (err) {
+        if (err) return done(err)
+        JSON.parse(fs.readFileSync('package.json', 'utf-8')).version.should.equal('1.1.0')
+        getPackageVersion().should.equal('1.1.0')
+        done()
+      })
+    })
+  })
 })