parent
a9b0542532
commit
0ac969f584
|
@ -11,18 +11,21 @@ import path from 'node:path';
|
|||
import { spawnSync, spawn } from 'node:child_process';
|
||||
import ora from 'ora';
|
||||
|
||||
const args = process.argv.slice( 2 );
|
||||
const usage = 'Usage: pnpm cherry-pick <release_branch> <pull_request_number>. Separate pull request numbers with a comma (no space) if more than one.';
|
||||
const releaseBranch = args[ 0 ];
|
||||
const prs = args[ 1 ];
|
||||
let githubToken = '';
|
||||
let tempWooDir = '';
|
||||
let changelogsToBeDeleted = [];
|
||||
let prCommits = {};
|
||||
let githubRemoteURL = 'https';
|
||||
const args = process.argv.slice( 2 );
|
||||
const usage =
|
||||
'Usage: pnpm cherry-pick <release_branch> <pull_request_number>. Separate pull request numbers with a comma (no space) if more than one.';
|
||||
const releaseBranch = args[ 0 ];
|
||||
const prs = args[ 1 ];
|
||||
let githubToken = '';
|
||||
let tempWooDir = '';
|
||||
const changelogsToBeDeleted = [];
|
||||
const prCommits = {};
|
||||
let githubRemoteURL = 'https';
|
||||
|
||||
if ( typeof process.env.GITHUB_CHERRY_PICK_TOKEN === 'undefined' ) {
|
||||
console.error( 'A GitHub token needs to be assigned to the "GITHUB_CHERRY_PICK_TOKEN" environment variable' );
|
||||
console.error(
|
||||
'A GitHub token needs to be assigned to the "GITHUB_CHERRY_PICK_TOKEN" environment variable'
|
||||
);
|
||||
process.exit( 1 );
|
||||
}
|
||||
|
||||
|
@ -43,28 +46,32 @@ if ( typeof releaseBranch === 'undefined' || typeof prs === 'undefined' ) {
|
|||
}
|
||||
|
||||
// Accounts for multiple PRs.
|
||||
const prsArr = prs.split( ',' );
|
||||
const version = releaseBranch.replace( 'release/', '' );
|
||||
const cherryPickBranch = 'cherry-pick-' + version + '/' + prsArr.toString().replace( ',', '-' );
|
||||
githubToken = process.env.GITHUB_CHERRY_PICK_TOKEN;
|
||||
const prsArr = prs.split( ',' );
|
||||
const version = releaseBranch.replace( 'release/', '' );
|
||||
const cherryPickBranch =
|
||||
'cherry-pick-' + version + '/' + prsArr.toString().replace( ',', '-' );
|
||||
githubToken = process.env.GITHUB_CHERRY_PICK_TOKEN;
|
||||
|
||||
async function getCommitFromPrs( prsArr ) {
|
||||
let properties = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/vnd.github.v3+json',
|
||||
'Authorization': `token ${githubToken}`
|
||||
}
|
||||
};
|
||||
const properties = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.v3+json',
|
||||
Authorization: `token ${ githubToken }`,
|
||||
},
|
||||
};
|
||||
|
||||
for ( const pr of prsArr ) {
|
||||
const response = await fetch( 'https://api.github.com/repos/woocommerce/woocommerce/pulls/' + pr, properties );
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/woocommerce/woocommerce/pulls/' + pr,
|
||||
properties
|
||||
);
|
||||
|
||||
if ( response.status !== 200 ) {
|
||||
throw 'One or more of the PR reference was not found.';
|
||||
}
|
||||
|
||||
await response.json().then( data => {
|
||||
await response.json().then( ( data ) => {
|
||||
prCommits[ pr ] = data.merge_commit_sha;
|
||||
} );
|
||||
}
|
||||
|
@ -73,37 +80,41 @@ async function getCommitFromPrs( prsArr ) {
|
|||
/**
|
||||
* Checks out a branch.
|
||||
*
|
||||
* @param string branch The branch to checkout.
|
||||
* @param boolean newBranch A flag to create a new branch.
|
||||
* @param string branch The branch to checkout.
|
||||
* @param boolean newBranch A flag to create a new branch.
|
||||
* @param branch
|
||||
* @param newBranch
|
||||
*/
|
||||
function checkoutBranch( branch, newBranch = false ) {
|
||||
const spinner = ora( {
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
let output = [];
|
||||
const output = [];
|
||||
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
const response = newBranch ? spawn( 'git', [ 'checkout', '-b', branch ] ) : spawn( 'git', [ 'checkout', branch ] );
|
||||
const response = newBranch
|
||||
? spawn( 'git', [ 'checkout', '-b', branch ] )
|
||||
: spawn( 'git', [ 'checkout', branch ] );
|
||||
|
||||
response.stdout.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.stderr.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.on( 'close', ( code ) => {
|
||||
if ( `${code}` == 0 ) {
|
||||
spinner.succeed( `Switched to '${branch}'` );
|
||||
if ( `${ code }` == 0 ) {
|
||||
spinner.succeed( `Switched to '${ branch }'` );
|
||||
resolve();
|
||||
}
|
||||
|
||||
reject( `error: ${output.toString().replace( ',', "\n" )}` );
|
||||
reject( `error: ${ output.toString().replace( ',', '\n' ) }` );
|
||||
} );
|
||||
} ).catch( err => {
|
||||
} ).catch( ( err ) => {
|
||||
spinner.fail( 'Failed to switch branch' );
|
||||
throw err;
|
||||
} );
|
||||
|
@ -112,7 +123,8 @@ function checkoutBranch( branch, newBranch = false ) {
|
|||
/**
|
||||
* Create the temp directory in system temp.
|
||||
*
|
||||
* @param string path The path to create.
|
||||
* @param string path The path to create.
|
||||
* @param path
|
||||
*/
|
||||
function createDir( path ) {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
|
@ -125,7 +137,7 @@ function createDir( path ) {
|
|||
|
||||
resolve();
|
||||
} );
|
||||
} ).catch( err => {
|
||||
} ).catch( ( err ) => {
|
||||
throw err;
|
||||
} );
|
||||
}
|
||||
|
@ -133,18 +145,18 @@ function createDir( path ) {
|
|||
/**
|
||||
* Clones the WooCommerce repo into temp dir.
|
||||
*
|
||||
* @param string woodir The temporary system directory.
|
||||
* @param string woodir The temporary system directory.
|
||||
*/
|
||||
function cloneWoo() {
|
||||
const spinner = ora( {
|
||||
text: `Cloning WooCommerce into ${tempWooDir}/woocommerce`,
|
||||
text: `Cloning WooCommerce into ${ tempWooDir }/woocommerce`,
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
spinner.start();
|
||||
|
||||
let output = [];
|
||||
const output = [];
|
||||
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
let url = 'https://github.com/woocommerce/woocommerce.git';
|
||||
|
@ -156,22 +168,22 @@ function cloneWoo() {
|
|||
const response = spawn( 'git', [ 'clone', url ] );
|
||||
|
||||
response.stdout.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.stderr.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.on( 'close', ( code ) => {
|
||||
if ( `${code}` == 0 ) {
|
||||
if ( `${ code }` == 0 ) {
|
||||
spinner.succeed();
|
||||
resolve();
|
||||
}
|
||||
|
||||
reject( `error: ${output.toString().replace( ',', "\n" )}` );
|
||||
reject( `error: ${ output.toString().replace( ',', '\n' ) }` );
|
||||
} );
|
||||
} ).catch( err => {
|
||||
} ).catch( ( err ) => {
|
||||
spinner.fail( 'Fail to clone WooCommerce!' );
|
||||
throw err;
|
||||
} );
|
||||
|
@ -180,36 +192,44 @@ function cloneWoo() {
|
|||
/**
|
||||
* Cherry picks.
|
||||
*
|
||||
* @param string commit The commit hash to cherry pick.
|
||||
* @param string commit The commit hash to cherry pick.
|
||||
* @param commit
|
||||
*/
|
||||
function cherryPick( commit ) {
|
||||
const spinner = ora( {
|
||||
text: `Cherry picking ${commit}`,
|
||||
text: `Cherry picking ${ commit }`,
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
spinner.start();
|
||||
|
||||
const response = spawnSync( 'git', [ 'cherry-pick', commit ] );
|
||||
const response = spawnSync( 'git', [ 'cherry-pick', commit ], {
|
||||
encoding: 'utf-8',
|
||||
} );
|
||||
|
||||
if ( response.status == 0 ) {
|
||||
if ( response.status === 0 ) {
|
||||
spinner.succeed();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( response.stderr ) {
|
||||
if ( response.stderr.match( 'fatal: bad revision' ) || response.stderr.match( 'error: could not apply' ) ) {
|
||||
spinner.fail( `Fail cherry picking ${commit}` );
|
||||
throw `stderr: ${response.stderr}`;
|
||||
if (
|
||||
response.stderr.match( 'fatal: bad revision' ) ||
|
||||
response.stderr.match( 'error: could not apply' )
|
||||
) {
|
||||
spinner.fail( `Fail cherry picking ${ commit }` );
|
||||
console.log( response.stdout );
|
||||
throw `stderr: ${ response.stderr }`;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to change directories.
|
||||
*
|
||||
* @param string dir The directory to change to.
|
||||
* @param string dir The directory to change to.
|
||||
* @param dir
|
||||
*/
|
||||
function chdir( dir ) {
|
||||
try {
|
||||
|
@ -222,22 +242,28 @@ function chdir( dir ) {
|
|||
/**
|
||||
* Generates the changelog for readme.txt.
|
||||
*
|
||||
* @param string pr The PR to use.
|
||||
* @param string commit The commit to use.
|
||||
* @param string pr The PR to use.
|
||||
* @param string commit The commit to use.
|
||||
* @param pr
|
||||
* @param commit
|
||||
*/
|
||||
async function generateChangelog( pr, commit ) {
|
||||
let properties = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/vnd.github.v3+json'
|
||||
}
|
||||
};
|
||||
const properties = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/vnd.github.v3+json',
|
||||
},
|
||||
};
|
||||
|
||||
if ( githubToken ) {
|
||||
properties.headers.Authorization = 'token ' + githubToken;
|
||||
}
|
||||
|
||||
const response = await fetch( 'https://api.github.com/repos/woocommerce/woocommerce/commits/' + commit, properties );
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/woocommerce/woocommerce/commits/' +
|
||||
commit,
|
||||
properties
|
||||
);
|
||||
|
||||
if ( response.status !== 200 ) {
|
||||
throw 'Commit was not found.';
|
||||
|
@ -245,98 +271,134 @@ async function generateChangelog( pr, commit ) {
|
|||
|
||||
let changelogTxt = '';
|
||||
|
||||
await response.json().then( data => {
|
||||
await response.json().then( ( data ) => {
|
||||
for ( const file of data.files ) {
|
||||
if ( file.filename.match( 'plugins/woocommerce/changelog/' ) ) {
|
||||
if ( changelogsToBeDeleted.indexOf( file.filename ) === -1 ) {
|
||||
changelogsToBeDeleted.push( file.filename );
|
||||
}
|
||||
|
||||
let changelogEntry = '';
|
||||
let changelogEntry = '';
|
||||
let changelogEntryType = '';
|
||||
|
||||
fs.readFile( './' + file.filename, 'utf-8', function( err, data ) {
|
||||
if ( err ) {
|
||||
throw err;
|
||||
fs.readFile(
|
||||
'./' + file.filename,
|
||||
'utf-8',
|
||||
function ( err, data ) {
|
||||
if ( err ) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
const changelogEntryArr = data.split( '\n' );
|
||||
changelogEntryType = data.match( /Type: (.+)/i );
|
||||
changelogEntryType =
|
||||
changelogEntryType[ 1 ].charAt( 0 ).toUpperCase() +
|
||||
changelogEntryType[ 1 ].slice( 1 );
|
||||
|
||||
changelogEntry = changelogEntryArr.filter( ( el ) => {
|
||||
return (
|
||||
el !== null &&
|
||||
typeof el !== 'undefined' &&
|
||||
el !== ''
|
||||
);
|
||||
} );
|
||||
changelogEntry =
|
||||
changelogEntry[ changelogEntry.length - 1 ];
|
||||
|
||||
// Check if changelogEntry is what we want.
|
||||
if ( changelogEntry.length < 1 ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
|
||||
if ( changelogEntry.match( /significance:/i ) ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
|
||||
if ( changelogEntry.match( /type:/i ) ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
|
||||
if ( changelogEntry.match( /comment:/i ) ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
}
|
||||
|
||||
const changelogEntryArr = data.split( "\n" );
|
||||
changelogEntryType = data.match( /Type: (.+)/i );
|
||||
changelogEntryType = changelogEntryType[ 1 ].charAt( 0 ).toUpperCase() + changelogEntryType[ 1 ].slice( 1 );
|
||||
|
||||
changelogEntry = changelogEntryArr.filter( el => {
|
||||
return el !== null && typeof el !== 'undefined' && el !== '';
|
||||
} );
|
||||
changelogEntry = changelogEntry[ changelogEntry.length - 1 ];
|
||||
|
||||
// Check if changelogEntry is what we want.
|
||||
if ( changelogEntry.length < 1 ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
|
||||
if ( changelogEntry.match( /significance:/i ) ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
|
||||
if ( changelogEntry.match( /type:/i ) ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
|
||||
if ( changelogEntry.match( /comment:/i ) ) {
|
||||
changelogEntry = false;
|
||||
}
|
||||
} );
|
||||
);
|
||||
|
||||
if ( changelogEntry === false ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fs.readFile( './plugins/woocommerce/readme.txt', 'utf-8', function( err, data ) {
|
||||
if ( err ) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
const spinner = ora( {
|
||||
text: `Generating changelog entry for PR ${pr}`,
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
} );
|
||||
|
||||
spinner.start();
|
||||
|
||||
changelogTxt = data.split( "\n" );
|
||||
let isInRange = false;
|
||||
let newChangelogTxt = [];
|
||||
|
||||
for ( const line of changelogTxt ) {
|
||||
if ( isInRange === false && line === '== Changelog ==' ) {
|
||||
isInRange = true;
|
||||
}
|
||||
|
||||
if ( isInRange === true && line.match( /\*\*WooCommerce Blocks/ ) ) {
|
||||
isInRange = false;
|
||||
}
|
||||
|
||||
// Find the first match of the entry "Type".
|
||||
if ( isInRange && line.match( `\\* ${changelogEntryType} -` ) ) {
|
||||
newChangelogTxt.push( '* ' + changelogEntryType + ' - ' + changelogEntry + ` [#${pr}](https://github.com/woocommerce/woocommerce/pull/${pr})` );
|
||||
newChangelogTxt.push( line );
|
||||
isInRange = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
newChangelogTxt.push( line );
|
||||
}
|
||||
|
||||
fs.writeFile( './plugins/woocommerce/readme.txt', newChangelogTxt.join( "\n" ), err => {
|
||||
fs.readFile(
|
||||
'./plugins/woocommerce/readme.txt',
|
||||
'utf-8',
|
||||
function ( err, data ) {
|
||||
if ( err ) {
|
||||
spinner.fail( `Unable to generate the changelog entry for PR ${pr}` );
|
||||
throw err;
|
||||
}
|
||||
|
||||
spinner.succeed();
|
||||
} );
|
||||
} );
|
||||
const spinner = ora( {
|
||||
text: `Generating changelog entry for PR ${ pr }`,
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
spinner.start();
|
||||
|
||||
changelogTxt = data.split( '\n' );
|
||||
let isInRange = false;
|
||||
const newChangelogTxt = [];
|
||||
|
||||
for ( const line of changelogTxt ) {
|
||||
if (
|
||||
isInRange === false &&
|
||||
line === '== Changelog =='
|
||||
) {
|
||||
isInRange = true;
|
||||
}
|
||||
|
||||
if (
|
||||
isInRange === true &&
|
||||
line.match( /\*\*WooCommerce Blocks/ )
|
||||
) {
|
||||
isInRange = false;
|
||||
}
|
||||
|
||||
// Find the first match of the entry "Type".
|
||||
if (
|
||||
isInRange &&
|
||||
line.match( `\\* ${ changelogEntryType } -` )
|
||||
) {
|
||||
newChangelogTxt.push(
|
||||
'* ' +
|
||||
changelogEntryType +
|
||||
' - ' +
|
||||
changelogEntry +
|
||||
` [#${ pr }](https://github.com/woocommerce/woocommerce/pull/${ pr })`
|
||||
);
|
||||
newChangelogTxt.push( line );
|
||||
isInRange = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
newChangelogTxt.push( line );
|
||||
}
|
||||
|
||||
fs.writeFile(
|
||||
'./plugins/woocommerce/readme.txt',
|
||||
newChangelogTxt.join( '\n' ),
|
||||
( err ) => {
|
||||
if ( err ) {
|
||||
spinner.fail(
|
||||
`Unable to generate the changelog entry for PR ${ pr }`
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
|
||||
spinner.succeed();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
@ -349,33 +411,35 @@ async function generateChangelog( pr, commit ) {
|
|||
function deleteChangelogFiles() {
|
||||
const spinner = ora( {
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
const files = changelogsToBeDeleted.join( ' ' );
|
||||
const filesFormatted = "\n" + files.replace( ' ', "\n" );
|
||||
let output = [];
|
||||
const filesFormatted = '\n' + files.replace( ' ', '\n' );
|
||||
const output = [];
|
||||
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
const response = spawn( 'git', [ 'rm', files ], { shell: true } );
|
||||
|
||||
response.stdout.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.stderr.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.on( 'close', ( code ) => {
|
||||
if ( `${code}` == 0 ) {
|
||||
spinner.succeed( `Removed changelog files:${filesFormatted}` );
|
||||
if ( `${ code }` == 0 ) {
|
||||
spinner.succeed(
|
||||
`Removed changelog files:${ filesFormatted }`
|
||||
);
|
||||
resolve();
|
||||
}
|
||||
|
||||
reject( `error: ${output.toString().replace( ',', "\n" )}` );
|
||||
reject( `error: ${ output.toString().replace( ',', '\n' ) }` );
|
||||
} );
|
||||
} ).catch( err => {
|
||||
} ).catch( ( err ) => {
|
||||
spinner.fail( 'Fail to delete changelog files' );
|
||||
throw err;
|
||||
} );
|
||||
|
@ -384,36 +448,42 @@ function deleteChangelogFiles() {
|
|||
/**
|
||||
* Commit changes.
|
||||
*
|
||||
* @param string msg The message for the commit.
|
||||
* @param string msg The message for the commit.
|
||||
* @param msg
|
||||
*/
|
||||
function commitChanges( msg ) {
|
||||
const spinner = ora( {
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
let output = [];
|
||||
const output = [];
|
||||
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
const response = spawn( 'git', [ 'commit', '--no-verify', '-am', msg ] );
|
||||
const response = spawn( 'git', [
|
||||
'commit',
|
||||
'--no-verify',
|
||||
'-am',
|
||||
msg,
|
||||
] );
|
||||
|
||||
response.stdout.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.stderr.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.on( 'close', ( code ) => {
|
||||
if ( `${code}` == 0 ) {
|
||||
if ( `${ code }` == 0 ) {
|
||||
spinner.succeed( `Commited changes.` );
|
||||
resolve();
|
||||
}
|
||||
|
||||
reject( `error: ${output.toString().replace( ',', "\n" )}` );
|
||||
reject( `error: ${ output.toString().replace( ',', '\n' ) }` );
|
||||
} );
|
||||
} ).catch( err => {
|
||||
} ).catch( ( err ) => {
|
||||
spinner.fail( 'Fail to commit changes.' );
|
||||
throw err;
|
||||
} );
|
||||
|
@ -422,39 +492,40 @@ function commitChanges( msg ) {
|
|||
/**
|
||||
* Push the branch up to GitHub.
|
||||
*
|
||||
* @param string branch The branch to push to GitHub.
|
||||
* @param string branch The branch to push to GitHub.
|
||||
* @param branch
|
||||
*/
|
||||
function pushBranch( branch ) {
|
||||
const spinner = ora( {
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
spinner.start( `Pushing ${branch} to GitHub...` );
|
||||
spinner.start( `Pushing ${ branch } to GitHub...` );
|
||||
|
||||
let output = [];
|
||||
const output = [];
|
||||
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
const response = spawn( 'git', [ 'push', 'origin', branch ] );
|
||||
|
||||
response.stdout.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.stderr.on( 'data', ( data ) => {
|
||||
output.push( `${data}` );
|
||||
output.push( `${ data }` );
|
||||
} );
|
||||
|
||||
response.on( 'close', ( code ) => {
|
||||
if ( `${code}` == 0 ) {
|
||||
if ( `${ code }` == 0 ) {
|
||||
spinner.succeed();
|
||||
resolve();
|
||||
}
|
||||
|
||||
reject( `error: ${output.toString().replace( ',', "\n" )}` );
|
||||
reject( `error: ${ output.toString().replace( ',', '\n' ) }` );
|
||||
} );
|
||||
} ).catch( err => {
|
||||
spinner.fail( `Fail to push ${branch} up.` );
|
||||
} ).catch( ( err ) => {
|
||||
spinner.fail( `Fail to push ${ branch } up.` );
|
||||
throw err;
|
||||
} );
|
||||
}
|
||||
|
@ -462,51 +533,58 @@ function pushBranch( branch ) {
|
|||
/**
|
||||
* Create pull request on GitHub.
|
||||
*
|
||||
* @param string title The title of the PR.
|
||||
* @param string body The body content of the PR.
|
||||
* @param string head The head of the branch to use.
|
||||
* @param string base The base branch to targe against.
|
||||
* @param string title The title of the PR.
|
||||
* @param string body The body content of the PR.
|
||||
* @param string head The head of the branch to use.
|
||||
* @param string base The base branch to targe against.
|
||||
* @param title
|
||||
* @param body
|
||||
* @param head
|
||||
* @param base
|
||||
*/
|
||||
async function createPR( title, body, head, base ) {
|
||||
const spinner = ora( {
|
||||
spinner: 'bouncingBar',
|
||||
color: 'green'
|
||||
color: 'green',
|
||||
} );
|
||||
|
||||
spinner.start( `Creating pull request for ${head} on GitHub...` );
|
||||
spinner.start( `Creating pull request for ${ head } on GitHub...` );
|
||||
|
||||
const response = await fetch( 'https://api.github.com/repos/woocommerce/woocommerce/pulls', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/vnd.github.v3+json',
|
||||
'Authorization': `token ${githubToken}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify( {
|
||||
"title": title,
|
||||
"body": body,
|
||||
"head": head,
|
||||
"base": base
|
||||
} )
|
||||
} );
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/woocommerce/woocommerce/pulls',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.v3+json',
|
||||
Authorization: `token ${ githubToken }`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify( {
|
||||
title,
|
||||
body,
|
||||
head,
|
||||
base,
|
||||
} ),
|
||||
}
|
||||
);
|
||||
|
||||
if ( response.status !== 201 ) {
|
||||
throw 'Fail to create PR on GitHub.';
|
||||
}
|
||||
|
||||
return await response.json().then( data => {
|
||||
return await response.json().then( ( data ) => {
|
||||
spinner.succeed();
|
||||
return {
|
||||
"url": data.url,
|
||||
"number": data.number
|
||||
}
|
||||
url: data.url,
|
||||
number: data.number,
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
( async function() {
|
||||
( async function () {
|
||||
try {
|
||||
// Creates a temp directory to work with.
|
||||
await createDir( path.join( os.tmpdir(), 'woo-cherry-pick-') );
|
||||
await createDir( path.join( os.tmpdir(), 'woo-cherry-pick-' ) );
|
||||
|
||||
// Gets the commits from GitHub based on the PRs passed in.
|
||||
await getCommitFromPrs( prsArr );
|
||||
|
@ -523,23 +601,24 @@ async function createPR( title, body, head, base ) {
|
|||
// This checks out a new branch based on the release branch.
|
||||
await checkoutBranch( cherryPickBranch, true );
|
||||
|
||||
let cherryPickPRBody = "This PR cherry-picks the following PRs into the release branch:\n";
|
||||
let cherryPickPRBody =
|
||||
'This PR cherry-picks the following PRs into the release branch:\n';
|
||||
|
||||
for ( const pr of Object.keys( prCommits ) ) {
|
||||
cherryPickPRBody = `${cherryPickPRBody}` + `* #${pr}` + "\n";
|
||||
cherryPickPRBody = `${ cherryPickPRBody }` + `* #${ pr }` + '\n';
|
||||
cherryPick( prCommits[ pr ] );
|
||||
await generateChangelog( pr, prCommits[ pr ] );
|
||||
await generateChangelog( pr, prCommits[ pr ] );
|
||||
}
|
||||
|
||||
// Deletes the changelog files from the release branch.
|
||||
await deleteChangelogFiles();
|
||||
|
||||
await commitChanges( `Prep for cherry pick ${prsArr.toString()}` );
|
||||
await commitChanges( `Prep for cherry pick ${ prsArr.toString() }` );
|
||||
|
||||
await pushBranch( cherryPickBranch );
|
||||
|
||||
const cherryPickPR = await createPR(
|
||||
`Prep for cherry pick ${prsArr.toString()}`,
|
||||
`Prep for cherry pick ${ prsArr.toString() }`,
|
||||
cherryPickPRBody,
|
||||
cherryPickBranch,
|
||||
releaseBranch
|
||||
|
@ -547,21 +626,25 @@ async function createPR( title, body, head, base ) {
|
|||
|
||||
await checkoutBranch( 'trunk' );
|
||||
|
||||
const deleteChangelogBranch = `delete-changelogs/${prsArr.toString().replace( ',', '-' )}`;
|
||||
const deleteChangelogBranch = `delete-changelogs/${ prsArr
|
||||
.toString()
|
||||
.replace( ',', '-' ) }`;
|
||||
|
||||
// This checks out a new branch based on the trunk branch.
|
||||
await checkoutBranch( `${deleteChangelogBranch}`, true );
|
||||
await checkoutBranch( `${ deleteChangelogBranch }`, true );
|
||||
|
||||
// Deletes the changelog files from the trunk branch.
|
||||
await deleteChangelogFiles();
|
||||
|
||||
await commitChanges( `Delete changelog files for ${prsArr.toString()}` );
|
||||
await commitChanges(
|
||||
`Delete changelog files for ${ prsArr.toString() }`
|
||||
);
|
||||
|
||||
await pushBranch( `${deleteChangelogBranch}` );
|
||||
await pushBranch( `${ deleteChangelogBranch }` );
|
||||
|
||||
const deleteChangelogsPR = await createPR(
|
||||
`Delete changelog files based on PR ${cherryPickPR.number}`,
|
||||
`Delete changelog files based on PR #${cherryPickPR.number}`,
|
||||
`Delete changelog files based on PR ${ cherryPickPR.number }`,
|
||||
`Delete changelog files based on PR #${ cherryPickPR.number }`,
|
||||
deleteChangelogBranch,
|
||||
'trunk'
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue