Changeset 62062
- Timestamp:
- 03/19/2026 12:35:31 PM (9 days ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
Gruntfile.js (modified) (2 diffs)
-
package.json (modified) (1 diff)
-
tools/release/sync-gutenberg-packages.js (modified) (1 diff)
-
tools/release/sync-stable-blocks.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Gruntfile.js
r62055 r62062 1565 1565 ] ); 1566 1566 1567 grunt.registerTask( 'sync-gutenberg-packages', function() {1568 if ( grunt.option( 'update-browserlist' ) ) {1569 /*1570 * Updating the browserlist database is opt-in and up to the release lead.1571 *1572 * Browserlist database should be updated:1573 * - In each release cycle up until RC11574 * - If Webpack throws a warning about an outdated database1575 *1576 * It should not be updated:1577 * - After the RC11578 * - When backporting fixes to older WordPress releases.1579 *1580 * For more context, see:1581 * https://github.com/WordPress/wordpress-develop/pull/2621#discussion_r8598405151582 * https://core.trac.wordpress.org/ticket/555591583 */1584 grunt.task.run( 'browserslist:update' );1585 }1586 1587 // Install the latest version of the packages already listed in package.json.1588 grunt.task.run( 'wp-packages:update' );1589 1590 /*1591 * Install any new @wordpress packages that are now required.1592 * Update any non-@wordpress deps to the same version as required in the @wordpress packages (e.g. react 16 -> 17).1593 */1594 grunt.task.run( 'wp-packages:refresh-deps' );1595 } );1596 1597 1567 // Gutenberg integration tasks. 1598 1568 grunt.registerTask( 'gutenberg:verify', 'Verifies the installed Gutenberg version matches the expected SHA.', function() { … … 2228 2198 } ); 2229 2199 2230 grunt.registerTask( 'wp-packages:refresh-deps', 'Update version of dependencies in package.json to match the ones listed in the latest WordPress packages', function() {2231 const distTag = grunt.option('dist-tag') || 'latest';2232 grunt.log.writeln( `Updating versions of dependencies listed in package.json (--dist-tag=${distTag})` );2233 spawn( 'node', [ 'tools/release/sync-gutenberg-packages.js', `--dist-tag=${distTag}` ], {2234 cwd: __dirname,2235 stdio: 'inherit',2236 } );2237 } );2238 2239 grunt.registerTask( 'wp-packages:sync-stable-blocks', 'Refresh the PHP files referring to stable @wordpress/block-library blocks.', function() {2240 grunt.log.writeln( `Syncing stable blocks from @wordpress/block-library to src/` );2241 const { main } = require( './tools/release/sync-stable-blocks' );2242 main();2243 } );2244 2245 2200 // Patch task. 2246 2201 grunt.renameTask('patch_wordpress', 'patch'); -
trunk/package.json
r62061 r62062 143 143 "gutenberg:verify": "node tools/gutenberg/utils.js", 144 144 "gutenberg:download": "node tools/gutenberg/download.js && grunt build:gutenberg --dev", 145 "vendor:copy": "node tools/vendors/copy-vendors.js", 146 "sync-gutenberg-packages": "grunt sync-gutenberg-packages", 147 "postsync-gutenberg-packages": "grunt wp-packages:sync-stable-blocks && grunt build --dev && grunt build" 145 "vendor:copy": "node tools/vendors/copy-vendors.js" 148 146 } 149 147 } -
trunk/tools/release/sync-gutenberg-packages.js
r61009 r62062 1 /* eslint-disable no-console */2 /**3 * External dependencies4 */5 const fs = require( 'fs' );6 const spawn = require( 'cross-spawn' );7 const { zip, uniq, identity, groupBy } = require( 'lodash' );8 9 /**10 * Constants11 */12 const WORDPRESS_PACKAGES_PREFIX = '@wordpress/';13 const { getArgFromCLI } = require( `../../node_modules/@wordpress/scripts/utils` );14 const distTag = getArgFromCLI( '--dist-tag' ) || 'latest';15 16 /**17 * The main function of this task.18 *19 * It installs any missing WordPress packages, and updates the20 * mismatched dependencies versions, e.g. it would detect that Gutenberg21 * updated react from 16.0.4 to 17.0.2 and install the latter.22 */23 function main() {24 const initialPackageJSON = readJSONFile( `package.json` );25 26 // Install any missing WordPress packages:27 const missingWordPressPackages = getMissingWordPressPackages();28 if ( missingWordPressPackages.length ) {29 console.log( "The following @wordpress dependencies are missing: " );30 console.log( missingWordPressPackages );31 console.log( "Installing via npm..." );32 installPackages( missingWordPressPackages.map( name => [name, distTag] ) );33 }34 35 // Update any outdated non-WordPress packages:36 const versionMismatches = getMismatchedNonWordPressDependencies();37 if ( versionMismatches.length ) {38 console.log( "The following dependencies are outdated: " );39 console.log( versionMismatches );40 console.log( "Updating via npm..." );41 const requiredPackages = versionMismatches.map( ( { name, required } ) => [name, required] );42 installPackages( requiredPackages );43 }44 45 const finalPackageJSON = readJSONFile( "package.json" );46 outputPackageDiffReport(47 getPackageVersionDiff( initialPackageJSON, finalPackageJSON ),48 );49 process.exit( 0 );50 }51 52 /**53 * @param {string} fileName File to read.54 * @return {Object} Parsed data.55 */56 function readJSONFile( fileName ) {57 const data = fs.readFileSync( fileName, 'utf8' );58 return JSON.parse( data );59 }60 61 /**62 * Spawns npm install --save.63 *64 * @param {Array} packages List of tuples [packageName, version] to install.65 * @return {string} CLI output.66 */67 function installPackages( packages ) {68 const packagesWithVersion = packages.map(69 ( [packageName, version] ) => `${ packageName }@${ version }`,70 );71 return spawn.sync( 'npm', ['install', ...packagesWithVersion, '--save'], {72 stdio: 'inherit',73 } );74 }75 76 /**77 * Computes which @wordpress packages are required by the Gutenberg78 * dependencies that are missing from WordPress package.json.79 *80 * @return {Array} List of tuples [packageName, version].81 */82 function getMissingWordPressPackages() {83 const perPackageDeps = getPerPackageDeps();84 const currentPackages = perPackageDeps.map( ( [name] ) => name );85 86 const requiredWpPackages = uniq( perPackageDeps87 // Capture the @wordpress dependencies of our dependencies into a flat list.88 .flatMap( ( [, dependencies] ) => getWordPressPackages( { dependencies } ) )89 .sort(),90 );91 92 return requiredWpPackages.filter(93 packageName => !currentPackages.includes( packageName ) );94 }95 96 /**97 * Computes which third party packages are required by the @wordpress98 * packages, but not by the WordPress repo itself. This includes99 * both packages that are missing from package.json and any version100 * mismatches.101 *102 * @return {Array} List of objects {name, required, actual} describing version mismatches.103 */104 function getMismatchedNonWordPressDependencies() {105 // Get the installed dependencies from package-lock.json106 const currentPackageJSON = readJSONFile( "package.json" );107 const currentPackages = getWordPressPackages( currentPackageJSON );108 109 const packageLock = readJSONFile( "package-lock.json" );110 const versionConflicts = Object.entries( packageLock.packages[''].dependencies )111 .filter( ( [packageName] ) => currentPackages.includes( packageName ) )112 .flatMap( ( [, { dependencies }] ) => Object.entries( dependencies || {} ) )113 .filter( identity )114 .map( ( [name, { version }] ) => ( {115 name,116 required: version,117 actual: packageLock.dependencies[ name ].version,118 } ) )119 .filter( ( { required, actual } ) => required !== actual )120 ;121 122 // Ensure that all the conflicts can be resolved with the same version123 const unresolvableConflicts = Object.entries( groupBy( versionConflicts, ( {name} ) => name ) )124 .map( ( [name, group] ) => [name, uniq( group.map( ( { required } ) => required ) )] )125 .filter( ( [, group] ) => group.length > 1 );126 if ( unresolvableConflicts.length > 0 ) {127 console.error( "Can't resolve some conflicts automatically." );128 console.error( "Multiple required versions of the following packages were detected:" );129 console.error( unresolvableConflicts );130 process.exit( 1 );131 }132 return versionConflicts;133 }134 135 /**136 * Returns a list of dependencies of each @wordpress dependency.137 *138 * @return {Object} An object of shape {packageName: [[packageName, version]]}.139 */140 function getPerPackageDeps() {141 // Get the dependencies currently listed in the wordpress-develop package.json142 const currentPackageJSON = readJSONFile( "package.json" );143 const currentPackages = getWordPressPackages( currentPackageJSON );144 145 // Get the dependencies that the above dependencies list in their package.json.146 const deps = currentPackages147 .map( ( packageName ) => `node_modules/${ packageName }/package.json` )148 .map( ( jsonPath ) => readJSONFile( jsonPath ).dependencies );149 return zip( currentPackages, deps );150 }151 152 /**153 * Takes unserialized package.json data and returns a list of @wordpress dependencies.154 *155 * @param {Object} dependencies unserialized package.json data.156 * @return {string[]} a list of @wordpress dependencies.157 */158 function getWordPressPackages( { dependencies = {} } ) {159 return Object.keys( dependencies )160 .filter( isWordPressPackage );161 }162 163 /**164 * Returns true if packageName represents a @wordpress package.165 *166 * @param {string} packageName Package name to test.167 * @return {boolean} Is it a @wodpress package?168 */169 function isWordPressPackage( packageName ) {170 return packageName.startsWith( WORDPRESS_PACKAGES_PREFIX );171 }172 173 /**174 * Computes the dependencies difference between two unserialized175 * package JSON objects. Needed only for the final reporting.176 *177 * @param {Object} initialPackageJSON Initial package JSON data.178 * @param {Object} finalPackageJSON Final package JSON data.179 * @return {Object} Delta.180 */181 function getPackageVersionDiff( initialPackageJSON, finalPackageJSON ) {182 const diff = ['dependencies', 'devDependencies'].reduce(183 ( result, keyPackageJSON ) => {184 return Object.keys(185 finalPackageJSON[ keyPackageJSON ] || {},186 ).reduce( ( _result, dependency ) => {187 const initial =188 initialPackageJSON[ keyPackageJSON ][ dependency ];189 const final = finalPackageJSON[ keyPackageJSON ][ dependency ];190 if ( initial !== final ) {191 _result.push( { dependency, initial, final } );192 }193 return _result;194 }, result );195 },196 [],197 );198 return diff.sort( ( a, b ) => a.dependency.localeCompare( b.dependency ) );199 }200 201 /**202 * Prints the delta between two package.json files.203 *204 * @param {Object} packageDiff Delta.205 */206 function outputPackageDiffReport( packageDiff ) {207 const readableDiff =208 packageDiff209 .map( ( { dependency, initial, final } ) => {210 return `${ dependency }: ${ initial } -> ${ final }`;211 } )212 .filter( identity );213 if ( !readableDiff.length ) {214 console.log( 'No changes detected' );215 return;216 }217 console.log(218 [219 'The following package versions were changed:',220 ...readableDiff,221 ].join( '\n' ),222 );223 }224 225 main();226 227 /* eslint-enable no-console */ -
trunk/tools/release/sync-stable-blocks.js
r54406 r62062 1 /* eslint-disable no-console */2 /**3 * External dependencies4 */5 const fs = require( 'fs' );6 const path = require( 'path' );7 8 /**9 * Constants10 */11 const BLOCK_LIBRARY_SRC = 'node_modules/@wordpress/block-library/src/';12 13 const REPOSITORY_ROOT = path.dirname( path.dirname( __dirname ) );14 15 /**16 * The main function of this task.17 *18 * Refreshes the PHP files referring to stable @wordpress/block-library blocks.19 */20 function main() {21 const blocks = getStableBlocksMetadata();22 const toolWarningMessage = '// This file was autogenerated by tools/release/sync-stable-blocks.js, do not change manually!';23 24 // wp-includes/blocks/require-blocks.php25 console.log( 'Refreshing wp-includes/blocks/require-static-blocks.php...' );26 const staticBlockFolderNames = blocks27 .filter( ( metadata ) => ! isDynamic( metadata ) )28 .map( toDirectoryName )29 .sort()30 // To the block folder name statement:31 .map( dirname => ` '${ dirname }',` )32 .join( "\n" );33 34 fs.writeFileSync(35 `${ REPOSITORY_ROOT }/src/wp-includes/blocks/require-static-blocks.php`,36 `<?php37 38 ${ toolWarningMessage }39 // Returns folder names for static blocks necessary for core blocks registration.40 return array(41 ${ staticBlockFolderNames }42 );43 `,44 );45 46 // wp-includes/blocks/require-blocks.php47 console.log( 'Refreshing wp-includes/blocks/require-dynamic-blocks.php...' );48 const dynamicBlockFileRequires = blocks49 .filter( isDynamic )50 .map( toDirectoryName )51 .sort()52 // To PHP require_once statement:53 .map( dirname => `require_once ABSPATH . WPINC . '/blocks/${ dirname }.php';` )54 .join( "\n" );55 56 fs.writeFileSync(57 `${ REPOSITORY_ROOT }/src/wp-includes/blocks/require-dynamic-blocks.php`,58 `<?php59 60 ${ toolWarningMessage }61 // Requires files for dynamic blocks necessary for core blocks registration.62 ${ dynamicBlockFileRequires }63 `,64 );65 66 // tests/phpunit/includes/unregister-blocks-hooks.php67 console.log( 'Refreshing tests/phpunit/includes/unregister-blocks-hooks.php...' );68 const unregisterHooks = blocks.filter( isDynamic )69 .map( function toHookName( metadata ) {70 const php = fs.readFileSync( path.join( metadata.path, '..', 'index.php' ) ).toString();71 let hookName = php.substring( php.indexOf( "add_action( 'init', 'register_block_core_" ) );72 return hookName.split( "'" )[ 3 ];73 } )74 .sort()75 .map( function toUnregisterCall( hookName ) {76 return `remove_action( 'init', '${ hookName }' );`;77 } )78 .join( "\n" );79 80 fs.writeFileSync(81 `${ REPOSITORY_ROOT }/tests/phpunit/includes/unregister-blocks-hooks.php`,82 `<?php83 84 ${ toolWarningMessage }85 ${ unregisterHooks }86 `,87 );88 console.log( 'Done!' );89 }90 91 /**92 * Returns a list of unserialized block.json metadata of the93 * stable blocks shipped with the currently installed version94 * of the @wordpress/block-library package/95 *96 * @return {Array} List of stable blocks metadata.97 */98 function getStableBlocksMetadata() {99 return (100 fs.readdirSync( BLOCK_LIBRARY_SRC )101 .map( dirMaybe => path.join( BLOCK_LIBRARY_SRC, dirMaybe, 'block.json' ) )102 .filter( fs.existsSync )103 .map( blockJsonPath => ( {104 ...JSON.parse( fs.readFileSync( blockJsonPath ) ),105 path: blockJsonPath,106 } ) )107 .filter( metadata => (108 !( '__experimental' in metadata ) || metadata.__experimental === false109 ) )110 );111 }112 113 /**114 * Returns true if the specified metadata refers to a dynamic block.115 *116 * @param {Object} metadata Block metadata in question.117 * @return {boolean} Is it a dynamic block?118 */119 function isDynamic( metadata ) {120 return (121 fs.existsSync( path.join( metadata.path, '..', 'index.php' ) )122 );123 }124 125 /**126 * Returns a name of the directory where a given block resides.127 *128 * @param {Object} metadata Block metadata in question.129 * @return {string} Parent directory name.130 */131 function toDirectoryName( metadata ) {132 return (133 path.basename( path.dirname( metadata.path ) )134 );135 }136 137 module.exports = {138 main,139 isDynamic,140 toDirectoryName,141 getStableBlocksMetadata,142 };143 144 /* eslint-enable no-console */
Note: See TracChangeset
for help on using the changeset viewer.