Skip to content

Commit

Permalink
Merge pull request #654 from ckeditor/i/7492
Browse files Browse the repository at this point in the history
Fix (env): The `getCommit()` util will return a proper array with commits if the release branch in the project is other than `master`. Due to `--first-parent` flag which is used for collecting the commits, when the release branch is other than `master`, commits made on `master` could not be collected directly from the branch. Now those commits are collected in two ranges: from the last tag to the [base commit](https://git-scm.com/docs/git-merge-base) and from the base commit to HEAD and merged together. Closes ckeditor/ckeditor5#7492.

Other (env): The `generateChangelogForMonoRepository()` task supports `options.releaseBranch` that is passed directly to the `getCommit()` util. See ckeditor/ckeditor5#7492.
  • Loading branch information
mlewand committed Jul 20, 2020
2 parents 4036b6e + 8cd7ff9 commit e18db62
Show file tree
Hide file tree
Showing 3 changed files with 334 additions and 140 deletions.
Expand Up @@ -52,6 +52,8 @@ const noteInfo = `[ℹ️](${ VERSIONING_POLICY_URL }#major-and-minor-breaking-c
*
* @param {Boolean} [options.collaborationFeatures=false] Whether to add a note about collaboration features.
*
* @param {String} [options.releaseBranch='master'] A name of the branch that should be used for releasing packages.
*
* @returns {Promise}
*/
module.exports = function generateChangelogForMonoRepository( options ) {
Expand Down Expand Up @@ -96,7 +98,8 @@ module.exports = function generateChangelogForMonoRepository( options ) {
const packagesPaths = new Map();

const commitOptions = {
from: options.from ? options.from : 'v' + pkgJson.version
from: options.from ? options.from : 'v' + pkgJson.version,
releaseBranch: options.releaseBranch
};

return getCommits( transformCommit, commitOptions )
Expand Down
113 changes: 76 additions & 37 deletions packages/ckeditor5-dev-env/lib/release-tools/utils/getcommits.js
Expand Up @@ -10,56 +10,95 @@ const conventionalCommitsFilter = require( 'conventional-commits-filter' );
const gitRawCommits = require( 'git-raw-commits' );
const concat = require( 'concat-stream' );
const parserOptions = require( './parseroptions' );
const { tools } = require( '@ckeditor/ckeditor5-dev-utils' );

/**
* Returns a promise that resolves an array of commits since the last tag specified as `options.from`.
*
* @param {Function} transformCommit
* @param {Object} options
* @param {String} [options.from] A commit or tag name that will be the first param of the range of commits to collect.
* @param {String} [options.releaseBranch='master'] A name of the branch that should be used for releasing packages.
* @param {String} [options.mainBranch='master'] A name of the main branch in the repository.
* @returns {Promise.<Array.<Commit>>}
*/
module.exports = function getCommits( transformCommit, options = {} ) {
const gitRawCommitsOpts = {
format: '%B%n-hash-%n%H',
from: options.from,
merges: undefined,
firstParent: true
};
const releaseBranch = options.releaseBranch || 'master';
const mainBranch = options.mainBranch || 'master';

return new Promise( ( resolve, reject ) => {
const stream = gitRawCommits( gitRawCommitsOpts )
.on( 'error', err => {
/* istanbul ignore else */
if ( err.message.match( /'HEAD': unknown/ ) ) {
reject( new Error( 'Given repository is empty.' ) );
} else if ( err.message.match( new RegExp( `'${ options.from }\\.\\.HEAD': unknown` ) ) ) {
reject( new Error(
`Cannot find tag or commit "${ options.from }" in given repository.`
) );
} else {
reject( err );
}
} );
const currentBranch = exec( 'git rev-parse --abbrev-ref HEAD' ).trim();

stream.pipe( conventionalCommitsParser( parserOptions ) )
.pipe( concat( data => {
const commits = conventionalCommitsFilter( data )
.map( commit => transformCommit( commit ) )
.reduce( ( allCommits, commit ) => {
if ( Array.isArray( commit ) ) {
allCommits.push( ...commit );
} else {
allCommits.push( commit );
}
// Check whether current branch is the same as the release branch.
if ( currentBranch !== releaseBranch ) {
return Promise.reject( new Error(
`Expected to be checked out on the release branch ("${ releaseBranch }") instead of "${ currentBranch }". Aborting.`
) );
}

return allCommits;
}, [] )
.filter( commit => commit );
// If the release branch is the same as the main branch, we can collect all commits directly from the branch.
if ( releaseBranch === mainBranch ) {
return findCommits( { from: options.from } );
} else {
// Otherwise, (release branch is other than the main branch) we need to merge arrays of commits.
// See: https://github.com/ckeditor/ckeditor5/issues/7492.
const baseCommit = exec( `git merge-base ${ releaseBranch } ${ mainBranch }` ).trim();

stream.destroy();
const commitPromises = [
// 1. Commits from the last release and to the point where the release branch was created (the merge-base commit).
findCommits( { from: options.from, to: baseCommit } ),
// 2. Commits from the merge-base commit to HEAD.
findCommits( { from: baseCommit } )
];

return resolve( commits );
} ) );
} );
return Promise.all( commitPromises )
.then( commits => [].concat( ...commits ) );
}

function findCommits( gitRawCommitsOptions ) {
const gitRawCommitsOpts = Object.assign( {}, gitRawCommitsOptions, {
format: '%B%n-hash-%n%H',
merges: undefined,
firstParent: true
} );

return new Promise( ( resolve, reject ) => {
const stream = gitRawCommits( gitRawCommitsOpts )
.on( 'error', err => {
/* istanbul ignore else */
if ( err.message.match( /'HEAD': unknown/ ) ) {
reject( new Error( 'Given repository is empty.' ) );
} else if ( err.message.match( new RegExp( `'${ options.from }\\.\\.HEAD': unknown` ) ) ) {
reject( new Error(
`Cannot find tag or commit "${ options.from }" in given repository.`
) );
} else {
reject( err );
}
} );

stream.pipe( conventionalCommitsParser( parserOptions ) )
.pipe( concat( data => {
const commits = conventionalCommitsFilter( data )
.map( commit => transformCommit( commit ) )
.reduce( ( allCommits, commit ) => {
if ( Array.isArray( commit ) ) {
allCommits.push( ...commit );
} else {
allCommits.push( commit );
}

return allCommits;
}, [] )
.filter( commit => commit );

stream.destroy();

return resolve( commits );
} ) );
} );
}

function exec( command ) {
return tools.shExec( command, { verbosity: 'error' } );
}
};

0 comments on commit e18db62

Please sign in to comment.