diff --git a/bin/backports.mjs b/bin/backports.mjs new file mode 100644 index 0000000000000..9bfc2c05d127d --- /dev/null +++ b/bin/backports.mjs @@ -0,0 +1,81 @@ +/** + * External dependencies + */ +import SimpleGit from 'simple-git'; +import { dirname, join as pathJoin } from 'path'; +import { fileURLToPath } from 'url'; +import { promises as fsPromises } from 'fs'; +import Octokit from '@octokit/rest'; + +/** + * Internal dependencies + */ +import { getPreviousMajorVersion } from './plugin/lib/version.js'; + +const __dirname = dirname( fileURLToPath( import.meta.url ) ); + +const simpleGit = SimpleGit( dirname( __dirname ) ); +const octokit = new Octokit(); + +const wpVersion = '6.1'; +const previousWpVersion = getPreviousMajorVersion( wpVersion ).replace( + /\.0$/, + '' +); + +async function getCommits( file ) { + const options = { + file, + from: `wp/${ previousWpVersion }`, + to: 'HEAD', + }; + const log = await simpleGit.log( options ); + return log.all; +} + +const prRegex = /\(#([0-9]+)\)$/; +const ghTreeRoot = 'https://github.com/WordPress/gutenberg/tree/trunk/'; +const ghCommitsRoot = 'https://github.com/WordPress/gutenberg/commits/trunk/'; +const backportDirectories = [ + 'lib/block-supports/', + `lib/compat/wordpress-${ wpVersion }/`, + 'lib/experimental/', +]; + +for ( const backportDir of backportDirectories ) { + console.log( `### [${ backportDir }](${ ghTreeRoot }${ backportDir })\n` ); + const files = await fsPromises.readdir( backportDir ); + for ( const file of files ) { + const path = pathJoin( backportDir, file ); + const stat = await fsPromises.stat( path ); + if ( ! stat.isFile() ) { + continue; + } + + console.log( `- [${ file }](${ ghCommitsRoot }${ path })` ); + const log = await getCommits( path ); + + const prNumbers = log.map( + ( { message } ) => message.match( prRegex )?.[ 1 ] + ); + + const authors = new Set(); + for ( const prNumber of prNumbers ) { + if ( ! prNumber ) { + continue; + } + const pr = await octokit.pulls.get( { + owner: 'WordPress', + repo: 'gutenberg', + pull_number: prNumber, + } ); + authors.add( pr.data.user.login ); + console.log( ` - #${ prNumber }` ); + } + + const byline = [ ...authors ] + .map( ( author ) => `@${ author }` ) + .join( ' ' ); + console.log( byline ); + } +} diff --git a/bin/plugin/lib/test/version.js b/bin/plugin/lib/test/version.js index b38875ccb72c0..2a5e226836583 100644 --- a/bin/plugin/lib/test/version.js +++ b/bin/plugin/lib/test/version.js @@ -1,10 +1,10 @@ /** * Internal dependencies */ -import { getNextMajorVersion } from '../version'; +import { getNextMajorVersion, getPreviousMajorVersion } from '../version'; describe( 'getNextMajorVersion', () => { - it( 'increases the minor number by default', () => { + it( 'increments the minor number by default', () => { const result = getNextMajorVersion( '7.3.4-rc.1' ); expect( result ).toBe( '7.4.0' ); @@ -16,3 +16,17 @@ describe( 'getNextMajorVersion', () => { expect( result ).toBe( '8.0.0' ); } ); } ); + +describe( 'getPreviousMajorVersion', () => { + it( 'decrements the minor number by default', () => { + const result = getPreviousMajorVersion( '7.4.0' ); + + expect( result ).toBe( '7.3.0' ); + } ); + + it( 'follows the WordPress versioning scheme', () => { + const result = getPreviousMajorVersion( '8.0.0' ); + + expect( result ).toBe( '7.9.0' ); + } ); +} ); diff --git a/bin/plugin/lib/version.js b/bin/plugin/lib/version.js index 64fefdb7ff810..83cd730759fbf 100644 --- a/bin/plugin/lib/version.js +++ b/bin/plugin/lib/version.js @@ -4,7 +4,7 @@ /** * Follow the WordPress version guidelines to compute - * the version to be used By default, increase the "minor" + * the version to be used By default, increment the "minor" * number but if we reach 9, bump to the next major. * * @param {string} version Current version. @@ -18,6 +18,23 @@ function getNextMajorVersion( version ) { return major + '.' + ( minor + 1 ) + '.0'; } +/** + * Follow the WordPress version guidelines to compute + * the version to be used. By default, decrement the "minor" + * number but if we reach 0, decrease to the next major. + * + * @param {string} version Current version. + * @return {string} Previous Major Version. + */ +function getPreviousMajorVersion( version ) { + const [ major, minor ] = version.split( '.' ).map( Number ); + if ( minor === 0 ) { + return major - 1 + '.9.0'; + } + return major + '.' + ( minor - 1 ) + '.0'; +} + module.exports = { getNextMajorVersion, + getPreviousMajorVersion, };