ut-tools
Version:
Build and Release management automation package.
250 lines (215 loc) • 6.3 kB
JavaScript
#!/usr/bin/env node
'use strict'
const addStream = require('add-stream')
const conventionalChangelog = require('conventional-changelog')
const fs = require('fs')
const meow = require('meow')
const tempfile = require('tempfile')
const _ = require('lodash')
const resolve = require('path').resolve
const cli = meow(`
Usage
conventional-changelog
Example
conventional-changelog -i CHANGELOG.md --same-file
Options
-i, --infile Read the CHANGELOG from this file
-o, --outfile Write the CHANGELOG to this file
If unspecified, it prints to stdout
-s, --same-file Outputting to the infile so you don't need to specify the same file as outfile
-p, --preset Name of the preset you want to use. Must be one of the following:
angular, atom, codemirror, conventionalcommits, ember, eslint, express, jquery or jshint
-k, --pkg A filepath of where your package.json is located
Default is the closest package.json from cwd
-a, --append Should the newer release be appended to the older release
Default: false
-r, --release-count How many releases to be generated from the latest
If 0, the whole changelog will be regenerated and the outfile will be overwritten
Default: 1
--skip-unstable If given, unstable tags will be skipped, e.g., x.x.x-alpha.1, x.x.x-rc.2
-u, --output-unreleased Output unreleased changelog
-v, --verbose Verbose output. Use this for debugging
Default: false
-n, --config A filepath of your config script
Example of a config script: https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-cli/test/fixtures/config.js
-c, --context A filepath of a json that is used to define template variables
-l, --lerna-package Generate a changelog for a specific lerna package (:pkg-name@1.0.0)
-t, --tag-prefix Tag prefix to consider when reading the tags
--commit-path Generate a changelog scoped to a specific directory
`, {
booleanDefault: undefined,
flags: {
infile: {
alias: 'i',
type: 'string'
},
outfile: {
alias: 'o',
type: 'string'
},
'same-file': {
alias: 's',
type: 'boolean'
},
preset: {
alias: 'p',
type: 'string'
},
pkg: {
alias: 'k',
type: 'string'
},
append: {
alias: 'a',
type: 'boolean'
},
'release-count': {
alias: 'r',
type: 'number'
},
'skip-unstable': {
type: 'boolean'
},
'output-unreleased': {
alias: 'u',
type: 'boolean'
},
verbose: {
alias: 'v',
type: 'boolean'
},
config: {
alias: 'n',
type: 'string'
},
context: {
alias: 'c',
type: 'string'
},
'lerna-package': {
alias: 'l',
type: 'string'
},
'tag-prefix': {
alias: 't',
type: 'string'
}
}
})
let config
const flags = cli.flags
const infile = flags.infile
let outfile = flags.outfile
let sameFile = flags.sameFile
const append = flags.append
const releaseCount = flags.releaseCount
const skipUnstable = flags.skipUnstable
if (infile && infile === outfile) {
sameFile = true
} else if (sameFile) {
if (infile) {
outfile = infile
} else {
console.error('infile must be provided if same-file flag presents.')
process.exit(1)
}
}
let options = _.omitBy({
preset: flags.preset,
pkg: {
path: flags.pkg
},
append: append,
releaseCount: releaseCount,
skipUnstable: skipUnstable,
outputUnreleased: flags.outputUnreleased,
lernaPackage: flags.lernaPackage,
tagPrefix: flags.tagPrefix
}, _.isUndefined)
if (flags.verbose) {
options.debug = console.info.bind(console)
options.warn = console.warn.bind(console)
}
let templateContext
let outStream
try {
if (flags.context) {
templateContext = require(resolve(process.cwd(), flags.context))
}
if (flags.config) {
config = require(resolve(process.cwd(), flags.config))
options.config = config
options = _.merge(options, config.options)
} else {
config = {}
}
} catch (err) {
console.error('Failed to get file. ' + err)
process.exit(1)
}
const gitRawCommitsOpts = _.merge({}, config.gitRawCommitsOpts || {})
if (flags.commitPath) gitRawCommitsOpts.path = flags.commitPath
const changelogStream = conventionalChangelog(options, templateContext, gitRawCommitsOpts, config.parserOpts, config.writerOpts)
.on('error', function (err) {
if (flags.verbose) {
console.error(err.stack)
} else {
console.error(err.toString())
}
process.exit(1)
})
function noInputFile () {
if (outfile) {
outStream = fs.createWriteStream(outfile)
} else {
outStream = process.stdout
}
changelogStream
.pipe(outStream)
}
if (infile && releaseCount !== 0) {
const readStream = fs.createReadStream(infile)
.on('error', function () {
if (flags.verbose) {
console.warn('infile does not exist.')
}
if (sameFile) {
noInputFile()
}
})
if (sameFile) {
if (options.append) {
changelogStream
.pipe(fs.createWriteStream(outfile, {
flags: 'a'
}))
} else {
const tmp = tempfile()
changelogStream
.pipe(addStream(readStream))
.pipe(fs.createWriteStream(tmp))
.on('finish', function () {
fs.createReadStream(tmp)
.pipe(fs.createWriteStream(outfile))
})
}
} else {
if (outfile) {
outStream = fs.createWriteStream(outfile)
} else {
outStream = process.stdout
}
let stream
if (options.append) {
stream = readStream
.pipe(addStream(changelogStream))
} else {
stream = changelogStream
.pipe(addStream(readStream))
}
stream
.pipe(outStream)
}
} else {
noInputFile()
}