Skip to content

Commit 8b8afe3

Browse files
Andrés AlvarezAndrés Alvarez
authored andcommitted
feat(packages/sui-mono): update changelog creation
1 parent 55702cc commit 8b8afe3

File tree

9 files changed

+657
-29
lines changed

9 files changed

+657
-29
lines changed

packages/sui-mono/bin/sui-mono-changelog.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
const program = require('commander')
33
const fs = require('fs')
44
const path = require('path')
5-
const conventionalChangelog = require('conventional-changelog')
5+
6+
const conventionalChangelog = require('../src/conventional-changelog.js')
67
const {checkIsMonoPackage, getWorkspaces, getChangelogFilename} = require('../src/config.js')
8+
const {fetchTags} = require('../src/tags.js')
79

810
program
911
.usage('<folder1> <folder2> <etc>')
@@ -28,7 +30,7 @@ const folders = program.args.length ? program.args : getWorkspaces()
2830
const changelogOptions = {
2931
preset: 'angular',
3032
append: false,
31-
releaseCount: 0,
33+
releaseCount: 1,
3234
outputUnreleased: false,
3335
transform: (commit, cb) => {
3436
if (commit.type === 'release') {
@@ -56,20 +58,30 @@ function generateChangelog(folder) {
5658
return new Promise((resolve, reject) => {
5759
const gitRawCommitsOpts = {path: folder}
5860
const outputFile = path.join(folder, CHANGELOG_NAME)
59-
const output = fs.createWriteStream(path.join(outputFile))
61+
const title = '# CHANGELOG'
62+
const content = fs.readFileSync(outputFile, 'utf8')
63+
const output = fs.createWriteStream(outputFile)
64+
65+
const name = getWorkspaces().find(path => folder.includes(path))
66+
const promise = name ? fetchTags(name) : Promise.resolve()
67+
6068
let chunkCount = 0
6169

62-
return conventionalChangelog(changelogOptions, {}, gitRawCommitsOpts)
63-
.on('data', chunk => {
64-
// First chunk is always an empty release
65-
if (!chunkCount++) output.write('# CHANGELOG\n\n')
66-
output.write(chunk)
67-
})
68-
.on('end', () => output.end(() => resolve(outputFile)))
69-
.on('error', error => {
70-
output.destroy(error)
71-
reject(error)
72-
})
70+
return promise.then(tags => {
71+
return conventionalChangelog({...changelogOptions, gitSemverTags: tags}, {}, gitRawCommitsOpts)
72+
.on('data', chunk => {
73+
if (!chunkCount++) output.write(`${title}\n\n`)
74+
output.write(chunk)
75+
})
76+
.on('end', () => {
77+
output.write(chunkCount > 0 ? content.replace(title, '').trim() : content)
78+
output.end(() => resolve(outputFile))
79+
})
80+
.on('error', error => {
81+
output.destroy(error)
82+
reject(error)
83+
})
84+
})
7385
})
7486
}
7587

packages/sui-mono/bin/sui-mono-release.js

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,30 +69,29 @@ const getCwd = ({pkg}) => {
6969
return isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg)
7070
}
7171

72-
const bump = ({pkg, code}) => {
72+
const commit = async ({pkg, code, skipCi}) => {
73+
const isMonoPackage = checkIsMonoPackage()
7374
const cwd = getCwd({pkg})
74-
return exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd})
75-
}
7675

77-
const commit = async ({pkg, skipCi}) => {
78-
const isMonoPackage = checkIsMonoPackage()
79-
const tagPrefix = isMonoPackage ? '' : `${pkg}-`
76+
const {version, name} = getPackageJson(cwd, true)
77+
78+
const tagPrefix = isMonoPackage ? '' : `${name}@`
8079
const packageScope = isMonoPackage ? 'Root' : pkg.replace(path.sep, '/')
8180

82-
const cwd = getCwd({pkg})
81+
await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd})
8382

8483
await exec(`git add ${path.join(cwd, 'package.json')}`, {cwd})
8584

86-
const {version} = getPackageJson(cwd, true)
87-
8885
// Add [skip ci] to the commit message to avoid CI build
8986
// https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build
9087
const skipCiSuffix = skipCi ? ' [skip ci]' : ''
9188
const commitMsg = `release(${packageScope}): v${version}${skipCiSuffix}`
9289
await exec(`git commit -m "${commitMsg}"`, {cwd})
9390

94-
await exec(`${suiMonoBinPath} changelog ${cwd}`, {cwd})
91+
await exec(`${suiMonoBinPath} changelog ${cwd}`)
92+
9593
await exec(`git add ${path.join(cwd, changelogFilename)}`, {cwd})
94+
9695
await exec(`git commit --amend --no-verify --no-edit`, {cwd})
9796

9897
await exec(`git tag -a ${tagPrefix}${version} -m "v${version}"`, {cwd})
@@ -166,8 +165,6 @@ checkShouldRelease()
166165

167166
const packagesToRelease = releasesByPackages({status}).filter(({code}) => code !== 0)
168167

169-
await Promise.all(packagesToRelease.map(pkg => bump(pkg)))
170-
171168
for (const pkg of packagesToRelease) {
172169
await commit({...pkg, skipCi})
173170
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"issue": "issue",
3+
"commit": "commits",
4+
"referenceActions": [
5+
"close",
6+
"closes",
7+
"closed",
8+
"closing",
9+
"fix",
10+
"fixes",
11+
"fixed",
12+
"fixing",
13+
"resolve",
14+
"resolves",
15+
"resolved",
16+
"resolving"
17+
],
18+
"issuePrefixes": ["#"]
19+
}

packages/sui-mono/hosts/github.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"issue": "issues",
3+
"commit": "commit",
4+
"referenceActions": ["close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"],
5+
"issuePrefixes": ["#", "gh-"]
6+
}

packages/sui-mono/hosts/gitlab.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"issue": "issues",
3+
"commit": "commit",
4+
"referenceActions": ["close", "closes", "closed", "closing", "fix", "fixes", "fixed", "fixing"],
5+
"issuePrefixes": ["#"]
6+
}

packages/sui-mono/package.json

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@s-ui/mono",
3-
"version": "2.42.0",
3+
"version": "2.42.0-beta.10",
44
"description": "Commit and release manager",
55
"main": "index.js",
66
"bin": {
@@ -10,11 +10,24 @@
1010
"dependencies": {
1111
"@s-ui/helpers": "1",
1212
"commander": "8.3.0",
13-
"conventional-changelog": "3.1.25",
1413
"enquirer": "2.3.6",
1514
"git-url-parse": "13.1.0",
1615
"glob": "8.0.3",
17-
"word-wrap": "1.2.4"
16+
"word-wrap": "1.2.4",
17+
"add-stream": "^1.0.0",
18+
"conventional-changelog-writer": "^5.0.0",
19+
"conventional-commits-parser": "^3.2.0",
20+
"dateformat": "^3.0.0",
21+
"get-pkg-repo": "^4.0.0",
22+
"git-raw-commits": "^2.0.8",
23+
"git-remote-origin-url": "^2.0.0",
24+
"git-semver-tags": "^4.1.1",
25+
"lodash": "^4.17.15",
26+
"normalize-package-data": "^3.0.0",
27+
"q": "^1.5.1",
28+
"read-pkg": "^3.0.0",
29+
"read-pkg-up": "^3.0.0",
30+
"through2": "^4.0.0"
1831
},
1932
"repository": {
2033
"type": "git",
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
'use strict'
2+
3+
const addStream = require('add-stream')
4+
const gitRawCommits = require('git-raw-commits')
5+
const conventionalCommitsParser = require('conventional-commits-parser')
6+
const conventionalChangelogWriter = require('conventional-changelog-writer')
7+
const _ = require('lodash')
8+
const stream = require('stream')
9+
const through = require('through2')
10+
const execFileSync = require('child_process').execFileSync
11+
12+
const mergeConfig = require('./merge-config.js')
13+
function conventionalChangelog(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) {
14+
writerOpts = writerOpts || {}
15+
16+
const readable = new stream.Readable({
17+
objectMode: writerOpts.includeDetails
18+
})
19+
readable._read = function () {}
20+
21+
let commitsErrorThrown = false
22+
23+
let commitsStream = new stream.Readable({
24+
objectMode: true
25+
})
26+
commitsStream._read = function () {}
27+
28+
function commitsRange(from, to) {
29+
return gitRawCommits(
30+
_.merge({}, gitRawCommitsOpts, {
31+
from,
32+
to
33+
})
34+
).on('error', function (err) {
35+
if (!commitsErrorThrown) {
36+
setImmediate(commitsStream.emit.bind(commitsStream), 'error', err)
37+
commitsErrorThrown = true
38+
}
39+
})
40+
}
41+
42+
mergeConfig(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts)
43+
.then(function (data) {
44+
options = data.options
45+
context = data.context
46+
gitRawCommitsOpts = data.gitRawCommitsOpts
47+
parserOpts = data.parserOpts
48+
writerOpts = data.writerOpts
49+
gitRawExecOpts = data.gitRawExecOpts
50+
51+
try {
52+
execFileSync('git', ['rev-parse', '--verify', 'HEAD'], {
53+
stdio: 'ignore'
54+
})
55+
let reverseTags = context.gitSemverTags.slice(0).reverse()
56+
reverseTags.push('HEAD')
57+
58+
if (gitRawCommitsOpts.from) {
59+
if (reverseTags.indexOf(gitRawCommitsOpts.from) !== -1) {
60+
reverseTags = reverseTags.slice(reverseTags.indexOf(gitRawCommitsOpts.from))
61+
} else {
62+
reverseTags = [gitRawCommitsOpts.from, 'HEAD']
63+
}
64+
}
65+
66+
let streams = reverseTags.map((to, i) => {
67+
const from = i > 0 ? reverseTags[i - 1] : ''
68+
return commitsRange(from, to)
69+
})
70+
71+
if (gitRawCommitsOpts.from) {
72+
streams = streams.splice(1)
73+
}
74+
75+
if (gitRawCommitsOpts.reverse) {
76+
streams.reverse()
77+
}
78+
79+
streams
80+
.reduce((prev, next) => next.pipe(addStream(prev)))
81+
.on('data', function (data) {
82+
setImmediate(commitsStream.emit.bind(commitsStream), 'data', data)
83+
})
84+
.on('end', function () {
85+
setImmediate(commitsStream.emit.bind(commitsStream), 'end')
86+
})
87+
} catch (_e) {
88+
commitsStream = gitRawCommits(gitRawCommitsOpts, gitRawExecOpts)
89+
}
90+
91+
commitsStream
92+
.on('error', function (err) {
93+
err.message = 'Error in git-raw-commits: ' + err.message
94+
setImmediate(readable.emit.bind(readable), 'error', err)
95+
})
96+
.pipe(conventionalCommitsParser(parserOpts))
97+
.on('error', function (err) {
98+
err.message = 'Error in conventional-commits-parser: ' + err.message
99+
setImmediate(readable.emit.bind(readable), 'error', err)
100+
})
101+
// it would be better if `gitRawCommits` could spit out better formatted data
102+
// so we don't need to transform here
103+
.pipe(
104+
through.obj(function (chunk, enc, cb) {
105+
try {
106+
options.transform.call(this, chunk, cb)
107+
} catch (err) {
108+
cb(err)
109+
}
110+
})
111+
)
112+
.on('error', function (err) {
113+
err.message = 'Error in options.transform: ' + err.message
114+
setImmediate(readable.emit.bind(readable), 'error', err)
115+
})
116+
.pipe(conventionalChangelogWriter(context, writerOpts))
117+
.on('error', function (err) {
118+
err.message = 'Error in conventional-changelog-writer: ' + err.message
119+
setImmediate(readable.emit.bind(readable), 'error', err)
120+
})
121+
.pipe(
122+
through(
123+
{
124+
objectMode: writerOpts.includeDetails
125+
},
126+
function (chunk, enc, cb) {
127+
try {
128+
readable.push(chunk)
129+
} catch (err) {
130+
setImmediate(function () {
131+
throw err
132+
})
133+
}
134+
135+
cb()
136+
},
137+
function (cb) {
138+
readable.push(null)
139+
140+
cb()
141+
}
142+
)
143+
)
144+
})
145+
.catch(function (err) {
146+
setImmediate(readable.emit.bind(readable), 'error', err)
147+
})
148+
149+
return readable
150+
}
151+
152+
module.exports = conventionalChangelog

0 commit comments

Comments
 (0)