From 6330c3acd0b68702737e9718179d33351aa69fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Mon, 18 Dec 2023 10:07:22 +0100 Subject: [PATCH 01/15] feat(packages/sui-mono): improve performance --- packages/sui-mono/bin/sui-mono-release.js | 10 ++++++++++ packages/sui-mono/package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 05011b657..5c5e7c685 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -72,8 +72,11 @@ const releasePackage = async ({pkg, code, skipCi} = {}) => { const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) const {private: isPrivatePackage, config: localPackageConfig} = getPackageJson(cwd, true) + console.time('performance') await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) + console.timeLog('performance') await exec(`git add ${path.join(cwd, 'package.json')}`, {cwd}) + console.timeLog('performance') const {version} = getPackageJson(cwd, true) @@ -82,17 +85,24 @@ const releasePackage = async ({pkg, code, skipCi} = {}) => { const skipCiSuffix = skipCi ? ' [skip ci]' : '' const commitMsg = `release(${packageScope}): v${version}${skipCiSuffix}` await exec(`git commit -m "${commitMsg}"`, {cwd}) + console.timeLog('performance') await exec(`${suiMonoBinPath} changelog ${cwd}`, {cwd}) + console.timeLog('performance') await exec(`git add ${path.join(cwd, changelogFilename)}`, {cwd}) + console.timeLog('performance') await exec(`git commit --amend --no-verify --no-edit`, {cwd}) + console.timeLog('performance') await exec(`git tag -a ${tagPrefix}${version} -m "v${version}"`, {cwd}) + console.timeLog('performance') if (!isPrivatePackage) { const publishAccess = getPublishAccess({localPackageConfig}) await exec(`npm publish --access=${publishAccess}`, {cwd}) } + + console.timeEnd('performance') } const checkIsMasterBranchActive = async () => { diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index b921aa710..18897dc66 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -1,6 +1,6 @@ { "name": "@s-ui/mono", - "version": "2.42.0", + "version": "2.42.0-beta.0", "description": "Commit and release manager", "main": "index.js", "bin": { From f14e2c75c981f0843887364bde64cfdb45d06d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Mon, 18 Dec 2023 10:22:08 +0100 Subject: [PATCH 02/15] feat(packages/sui-mono): publish parallelization --- packages/sui-mono/bin/sui-mono-release.js | 6 ++---- packages/sui-mono/package.json | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 5c5e7c685..783c37e91 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -163,9 +163,7 @@ checkShouldRelease() const packagesToRelease = releasesByPackages({status}).filter(({code}) => code !== 0) - for (const pkg of packagesToRelease) { - await releasePackage({...pkg, skipCi}) - } + await Promise.all(packagesToRelease.map(pkg => releasePackage({...pkg, skipCi}))) if (packagesToRelease.length > 0) { if (lock) { @@ -176,7 +174,7 @@ checkShouldRelease() await exec('git commit -m "chore(Root): update package-lock.json [skip ci]" --no-verify') } - await exec('git push -f --tags origin HEAD') + await exec('git push -f --tags origin HEAD --no-verify') } console.log(`[sui-mono release] ${packagesToRelease.length} packages released`) diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index 18897dc66..18efea7ef 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -1,6 +1,6 @@ { "name": "@s-ui/mono", - "version": "2.42.0-beta.0", + "version": "2.42.0-beta.1", "description": "Commit and release manager", "main": "index.js", "bin": { From df6d0ba674613ef1be3948554a7ebf7c336ed771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Mon, 18 Dec 2023 10:54:28 +0100 Subject: [PATCH 03/15] feat(packages/sui-mono): update parallel mono --- packages/sui-mono/bin/sui-mono-release.js | 35 ++++++++++++++--------- packages/sui-mono/package.json | 2 +- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 783c37e91..80a8c8c20 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -64,19 +64,20 @@ const releasesByPackages = ({status}) => { .map(scope => scopeMapper({scope, status})) } -const releasePackage = async ({pkg, code, skipCi} = {}) => { +const bump = async ({pkg, code} = {}) => { + const isMonoPackage = checkIsMonoPackage() + const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) + await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) +} + +const commit = async ({pkg, skipCi} = {}) => { const isMonoPackage = checkIsMonoPackage() const tagPrefix = isMonoPackage ? '' : `${pkg}-` const packageScope = isMonoPackage ? 'Root' : pkg.replace(path.sep, '/') const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) - const {private: isPrivatePackage, config: localPackageConfig} = getPackageJson(cwd, true) - console.time('performance') - await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) - console.timeLog('performance') await exec(`git add ${path.join(cwd, 'package.json')}`, {cwd}) - console.timeLog('performance') const {version} = getPackageJson(cwd, true) @@ -85,24 +86,24 @@ const releasePackage = async ({pkg, code, skipCi} = {}) => { const skipCiSuffix = skipCi ? ' [skip ci]' : '' const commitMsg = `release(${packageScope}): v${version}${skipCiSuffix}` await exec(`git commit -m "${commitMsg}"`, {cwd}) - console.timeLog('performance') await exec(`${suiMonoBinPath} changelog ${cwd}`, {cwd}) - console.timeLog('performance') await exec(`git add ${path.join(cwd, changelogFilename)}`, {cwd}) - console.timeLog('performance') await exec(`git commit --amend --no-verify --no-edit`, {cwd}) - console.timeLog('performance') await exec(`git tag -a ${tagPrefix}${version} -m "v${version}"`, {cwd}) - console.timeLog('performance') +} + +const publish = async ({pkg} = {}) => { + const isMonoPackage = checkIsMonoPackage() + + const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) + const {private: isPrivatePackage, config: localPackageConfig} = getPackageJson(cwd, true) if (!isPrivatePackage) { const publishAccess = getPublishAccess({localPackageConfig}) await exec(`npm publish --access=${publishAccess}`, {cwd}) } - - console.timeEnd('performance') } const checkIsMasterBranchActive = async () => { @@ -163,7 +164,13 @@ checkShouldRelease() const packagesToRelease = releasesByPackages({status}).filter(({code}) => code !== 0) - await Promise.all(packagesToRelease.map(pkg => releasePackage({...pkg, skipCi}))) + await Promise.all(packagesToRelease.map(pkg => bump({...pkg, skipCi}))) + + for (const pkg of packagesToRelease) { + await commit({...pkg, skipCi}) + } + + await Promise.all(packagesToRelease.map(pkg => publish({...pkg, skipCi}))) if (packagesToRelease.length > 0) { if (lock) { diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index 18efea7ef..7c6084bc6 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -1,6 +1,6 @@ { "name": "@s-ui/mono", - "version": "2.42.0-beta.1", + "version": "2.42.0-beta.2", "description": "Commit and release manager", "main": "index.js", "bin": { From fabea432ce041ca83e527f1b549b57786773752c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Tue, 19 Dec 2023 08:33:07 +0100 Subject: [PATCH 04/15] feat(packages/sui-mono): update cwd --- packages/sui-mono/bin/sui-mono-release.js | 24 ++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 80a8c8c20..1d4fc4606 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -64,18 +64,22 @@ const releasesByPackages = ({status}) => { .map(scope => scopeMapper({scope, status})) } -const bump = async ({pkg, code} = {}) => { +const getCwd = ({pkg}) => { const isMonoPackage = checkIsMonoPackage() - const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) - await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) + return isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) } -const commit = async ({pkg, skipCi} = {}) => { +const bump = ({pkg, code}) => { + const cwd = getCwd({pkg}) + return exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) +} + +const commit = async ({pkg, skipCi}) => { const isMonoPackage = checkIsMonoPackage() const tagPrefix = isMonoPackage ? '' : `${pkg}-` const packageScope = isMonoPackage ? 'Root' : pkg.replace(path.sep, '/') - const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) + const cwd = getCwd({pkg}) await exec(`git add ${path.join(cwd, 'package.json')}`, {cwd}) @@ -94,10 +98,8 @@ const commit = async ({pkg, skipCi} = {}) => { await exec(`git tag -a ${tagPrefix}${version} -m "v${version}"`, {cwd}) } -const publish = async ({pkg} = {}) => { - const isMonoPackage = checkIsMonoPackage() - - const cwd = isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) +const publish = async ({pkg}) => { + const cwd = getCwd({pkg}) const {private: isPrivatePackage, config: localPackageConfig} = getPackageJson(cwd, true) if (!isPrivatePackage) { @@ -164,13 +166,13 @@ checkShouldRelease() const packagesToRelease = releasesByPackages({status}).filter(({code}) => code !== 0) - await Promise.all(packagesToRelease.map(pkg => bump({...pkg, skipCi}))) + await Promise.all(packagesToRelease.map(pkg => bump(pkg))) for (const pkg of packagesToRelease) { await commit({...pkg, skipCi}) } - await Promise.all(packagesToRelease.map(pkg => publish({...pkg, skipCi}))) + await Promise.all(packagesToRelease.map(pkg => publish(pkg))) if (packagesToRelease.length > 0) { if (lock) { From 55702cc92db4b83aea2be876cd690e9b64185620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Tue, 19 Dec 2023 08:38:23 +0100 Subject: [PATCH 05/15] feat(packages/sui-mono): update version --- packages/sui-mono/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index 7c6084bc6..b921aa710 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -1,6 +1,6 @@ { "name": "@s-ui/mono", - "version": "2.42.0-beta.2", + "version": "2.42.0", "description": "Commit and release manager", "main": "index.js", "bin": { From 8b8afe387f3e8f9268e9c0b7038217cbefd27d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Thu, 28 Dec 2023 09:54:32 +0100 Subject: [PATCH 06/15] feat(packages/sui-mono): update changelog creation --- packages/sui-mono/bin/sui-mono-changelog.js | 40 +- packages/sui-mono/bin/sui-mono-release.js | 21 +- packages/sui-mono/hosts/bitbucket.json | 19 + packages/sui-mono/hosts/github.json | 6 + packages/sui-mono/hosts/gitlab.json | 6 + packages/sui-mono/package.json | 19 +- .../sui-mono/src/conventional-changelog.js | 152 +++++++ packages/sui-mono/src/merge-config.js | 374 ++++++++++++++++++ packages/sui-mono/src/tags.js | 49 +++ 9 files changed, 657 insertions(+), 29 deletions(-) create mode 100644 packages/sui-mono/hosts/bitbucket.json create mode 100644 packages/sui-mono/hosts/github.json create mode 100644 packages/sui-mono/hosts/gitlab.json create mode 100644 packages/sui-mono/src/conventional-changelog.js create mode 100644 packages/sui-mono/src/merge-config.js create mode 100644 packages/sui-mono/src/tags.js diff --git a/packages/sui-mono/bin/sui-mono-changelog.js b/packages/sui-mono/bin/sui-mono-changelog.js index c4677e3c7..e551b00b5 100644 --- a/packages/sui-mono/bin/sui-mono-changelog.js +++ b/packages/sui-mono/bin/sui-mono-changelog.js @@ -2,8 +2,10 @@ const program = require('commander') const fs = require('fs') const path = require('path') -const conventionalChangelog = require('conventional-changelog') + +const conventionalChangelog = require('../src/conventional-changelog.js') const {checkIsMonoPackage, getWorkspaces, getChangelogFilename} = require('../src/config.js') +const {fetchTags} = require('../src/tags.js') program .usage(' ') @@ -28,7 +30,7 @@ const folders = program.args.length ? program.args : getWorkspaces() const changelogOptions = { preset: 'angular', append: false, - releaseCount: 0, + releaseCount: 1, outputUnreleased: false, transform: (commit, cb) => { if (commit.type === 'release') { @@ -56,20 +58,30 @@ function generateChangelog(folder) { return new Promise((resolve, reject) => { const gitRawCommitsOpts = {path: folder} const outputFile = path.join(folder, CHANGELOG_NAME) - const output = fs.createWriteStream(path.join(outputFile)) + const title = '# CHANGELOG' + const content = fs.readFileSync(outputFile, 'utf8') + const output = fs.createWriteStream(outputFile) + + const name = getWorkspaces().find(path => folder.includes(path)) + const promise = name ? fetchTags(name) : Promise.resolve() + let chunkCount = 0 - return conventionalChangelog(changelogOptions, {}, gitRawCommitsOpts) - .on('data', chunk => { - // First chunk is always an empty release - if (!chunkCount++) output.write('# CHANGELOG\n\n') - output.write(chunk) - }) - .on('end', () => output.end(() => resolve(outputFile))) - .on('error', error => { - output.destroy(error) - reject(error) - }) + return promise.then(tags => { + return conventionalChangelog({...changelogOptions, gitSemverTags: tags}, {}, gitRawCommitsOpts) + .on('data', chunk => { + if (!chunkCount++) output.write(`${title}\n\n`) + output.write(chunk) + }) + .on('end', () => { + output.write(chunkCount > 0 ? content.replace(title, '').trim() : content) + output.end(() => resolve(outputFile)) + }) + .on('error', error => { + output.destroy(error) + reject(error) + }) + }) }) } diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 1d4fc4606..525edb049 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -69,30 +69,29 @@ const getCwd = ({pkg}) => { return isMonoPackage ? BASE_DIR : path.join(process.cwd(), pkg) } -const bump = ({pkg, code}) => { +const commit = async ({pkg, code, skipCi}) => { + const isMonoPackage = checkIsMonoPackage() const cwd = getCwd({pkg}) - return exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) -} -const commit = async ({pkg, skipCi}) => { - const isMonoPackage = checkIsMonoPackage() - const tagPrefix = isMonoPackage ? '' : `${pkg}-` + const {version, name} = getPackageJson(cwd, true) + + const tagPrefix = isMonoPackage ? '' : `${name}@` const packageScope = isMonoPackage ? 'Root' : pkg.replace(path.sep, '/') - const cwd = getCwd({pkg}) + await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) await exec(`git add ${path.join(cwd, 'package.json')}`, {cwd}) - const {version} = getPackageJson(cwd, true) - // Add [skip ci] to the commit message to avoid CI build // https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build const skipCiSuffix = skipCi ? ' [skip ci]' : '' const commitMsg = `release(${packageScope}): v${version}${skipCiSuffix}` await exec(`git commit -m "${commitMsg}"`, {cwd}) - await exec(`${suiMonoBinPath} changelog ${cwd}`, {cwd}) + await exec(`${suiMonoBinPath} changelog ${cwd}`) + await exec(`git add ${path.join(cwd, changelogFilename)}`, {cwd}) + await exec(`git commit --amend --no-verify --no-edit`, {cwd}) await exec(`git tag -a ${tagPrefix}${version} -m "v${version}"`, {cwd}) @@ -166,8 +165,6 @@ checkShouldRelease() const packagesToRelease = releasesByPackages({status}).filter(({code}) => code !== 0) - await Promise.all(packagesToRelease.map(pkg => bump(pkg))) - for (const pkg of packagesToRelease) { await commit({...pkg, skipCi}) } diff --git a/packages/sui-mono/hosts/bitbucket.json b/packages/sui-mono/hosts/bitbucket.json new file mode 100644 index 000000000..dff375d49 --- /dev/null +++ b/packages/sui-mono/hosts/bitbucket.json @@ -0,0 +1,19 @@ +{ + "issue": "issue", + "commit": "commits", + "referenceActions": [ + "close", + "closes", + "closed", + "closing", + "fix", + "fixes", + "fixed", + "fixing", + "resolve", + "resolves", + "resolved", + "resolving" + ], + "issuePrefixes": ["#"] +} diff --git a/packages/sui-mono/hosts/github.json b/packages/sui-mono/hosts/github.json new file mode 100644 index 000000000..fa7ccf955 --- /dev/null +++ b/packages/sui-mono/hosts/github.json @@ -0,0 +1,6 @@ +{ + "issue": "issues", + "commit": "commit", + "referenceActions": ["close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"], + "issuePrefixes": ["#", "gh-"] +} diff --git a/packages/sui-mono/hosts/gitlab.json b/packages/sui-mono/hosts/gitlab.json new file mode 100644 index 000000000..2563046ab --- /dev/null +++ b/packages/sui-mono/hosts/gitlab.json @@ -0,0 +1,6 @@ +{ + "issue": "issues", + "commit": "commit", + "referenceActions": ["close", "closes", "closed", "closing", "fix", "fixes", "fixed", "fixing"], + "issuePrefixes": ["#"] +} diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index b921aa710..2d4782378 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -1,6 +1,6 @@ { "name": "@s-ui/mono", - "version": "2.42.0", + "version": "2.42.0-beta.10", "description": "Commit and release manager", "main": "index.js", "bin": { @@ -10,11 +10,24 @@ "dependencies": { "@s-ui/helpers": "1", "commander": "8.3.0", - "conventional-changelog": "3.1.25", "enquirer": "2.3.6", "git-url-parse": "13.1.0", "glob": "8.0.3", - "word-wrap": "1.2.4" + "word-wrap": "1.2.4", + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" }, "repository": { "type": "git", diff --git a/packages/sui-mono/src/conventional-changelog.js b/packages/sui-mono/src/conventional-changelog.js new file mode 100644 index 000000000..146cd461c --- /dev/null +++ b/packages/sui-mono/src/conventional-changelog.js @@ -0,0 +1,152 @@ +'use strict' + +const addStream = require('add-stream') +const gitRawCommits = require('git-raw-commits') +const conventionalCommitsParser = require('conventional-commits-parser') +const conventionalChangelogWriter = require('conventional-changelog-writer') +const _ = require('lodash') +const stream = require('stream') +const through = require('through2') +const execFileSync = require('child_process').execFileSync + +const mergeConfig = require('./merge-config.js') +function conventionalChangelog(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) { + writerOpts = writerOpts || {} + + const readable = new stream.Readable({ + objectMode: writerOpts.includeDetails + }) + readable._read = function () {} + + let commitsErrorThrown = false + + let commitsStream = new stream.Readable({ + objectMode: true + }) + commitsStream._read = function () {} + + function commitsRange(from, to) { + return gitRawCommits( + _.merge({}, gitRawCommitsOpts, { + from, + to + }) + ).on('error', function (err) { + if (!commitsErrorThrown) { + setImmediate(commitsStream.emit.bind(commitsStream), 'error', err) + commitsErrorThrown = true + } + }) + } + + mergeConfig(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) + .then(function (data) { + options = data.options + context = data.context + gitRawCommitsOpts = data.gitRawCommitsOpts + parserOpts = data.parserOpts + writerOpts = data.writerOpts + gitRawExecOpts = data.gitRawExecOpts + + try { + execFileSync('git', ['rev-parse', '--verify', 'HEAD'], { + stdio: 'ignore' + }) + let reverseTags = context.gitSemverTags.slice(0).reverse() + reverseTags.push('HEAD') + + if (gitRawCommitsOpts.from) { + if (reverseTags.indexOf(gitRawCommitsOpts.from) !== -1) { + reverseTags = reverseTags.slice(reverseTags.indexOf(gitRawCommitsOpts.from)) + } else { + reverseTags = [gitRawCommitsOpts.from, 'HEAD'] + } + } + + let streams = reverseTags.map((to, i) => { + const from = i > 0 ? reverseTags[i - 1] : '' + return commitsRange(from, to) + }) + + if (gitRawCommitsOpts.from) { + streams = streams.splice(1) + } + + if (gitRawCommitsOpts.reverse) { + streams.reverse() + } + + streams + .reduce((prev, next) => next.pipe(addStream(prev))) + .on('data', function (data) { + setImmediate(commitsStream.emit.bind(commitsStream), 'data', data) + }) + .on('end', function () { + setImmediate(commitsStream.emit.bind(commitsStream), 'end') + }) + } catch (_e) { + commitsStream = gitRawCommits(gitRawCommitsOpts, gitRawExecOpts) + } + + commitsStream + .on('error', function (err) { + err.message = 'Error in git-raw-commits: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + .pipe(conventionalCommitsParser(parserOpts)) + .on('error', function (err) { + err.message = 'Error in conventional-commits-parser: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + // it would be better if `gitRawCommits` could spit out better formatted data + // so we don't need to transform here + .pipe( + through.obj(function (chunk, enc, cb) { + try { + options.transform.call(this, chunk, cb) + } catch (err) { + cb(err) + } + }) + ) + .on('error', function (err) { + err.message = 'Error in options.transform: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + .pipe(conventionalChangelogWriter(context, writerOpts)) + .on('error', function (err) { + err.message = 'Error in conventional-changelog-writer: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + .pipe( + through( + { + objectMode: writerOpts.includeDetails + }, + function (chunk, enc, cb) { + try { + readable.push(chunk) + } catch (err) { + setImmediate(function () { + throw err + }) + } + + cb() + }, + function (cb) { + readable.push(null) + + cb() + } + ) + ) + }) + .catch(function (err) { + setImmediate(readable.emit.bind(readable), 'error', err) + }) + + return readable +} + +module.exports = conventionalChangelog diff --git a/packages/sui-mono/src/merge-config.js b/packages/sui-mono/src/merge-config.js new file mode 100644 index 000000000..a7e9ab0be --- /dev/null +++ b/packages/sui-mono/src/merge-config.js @@ -0,0 +1,374 @@ +'use strict' + +const dateFormat = require('dateformat') +const getPkgRepo = require('get-pkg-repo') +const gitSemverTags = require('git-semver-tags') +const normalizePackageData = require('normalize-package-data') +const Q = require('q') +let gitRemoteOriginUrl +try { + gitRemoteOriginUrl = require('git-remote-origin-url') +} catch (err) { + gitRemoteOriginUrl = function () { + return Q.reject(err) + } +} +const readPkg = require('read-pkg') +const readPkgUp = require('read-pkg-up') +const URL = require('url').URL +const _ = require('lodash') + +const rhosts = /github|bitbucket|gitlab/i + +function semverTagsPromise(options) { + return Q.Promise(function (resolve, reject) { + if (options.gitSemverTags) { + resolve(options.gitSemverTags) + } + + gitSemverTags( + { + lernaTags: !!options.lernaPackage, + package: options.lernaPackage, + tagPrefix: options.tagPrefix, + skipUnstable: options.skipUnstable + }, + function (err, result) { + if (err) { + reject(err) + } else { + resolve(result) + } + } + ) + }) +} + +function guessNextTag(previousTag, version) { + if (previousTag) { + if (previousTag[0] === 'v' && version[0] !== 'v') { + return 'v' + version + } + + if (previousTag[0] !== 'v' && version[0] === 'v') { + return version.replace(/^v/, '') + } + + return version + } + + if (version[0] !== 'v') { + return 'v' + version + } + + return version +} + +function mergeConfig(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) { + let configPromise + let pkgPromise + + context = context || {} + gitRawCommitsOpts = gitRawCommitsOpts || {} + gitRawExecOpts = gitRawExecOpts || {} + + const rtag = + options && options.tagPrefix + ? new RegExp(`tag:\\s*[=]?${options.tagPrefix}(.+?)[,)]`, 'gi') + : /tag:\s*[v=]?(.+?)[,)]/gi + + options = _.merge( + { + pkg: { + transform: function (pkg) { + return pkg + } + }, + append: false, + releaseCount: 1, + skipUnstable: false, + debug: function () {}, + transform: function (commit, cb) { + if (_.isString(commit.gitTags)) { + const match = rtag.exec(commit.gitTags) + rtag.lastIndex = 0 + + if (match) { + commit.version = match[1] + } + } + + if (commit.committerDate) { + commit.committerDate = dateFormat(commit.committerDate, 'yyyy-mm-dd', true) + } + + cb(null, commit) + }, + lernaPackage: null + }, + options + ) + + options.warn = options.warn || options.debug + + if (options.config) { + if (_.isFunction(options.config)) { + configPromise = Q.nfcall(options.config) + } else { + configPromise = Q(options.config) + } + } + + if (options.pkg) { + if (options.pkg.path) { + pkgPromise = Q(readPkg(options.pkg.path)) + } else { + pkgPromise = Q(readPkgUp()) + } + } + + const gitRemoteOriginUrlPromise = Q(gitRemoteOriginUrl()) + + return Q.allSettled([configPromise, pkgPromise, semverTagsPromise(options), gitRemoteOriginUrlPromise]).spread( + function (configObj, pkgObj, tagsObj, gitRemoteOriginUrlObj) { + let config + let pkg + let fromTag + let repo + + let hostOpts + + let gitSemverTags = [] + + if (configPromise) { + if (configObj.state === 'fulfilled') { + config = configObj.value + } else { + options.warn('Error in config' + configObj.reason.toString()) + config = {} + } + } else { + config = {} + } + + context = _.assign(context, config.context) + + if (options.pkg) { + if (pkgObj.state === 'fulfilled') { + if (options.pkg.path) { + pkg = pkgObj.value + } else { + pkg = pkgObj.value.pkg || {} + } + + pkg = options.pkg.transform(pkg) + } else if (options.pkg.path) { + options.warn(pkgObj.reason.toString()) + } + } + + if ((!pkg || !pkg.repository || !pkg.repository.url) && gitRemoteOriginUrlObj.state === 'fulfilled') { + pkg = pkg || {} + pkg.repository = pkg.repository || {} + pkg.repository.url = gitRemoteOriginUrlObj.value + normalizePackageData(pkg) + } + + if (pkg) { + context.version = context.version || pkg.version + + try { + repo = getPkgRepo(pkg) + } catch (err) { + repo = {} + } + + if (repo.browse) { + const browse = repo.browse() + if (!context.host) { + if (repo.domain) { + const parsedBrowse = new URL(browse) + if (parsedBrowse.origin.indexOf('//') !== -1) { + context.host = parsedBrowse.protocol + '//' + repo.domain + } else { + context.host = parsedBrowse.protocol + repo.domain + } + } else { + context.host = null + } + } + context.owner = context.owner || repo.user || '' + context.repository = context.repository || repo.project + if (repo.host && repo.project && repo.user) { + context.repoUrl = browse + } else { + context.repoUrl = context.host + } + } + + context.packageData = pkg + } + + context.version = context.version || '' + + if (tagsObj.state === 'fulfilled') { + gitSemverTags = context.gitSemverTags = tagsObj.value + fromTag = gitSemverTags[options.releaseCount - 1] + const lastTag = gitSemverTags[0] + + if (lastTag === context.version || lastTag === 'v' + context.version) { + if (options.outputUnreleased) { + context.version = 'Unreleased' + } else { + options.outputUnreleased = false + } + } + } + + if (!_.isBoolean(options.outputUnreleased)) { + options.outputUnreleased = true + } + + if (context.host && (!context.issue || !context.commit || !parserOpts || !parserOpts.referenceActions)) { + let type + + if (context.host) { + const match = context.host.match(rhosts) + if (match) { + type = match[0] + } + } else if (repo && repo.type) { + type = repo.type + } + + if (type) { + hostOpts = require('../hosts/' + type) + + context = _.assign( + { + issue: hostOpts.issue, + commit: hostOpts.commit + }, + context + ) + } else { + options.warn('Host: "' + context.host + '" does not exist') + hostOpts = {} + } + } else { + hostOpts = {} + } + + if (context.resetChangelog) { + fromTag = null + } + + gitRawCommitsOpts = _.assign( + { + format: '%B%n-hash-%n%H%n-gitTags-%n%d%n-committerDate-%n%ci', + from: fromTag, + merges: false, + debug: options.debug + }, + config.gitRawCommitsOpts, + gitRawCommitsOpts + ) + + if (options.append) { + gitRawCommitsOpts.reverse = gitRawCommitsOpts.reverse || true + } + + parserOpts = _.assign( + {}, + config.parserOpts, + { + warn: options.warn + }, + parserOpts + ) + + if (hostOpts.referenceActions && parserOpts) { + parserOpts.referenceActions = hostOpts.referenceActions + } + + if (_.isEmpty(parserOpts.issuePrefixes) && hostOpts.issuePrefixes) { + parserOpts.issuePrefixes = hostOpts.issuePrefixes + } + + writerOpts = _.assign( + { + finalizeContext: function (context, writerOpts, filteredCommits, keyCommit, originalCommits) { + const firstCommit = originalCommits[0] + const lastCommit = originalCommits[originalCommits.length - 1] + const firstCommitHash = firstCommit ? firstCommit.hash : null + const lastCommitHash = lastCommit ? lastCommit.hash : null + + if ((!context.currentTag || !context.previousTag) && keyCommit) { + const match = /tag:\s*(.+?)[,)]/gi.exec(keyCommit.gitTags) + const currentTag = context.currentTag + context.currentTag = currentTag || match ? match[1] : null + const index = gitSemverTags.indexOf(context.currentTag) + + // if `keyCommit.gitTags` is not a semver + if (index === -1) { + context.currentTag = currentTag || null + } else { + const previousTag = (context.previousTag = gitSemverTags[index + 1]) + + if (!previousTag) { + if (options.append) { + context.previousTag = context.previousTag || firstCommitHash + } else { + context.previousTag = context.previousTag || lastCommitHash + } + } + } + } else { + context.previousTag = context.previousTag || gitSemverTags[0] + + if (context.version === 'Unreleased') { + if (options.append) { + context.currentTag = context.currentTag || lastCommitHash + } else { + context.currentTag = context.currentTag || firstCommitHash + } + } else if (!context.currentTag) { + if (options.lernaPackage) { + context.currentTag = options.lernaPackage + '@' + context.version + } else if (options.tagPrefix) { + context.currentTag = options.tagPrefix + context.version + } else { + context.currentTag = guessNextTag(gitSemverTags[0], context.version) + } + } + } + + if (!_.isBoolean(context.linkCompare) && context.previousTag && context.currentTag) { + context.linkCompare = true + } + + return context + }, + debug: options.debug + }, + config.writerOpts, + { + reverse: options.append, + doFlush: options.outputUnreleased + }, + writerOpts + ) + + return { + options, + context, + gitRawCommitsOpts, + parserOpts, + writerOpts, + gitRawExecOpts + } + } + ) +} + +module.exports = mergeConfig diff --git a/packages/sui-mono/src/tags.js b/packages/sui-mono/src/tags.js new file mode 100644 index 000000000..722f545e8 --- /dev/null +++ b/packages/sui-mono/src/tags.js @@ -0,0 +1,49 @@ +const {exec} = require('child_process') + +function checkSUITag(tag, pkg) { + if (pkg && !tag.startsWith(`${pkg}-`)) { + return false + } + + return /^.+-[0-9]+\.[0-9]+\.[0-9]+(-.+)?$/.test(tag) +} + +function fetchTags(pkg, opts = {}) { + return new Promise((resolve, reject) => { + const regex = /tag:\s*(.+?)[,)]/gi + const cmd = 'git log --decorate --no-color --date-order' + + const options = { + maxBuffer: Infinity, + cwd: process.cwd(), + ...opts + } + + exec(cmd, options, (err, data) => { + if (err) { + reject(err) + return + } + + const tags = [] + let match + let tag + + data.split('\n').forEach(decorations => { + while ((match = regex.exec(decorations))) { + tag = match[1] + + if (checkSUITag(tag, pkg)) { + tags.push(tag) + } + } + }) + + resolve(tags) + }) + }) +} + +module.exports = { + fetchTags +} From 380a52068c590a3800ff4f1fc7629cf0e8594287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Thu, 28 Dec 2023 10:19:40 +0100 Subject: [PATCH 07/15] feat(packages/sui-mono): update broken import --- packages/sui-mono/src/check.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sui-mono/src/check.js b/packages/sui-mono/src/check.js index 60190e759..9f81c5de1 100644 --- a/packages/sui-mono/src/check.js +++ b/packages/sui-mono/src/check.js @@ -1,6 +1,6 @@ /* eslint no-console:0 */ -const conventionalChangelog = require('conventional-changelog') +const conventionalChangelog = require('./conventional-changelog.js') const {readJsonSync} = require('fs-extra') const {promisify} = require('util') From d31d0611927e47fcedda8c12044203ba90e6561e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Thu, 28 Dec 2023 10:28:55 +0100 Subject: [PATCH 08/15] feat(packages/sui-mono): update mono tag prefix --- packages/sui-mono/bin/sui-mono-release.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 525edb049..2beb6d23c 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -73,9 +73,9 @@ const commit = async ({pkg, code, skipCi}) => { const isMonoPackage = checkIsMonoPackage() const cwd = getCwd({pkg}) - const {version, name} = getPackageJson(cwd, true) + const {version} = getPackageJson(cwd, true) - const tagPrefix = isMonoPackage ? '' : `${name}@` + const tagPrefix = isMonoPackage ? '' : `${pkg}-` const packageScope = isMonoPackage ? 'Root' : pkg.replace(path.sep, '/') await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) From fc67f206c68c489703737cef789214a6cde1c1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Thu, 28 Dec 2023 10:40:28 +0100 Subject: [PATCH 09/15] feat(packages/sui-mono): update version place --- packages/sui-mono/bin/sui-mono-release.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 2beb6d23c..7d195a025 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -73,15 +73,14 @@ const commit = async ({pkg, code, skipCi}) => { const isMonoPackage = checkIsMonoPackage() const cwd = getCwd({pkg}) - const {version} = getPackageJson(cwd, true) - const tagPrefix = isMonoPackage ? '' : `${pkg}-` const packageScope = isMonoPackage ? 'Root' : pkg.replace(path.sep, '/') await exec(`npm --no-git-tag-version version ${RELEASE_CODES[code]}`, {cwd}) - await exec(`git add ${path.join(cwd, 'package.json')}`, {cwd}) + const {version} = getPackageJson(cwd, true) + // Add [skip ci] to the commit message to avoid CI build // https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build const skipCiSuffix = skipCi ? ' [skip ci]' : '' @@ -89,9 +88,7 @@ const commit = async ({pkg, code, skipCi}) => { await exec(`git commit -m "${commitMsg}"`, {cwd}) await exec(`${suiMonoBinPath} changelog ${cwd}`) - await exec(`git add ${path.join(cwd, changelogFilename)}`, {cwd}) - await exec(`git commit --amend --no-verify --no-edit`, {cwd}) await exec(`git tag -a ${tagPrefix}${version} -m "v${version}"`, {cwd}) From f631ea406a53114b7e00fd6ba5d910f7c575cfbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Thu, 28 Dec 2023 16:19:23 +0100 Subject: [PATCH 10/15] feat(packages/sui-mono): update folder matching --- packages/sui-mono/bin/sui-mono-changelog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sui-mono/bin/sui-mono-changelog.js b/packages/sui-mono/bin/sui-mono-changelog.js index e551b00b5..86a12e126 100644 --- a/packages/sui-mono/bin/sui-mono-changelog.js +++ b/packages/sui-mono/bin/sui-mono-changelog.js @@ -62,7 +62,7 @@ function generateChangelog(folder) { const content = fs.readFileSync(outputFile, 'utf8') const output = fs.createWriteStream(outputFile) - const name = getWorkspaces().find(path => folder.includes(path)) + const name = getWorkspaces().find(path => folder.endsWith(path)) const promise = name ? fetchTags(name) : Promise.resolve() let chunkCount = 0 From c18405675f36ee1e53b39dabe6e7543c70a8f01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Fri, 29 Dec 2023 10:07:40 +0100 Subject: [PATCH 11/15] feat(packages/sui-mono): update read file sync --- packages/sui-mono/bin/sui-mono-changelog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-changelog.js b/packages/sui-mono/bin/sui-mono-changelog.js index 86a12e126..fed740e0c 100644 --- a/packages/sui-mono/bin/sui-mono-changelog.js +++ b/packages/sui-mono/bin/sui-mono-changelog.js @@ -59,7 +59,7 @@ function generateChangelog(folder) { const gitRawCommitsOpts = {path: folder} const outputFile = path.join(folder, CHANGELOG_NAME) const title = '# CHANGELOG' - const content = fs.readFileSync(outputFile, 'utf8') + const content = fs.existsSync(outputFile) ? fs.readFileSync(outputFile, 'utf8') : '' const output = fs.createWriteStream(outputFile) const name = getWorkspaces().find(path => folder.endsWith(path)) @@ -74,7 +74,7 @@ function generateChangelog(folder) { output.write(chunk) }) .on('end', () => { - output.write(chunkCount > 0 ? content.replace(title, '').trim() : content) + output.write(chunkCount > 0 && content ? content.replace(title, '').trim() : content) output.end(() => resolve(outputFile)) }) .on('error', error => { From adfcd76b84fe14a9f4aaaca3b5e97924b259ee94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Fri, 29 Dec 2023 10:49:46 +0100 Subject: [PATCH 12/15] feat(packages/sui-mono): update deps --- packages/sui-mono/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index 2d4782378..b397bfd1a 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -1,6 +1,6 @@ { "name": "@s-ui/mono", - "version": "2.42.0-beta.10", + "version": "2.42.0", "description": "Commit and release manager", "main": "index.js", "bin": { @@ -17,6 +17,7 @@ "add-stream": "^1.0.0", "conventional-changelog-writer": "^5.0.0", "conventional-commits-parser": "^3.2.0", + "conventional-changelog-angular": "^5.0.12", "dateformat": "^3.0.0", "get-pkg-repo": "^4.0.0", "git-raw-commits": "^2.0.8", From 5485065cdf06f61cb95c1a133461662a4fa9b126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Fri, 29 Dec 2023 11:51:16 +0100 Subject: [PATCH 13/15] feat(packages/sui-mono): use preset --- .../src/conventional-changelog-core.js | 152 ++++++++++++++++ .../sui-mono/src/conventional-changelog.js | 163 ++---------------- 2 files changed, 171 insertions(+), 144 deletions(-) create mode 100644 packages/sui-mono/src/conventional-changelog-core.js diff --git a/packages/sui-mono/src/conventional-changelog-core.js b/packages/sui-mono/src/conventional-changelog-core.js new file mode 100644 index 000000000..146cd461c --- /dev/null +++ b/packages/sui-mono/src/conventional-changelog-core.js @@ -0,0 +1,152 @@ +'use strict' + +const addStream = require('add-stream') +const gitRawCommits = require('git-raw-commits') +const conventionalCommitsParser = require('conventional-commits-parser') +const conventionalChangelogWriter = require('conventional-changelog-writer') +const _ = require('lodash') +const stream = require('stream') +const through = require('through2') +const execFileSync = require('child_process').execFileSync + +const mergeConfig = require('./merge-config.js') +function conventionalChangelog(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) { + writerOpts = writerOpts || {} + + const readable = new stream.Readable({ + objectMode: writerOpts.includeDetails + }) + readable._read = function () {} + + let commitsErrorThrown = false + + let commitsStream = new stream.Readable({ + objectMode: true + }) + commitsStream._read = function () {} + + function commitsRange(from, to) { + return gitRawCommits( + _.merge({}, gitRawCommitsOpts, { + from, + to + }) + ).on('error', function (err) { + if (!commitsErrorThrown) { + setImmediate(commitsStream.emit.bind(commitsStream), 'error', err) + commitsErrorThrown = true + } + }) + } + + mergeConfig(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) + .then(function (data) { + options = data.options + context = data.context + gitRawCommitsOpts = data.gitRawCommitsOpts + parserOpts = data.parserOpts + writerOpts = data.writerOpts + gitRawExecOpts = data.gitRawExecOpts + + try { + execFileSync('git', ['rev-parse', '--verify', 'HEAD'], { + stdio: 'ignore' + }) + let reverseTags = context.gitSemverTags.slice(0).reverse() + reverseTags.push('HEAD') + + if (gitRawCommitsOpts.from) { + if (reverseTags.indexOf(gitRawCommitsOpts.from) !== -1) { + reverseTags = reverseTags.slice(reverseTags.indexOf(gitRawCommitsOpts.from)) + } else { + reverseTags = [gitRawCommitsOpts.from, 'HEAD'] + } + } + + let streams = reverseTags.map((to, i) => { + const from = i > 0 ? reverseTags[i - 1] : '' + return commitsRange(from, to) + }) + + if (gitRawCommitsOpts.from) { + streams = streams.splice(1) + } + + if (gitRawCommitsOpts.reverse) { + streams.reverse() + } + + streams + .reduce((prev, next) => next.pipe(addStream(prev))) + .on('data', function (data) { + setImmediate(commitsStream.emit.bind(commitsStream), 'data', data) + }) + .on('end', function () { + setImmediate(commitsStream.emit.bind(commitsStream), 'end') + }) + } catch (_e) { + commitsStream = gitRawCommits(gitRawCommitsOpts, gitRawExecOpts) + } + + commitsStream + .on('error', function (err) { + err.message = 'Error in git-raw-commits: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + .pipe(conventionalCommitsParser(parserOpts)) + .on('error', function (err) { + err.message = 'Error in conventional-commits-parser: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + // it would be better if `gitRawCommits` could spit out better formatted data + // so we don't need to transform here + .pipe( + through.obj(function (chunk, enc, cb) { + try { + options.transform.call(this, chunk, cb) + } catch (err) { + cb(err) + } + }) + ) + .on('error', function (err) { + err.message = 'Error in options.transform: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + .pipe(conventionalChangelogWriter(context, writerOpts)) + .on('error', function (err) { + err.message = 'Error in conventional-changelog-writer: ' + err.message + setImmediate(readable.emit.bind(readable), 'error', err) + }) + .pipe( + through( + { + objectMode: writerOpts.includeDetails + }, + function (chunk, enc, cb) { + try { + readable.push(chunk) + } catch (err) { + setImmediate(function () { + throw err + }) + } + + cb() + }, + function (cb) { + readable.push(null) + + cb() + } + ) + ) + }) + .catch(function (err) { + setImmediate(readable.emit.bind(readable), 'error', err) + }) + + return readable +} + +module.exports = conventionalChangelog diff --git a/packages/sui-mono/src/conventional-changelog.js b/packages/sui-mono/src/conventional-changelog.js index 146cd461c..e8acf2451 100644 --- a/packages/sui-mono/src/conventional-changelog.js +++ b/packages/sui-mono/src/conventional-changelog.js @@ -1,152 +1,27 @@ 'use strict' -const addStream = require('add-stream') -const gitRawCommits = require('git-raw-commits') -const conventionalCommitsParser = require('conventional-commits-parser') -const conventionalChangelogWriter = require('conventional-changelog-writer') -const _ = require('lodash') -const stream = require('stream') -const through = require('through2') -const execFileSync = require('child_process').execFileSync - -const mergeConfig = require('./merge-config.js') -function conventionalChangelog(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) { - writerOpts = writerOpts || {} - - const readable = new stream.Readable({ - objectMode: writerOpts.includeDetails - }) - readable._read = function () {} - - let commitsErrorThrown = false - - let commitsStream = new stream.Readable({ - objectMode: true - }) - commitsStream._read = function () {} - - function commitsRange(from, to) { - return gitRawCommits( - _.merge({}, gitRawCommitsOpts, { - from, - to - }) - ).on('error', function (err) { - if (!commitsErrorThrown) { - setImmediate(commitsStream.emit.bind(commitsStream), 'error', err) - commitsErrorThrown = true +const conventionalChangelogPresetLoader = require('conventional-changelog-preset-loader') + +const conventionalChangelogCore = require('./conventional-changelog-core.js') + +function conventionalChangelog(options, context, gitRawCommitsOpts, parserOpts, writerOpts) { + options.warn = options.warn || function () {} + + if (options.preset) { + try { + options.config = conventionalChangelogPresetLoader(options.preset) + } catch (err) { + if (typeof options.preset === 'object') { + options.warn(`Preset: "${options.preset.name}" ${err.message}`) + } else if (typeof options.preset === 'string') { + options.warn(`Preset: "${options.preset}" ${err.message}`) + } else { + options.warn(`Preset: ${err.message}`) } - }) + } } - mergeConfig(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) - .then(function (data) { - options = data.options - context = data.context - gitRawCommitsOpts = data.gitRawCommitsOpts - parserOpts = data.parserOpts - writerOpts = data.writerOpts - gitRawExecOpts = data.gitRawExecOpts - - try { - execFileSync('git', ['rev-parse', '--verify', 'HEAD'], { - stdio: 'ignore' - }) - let reverseTags = context.gitSemverTags.slice(0).reverse() - reverseTags.push('HEAD') - - if (gitRawCommitsOpts.from) { - if (reverseTags.indexOf(gitRawCommitsOpts.from) !== -1) { - reverseTags = reverseTags.slice(reverseTags.indexOf(gitRawCommitsOpts.from)) - } else { - reverseTags = [gitRawCommitsOpts.from, 'HEAD'] - } - } - - let streams = reverseTags.map((to, i) => { - const from = i > 0 ? reverseTags[i - 1] : '' - return commitsRange(from, to) - }) - - if (gitRawCommitsOpts.from) { - streams = streams.splice(1) - } - - if (gitRawCommitsOpts.reverse) { - streams.reverse() - } - - streams - .reduce((prev, next) => next.pipe(addStream(prev))) - .on('data', function (data) { - setImmediate(commitsStream.emit.bind(commitsStream), 'data', data) - }) - .on('end', function () { - setImmediate(commitsStream.emit.bind(commitsStream), 'end') - }) - } catch (_e) { - commitsStream = gitRawCommits(gitRawCommitsOpts, gitRawExecOpts) - } - - commitsStream - .on('error', function (err) { - err.message = 'Error in git-raw-commits: ' + err.message - setImmediate(readable.emit.bind(readable), 'error', err) - }) - .pipe(conventionalCommitsParser(parserOpts)) - .on('error', function (err) { - err.message = 'Error in conventional-commits-parser: ' + err.message - setImmediate(readable.emit.bind(readable), 'error', err) - }) - // it would be better if `gitRawCommits` could spit out better formatted data - // so we don't need to transform here - .pipe( - through.obj(function (chunk, enc, cb) { - try { - options.transform.call(this, chunk, cb) - } catch (err) { - cb(err) - } - }) - ) - .on('error', function (err) { - err.message = 'Error in options.transform: ' + err.message - setImmediate(readable.emit.bind(readable), 'error', err) - }) - .pipe(conventionalChangelogWriter(context, writerOpts)) - .on('error', function (err) { - err.message = 'Error in conventional-changelog-writer: ' + err.message - setImmediate(readable.emit.bind(readable), 'error', err) - }) - .pipe( - through( - { - objectMode: writerOpts.includeDetails - }, - function (chunk, enc, cb) { - try { - readable.push(chunk) - } catch (err) { - setImmediate(function () { - throw err - }) - } - - cb() - }, - function (cb) { - readable.push(null) - - cb() - } - ) - ) - }) - .catch(function (err) { - setImmediate(readable.emit.bind(readable), 'error', err) - }) - - return readable + return conventionalChangelogCore(options, context, gitRawCommitsOpts, parserOpts, writerOpts) } module.exports = conventionalChangelog From d5a872b2262c3a03164c510dc86d37e1c39c102e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Fri, 29 Dec 2023 12:54:59 +0100 Subject: [PATCH 14/15] feat(packages/sui-mono): minor fixes --- packages/sui-mono/bin/sui-mono-release.js | 6 +++--- packages/sui-mono/package.json | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 7d195a025..936808350 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -166,8 +166,6 @@ checkShouldRelease() await commit({...pkg, skipCi}) } - await Promise.all(packagesToRelease.map(pkg => publish(pkg))) - if (packagesToRelease.length > 0) { if (lock) { await exec( @@ -177,9 +175,11 @@ checkShouldRelease() await exec('git commit -m "chore(Root): update package-lock.json [skip ci]" --no-verify') } - await exec('git push -f --tags origin HEAD --no-verify') + await exec('git push --force-with-lease --tags origin HEAD --no-verify') } + await Promise.all(packagesToRelease.map(pkg => publish(pkg))) + console.log(`[sui-mono release] ${packagesToRelease.length} packages released`) }) }) diff --git a/packages/sui-mono/package.json b/packages/sui-mono/package.json index b397bfd1a..458c312b0 100644 --- a/packages/sui-mono/package.json +++ b/packages/sui-mono/package.json @@ -17,6 +17,7 @@ "add-stream": "^1.0.0", "conventional-changelog-writer": "^5.0.0", "conventional-commits-parser": "^3.2.0", + "conventional-changelog-preset-loader": "^2.3.4", "conventional-changelog-angular": "^5.0.12", "dateformat": "^3.0.0", "get-pkg-repo": "^4.0.0", From b6e14d7fa971ae01617e6e67923a5a3d3ab22e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Alvarez?= Date: Mon, 8 Jan 2024 10:56:35 +0100 Subject: [PATCH 15/15] feat(packages/sui-mono): add atomic git push --- packages/sui-mono/bin/sui-mono-release.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sui-mono/bin/sui-mono-release.js b/packages/sui-mono/bin/sui-mono-release.js index 936808350..698e5fe34 100644 --- a/packages/sui-mono/bin/sui-mono-release.js +++ b/packages/sui-mono/bin/sui-mono-release.js @@ -175,7 +175,7 @@ checkShouldRelease() await exec('git commit -m "chore(Root): update package-lock.json [skip ci]" --no-verify') } - await exec('git push --force-with-lease --tags origin HEAD --no-verify') + await exec('git push --atomic --tags origin HEAD --no-verify') } await Promise.all(packagesToRelease.map(pkg => publish(pkg)))