@ckeditor/ckeditor5-dev-release-tools 38.4.1 → 39.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,6 +70,7 @@ module.exports = async function publishPackages( options ) {
70
70
 
71
71
  if ( shouldPublishPackages ) {
72
72
  await executeInParallel( {
73
+ cwd,
73
74
  packagesDirectory,
74
75
  listrTask,
75
76
  taskToExecute: publishPackageOnNpmCallback,
@@ -22,8 +22,10 @@ const upath = require( 'upath' );
22
22
  * @param {Object} options
23
23
  * @param {String} options.version Target version or a range version to which all eligible dependencies will be updated.
24
24
  * Examples: `1.0.0`, `^1.0.0`, etc.
25
- * @param {Function} options.shouldUpdateVersionCallback Callback function that decides whether to update a version for a dependency.
26
- * It receives a package name as an argument and should return a boolean value.
25
+ * @param {UpdateVersionCallback} options.shouldUpdateVersionCallback Callback function that decides whether to update a version
26
+ * for a dependency. It receives a package name as an argument and should return a boolean value.
27
+ * @param {UpdateDependenciesPackagesDirectoryFilter|null} [options.packagesDirectoryFilter=null] An optional callback allowing
28
+ * filtering out directories/packages that should not be touched by the task.
27
29
  * @param {String} [options.packagesDirectory] Relative path to a location of packages to update their dependencies. If not specified,
28
30
  * only the root package is checked.
29
31
  * @param {String} [options.cwd=process.cwd()] Current working directory from which all paths will be resolved.
@@ -34,15 +36,10 @@ module.exports = async function updateDependencies( options ) {
34
36
  version,
35
37
  packagesDirectory,
36
38
  shouldUpdateVersionCallback,
39
+ packagesDirectoryFilter = null,
37
40
  cwd = process.cwd()
38
41
  } = options;
39
42
 
40
- const globOptions = {
41
- cwd,
42
- nodir: true,
43
- absolute: true
44
- };
45
-
46
43
  const globPatterns = [ 'package.json' ];
47
44
 
48
45
  if ( packagesDirectory ) {
@@ -51,7 +48,7 @@ module.exports = async function updateDependencies( options ) {
51
48
  globPatterns.push( packagesDirectoryPattern );
52
49
  }
53
50
 
54
- const pkgJsonPaths = await glob( globPatterns, globOptions );
51
+ const pkgJsonPaths = await getPackageJsonPaths( cwd, globPatterns, packagesDirectoryFilter );
55
52
 
56
53
  for ( const pkgJsonPath of pkgJsonPaths ) {
57
54
  const pkgJson = await fs.readJson( pkgJsonPath );
@@ -82,3 +79,41 @@ function updateVersion( version, callback, dependencies ) {
82
79
  }
83
80
  }
84
81
  }
82
+
83
+ /**
84
+ * @param {String} cwd
85
+ * @param {Array.<String>} globPatterns
86
+ * @param {UpdateDependenciesPackagesDirectoryFilter|null} packagesDirectoryFilter
87
+ * @returns {Promise.<Array.<String>>}
88
+ */
89
+ async function getPackageJsonPaths( cwd, globPatterns, packagesDirectoryFilter ) {
90
+ const globOptions = {
91
+ cwd,
92
+ nodir: true,
93
+ absolute: true
94
+ };
95
+
96
+ const pkgJsonPaths = await glob( globPatterns, globOptions );
97
+
98
+ if ( !packagesDirectoryFilter ) {
99
+ return pkgJsonPaths;
100
+ }
101
+
102
+ return pkgJsonPaths.filter( packagesDirectoryFilter );
103
+ }
104
+
105
+ /**
106
+ * @callback UpdateVersionCallback
107
+ *
108
+ * @param {String} packageName A package name.
109
+ *
110
+ * @returns {Boolean} Whether to update (`true`) or ignore (`false`) bumping the package version.
111
+ */
112
+
113
+ /**
114
+ * @callback UpdateDependenciesPackagesDirectoryFilter
115
+ *
116
+ * @param {String} packageJsonPath An absolute path to a `package.json` file.
117
+ *
118
+ * @returns {Boolean} Whether to include (`true`) or skip (`false`) processing the given directory/package.
119
+ */
@@ -24,24 +24,30 @@ const checkVersionAvailability = require( '../utils/checkversionavailability' );
24
24
  *
25
25
  * @param {Object} options
26
26
  * @param {String} options.version Version to store in a `package.json` file under the `version` key.
27
+ * @param {UpdateVersionsPackagesDirectoryFilter|null} [options.packagesDirectoryFilter=null] An optional callback allowing filtering out
28
+ * directories/packages that should not be touched by the task.
27
29
  * @param {String} [options.packagesDirectory] Relative path to a location of packages to update. If not specified,
28
30
  * only the root package is checked.
29
31
  * @param {String} [options.cwd=process.cwd()] Current working directory from which all paths will be resolved.
30
32
  * @returns {Promise}
31
33
  */
32
- module.exports = async function updateVersions( { packagesDirectory, version, cwd = process.cwd() } ) {
34
+ module.exports = async function updateVersions( options ) {
35
+ const {
36
+ packagesDirectory,
37
+ version,
38
+ packagesDirectoryFilter = null,
39
+ cwd = process.cwd()
40
+ } = options;
33
41
  const normalizedCwd = toUnix( cwd );
34
42
  const normalizedPackagesDir = packagesDirectory ? normalizeTrim( packagesDirectory ) : null;
35
43
 
36
44
  const globPatterns = getGlobPatterns( normalizedPackagesDir );
37
- const pkgJsonPaths = await glob( globPatterns, { cwd: normalizedCwd, absolute: true, nodir: true } );
38
- const randomPackagePath = getRandomPackagePath( pkgJsonPaths, normalizedPackagesDir );
45
+ const pkgJsonPaths = await getPackageJsonPaths( cwd, globPatterns, packagesDirectoryFilter );
39
46
 
40
- const rootPackageJson = join( normalizedCwd, 'package.json' );
41
- const rootPackageVersion = ( await fs.readJson( rootPackageJson ) ).version;
47
+ const randomPackagePath = getRandomPackagePath( pkgJsonPaths, normalizedPackagesDir );
42
48
 
43
- const randomPackageJson = join( randomPackagePath, 'package.json' );
44
- const randomPackageName = ( await fs.readJson( randomPackageJson ) ).name;
49
+ const { version: rootPackageVersion } = await readPackageJson( normalizedCwd );
50
+ const { name: randomPackageName } = await readPackageJson( randomPackagePath );
45
51
 
46
52
  checkIfVersionIsValid( version, rootPackageVersion );
47
53
 
@@ -59,6 +65,36 @@ module.exports = async function updateVersions( { packagesDirectory, version, cw
59
65
  }
60
66
  };
61
67
 
68
+ /**
69
+ * @param {String} cwd
70
+ * @param {Array.<String>} globPatterns
71
+ * @param {UpdateVersionsPackagesDirectoryFilter|null} packagesDirectoryFilter
72
+ * @returns {Promise.<Array.<String>>}
73
+ */
74
+ async function getPackageJsonPaths( cwd, globPatterns, packagesDirectoryFilter ) {
75
+ const pkgJsonPaths = await glob( globPatterns, {
76
+ cwd,
77
+ absolute: true,
78
+ nodir: true
79
+ } );
80
+
81
+ if ( !packagesDirectoryFilter ) {
82
+ return pkgJsonPaths;
83
+ }
84
+
85
+ return pkgJsonPaths.filter( packagesDirectoryFilter );
86
+ }
87
+
88
+ /**
89
+ * @param {String} packagesDirectory
90
+ * @returns {Promise.<Object>}
91
+ */
92
+ function readPackageJson( packagesDirectory ) {
93
+ const packageJsonPath = join( packagesDirectory, 'package.json' );
94
+
95
+ return fs.readJson( packageJsonPath );
96
+ }
97
+
62
98
  /**
63
99
  * @param {String|null} packagesDirectory
64
100
  * @returns {Array.<String>}
@@ -104,3 +140,11 @@ function checkIfVersionIsValid( newVersion, currentVersion ) {
104
140
  throw new Error( `Provided version ${ newVersion } must be greater than ${ currentVersion } or match pattern 0.0.0-nightly.` );
105
141
  }
106
142
  }
143
+
144
+ /**
145
+ * @callback UpdateVersionsPackagesDirectoryFilter
146
+ *
147
+ * @param {String} packageJsonPath An absolute path to a `package.json` file.
148
+ *
149
+ * @returns {Boolean} Whether to include (`true`) or skip (`false`) processing the given directory/package.
150
+ */
@@ -31,9 +31,8 @@ const WORKER_SCRIPT = upath.join( __dirname, 'parallelworker.js' );
31
31
  * @param {ListrTaskObject} [options.listrTask={}] An instance of `ListrTask`.
32
32
  * @param {AbortSignal|null} [options.signal=null] Signal to abort the asynchronous process. If not set, default AbortController is created.
33
33
  * @param {Object} [options.taskOptions=null] Optional data required by the task.
34
- * @param {Function} [options.packagesDirectoryFilter=null] A function that is executed for each found package directory to filter out those
35
- * that do not require executing a task. It should return a truthy value to keep the package and a falsy value to skip the package from
36
- * processing.
34
+ * @param {ExecuteInParallelPackagesDirectoryFilter|null} [options.packagesDirectoryFilter=null] An optional callback allowing filtering out
35
+ * directories/packages that should not be touched by the task.
37
36
  * @param {String} [options.cwd=process.cwd()] Current working directory from which all paths will be resolved.
38
37
  * @param {Number} [options.concurrency=require( 'os' ).cpus().length / 2] Number of CPUs that will execute the task.
39
38
  * @returns {Promise}
@@ -178,3 +177,11 @@ function getPackagesGroupedByThreads( packages, concurrency ) {
178
177
  *
179
178
  * @property {String} output Update the current output of the task.
180
179
  */
180
+
181
+ /**
182
+ * @callback ExecuteInParallelPackagesDirectoryFilter
183
+ *
184
+ * @param {String} directoryPath An absolute path to a directory.
185
+ *
186
+ * @returns {Boolean} Whether to include (`true`) or skip (`false`) processing the given directory.
187
+ */
@@ -9,6 +9,9 @@ const { cloneDeepWith } = require( 'lodash' );
9
9
  const utils = require( './transformcommitutils' );
10
10
  const getChangedFilesForCommit = require( './getchangedfilesforcommit' );
11
11
 
12
+ // Squash commit follows the pattern: "A pull request title (#{number})".
13
+ const SQUASH_COMMIT_REGEXP = /^[\W\w]+ \(#\d+\)$/;
14
+
12
15
  /**
13
16
  * Factory function.
14
17
  *
@@ -26,7 +29,7 @@ const getChangedFilesForCommit = require( './getchangedfilesforcommit' );
26
29
  * @param {Boolean} [options.useExplicitBreakingChangeGroups] If set on `true`, notes from parsed commits will be grouped as
27
30
  * "MINOR BREAKING CHANGES" and "MAJOR BREAKING CHANGES'. If set on `false` (by default), all breaking changes notes will be treated
28
31
  * as "BREAKING CHANGES".
29
- * @returns {Function}
32
+ * @returns {TransformCommit}
30
33
  */
31
34
  module.exports = function transformCommitFactory( options = {} ) {
32
35
  return rawCommit => {
@@ -36,11 +39,29 @@ module.exports = function transformCommitFactory( options = {} ) {
36
39
  return commit;
37
40
  }
38
41
 
39
- if ( Array.isArray( commit ) ) {
40
- return commit.flatMap( splitMultiScopeCommit );
42
+ // Single commit.
43
+ if ( !Array.isArray( commit ) ) {
44
+ return splitMultiScopeCommit( commit );
41
45
  }
42
46
 
43
- return splitMultiScopeCommit( commit );
47
+ // For a squash merge commit, the `commit` array contains an additional, invalid entry for the squash itself.
48
+ // It contains all notes that were not processed. Hence, let's remove it and copy its notes to a first valid commit.
49
+ // Also, let's update the "merge" field to display a merge commit on the screen,
50
+ // when passing the commits array through the `displayCommits()` function.
51
+ if ( isSquashMergeCommit( commit ) ) {
52
+ const firstCommit = commit.find( c => c.isPublicCommit );
53
+
54
+ if ( firstCommit ) {
55
+ const squashCommit = commit.shift();
56
+
57
+ firstCommit.notes = squashCommit.notes;
58
+ firstCommit.merge = squashCommit.header;
59
+
60
+ normalizeNotes( firstCommit );
61
+ }
62
+ }
63
+
64
+ return commit.flatMap( splitMultiScopeCommit );
44
65
  };
45
66
 
46
67
  /**
@@ -449,8 +470,28 @@ module.exports = function transformCommitFactory( options = {} ) {
449
470
  }
450
471
  } ) );
451
472
  }
473
+
474
+ /**
475
+ * @param {Array.<Commit>} commits
476
+ * @returns {Boolean}
477
+ */
478
+ function isSquashMergeCommit( commits ) {
479
+ const [ squashCommit ] = commits;
480
+
481
+ if ( squashCommit.type ) {
482
+ return false;
483
+ }
484
+
485
+ return !!squashCommit.header.match( SQUASH_COMMIT_REGEXP );
486
+ }
452
487
  };
453
488
 
489
+ /**
490
+ * @callback TransformCommit
491
+ * @param {Commit} rawCommit
492
+ * @returns {Commit|Array.<Commit>|undefined}
493
+ */
494
+
454
495
  /**
455
496
  * @typedef {Object} Commit
456
497
  *
@@ -458,7 +499,7 @@ module.exports = function transformCommitFactory( options = {} ) {
458
499
  *
459
500
  * @property {String} rawType Type of the commit without any modifications.
460
501
  *
461
- * @property {String} type Type of the commit (it can be modified).
502
+ * @property {String|null} type Type of the commit (it can be modified).
462
503
  *
463
504
  * @property {String} header First line of the commit message.
464
505
  *
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-dev-release-tools",
3
- "version": "38.4.1",
3
+ "version": "39.1.0",
4
4
  "description": "Tools used for releasing CKEditor 5 and related packages.",
5
5
  "keywords": [],
6
6
  "main": "lib/index.js",
7
7
  "dependencies": {
8
- "@ckeditor/ckeditor5-dev-utils": "^38.4.1",
8
+ "@ckeditor/ckeditor5-dev-utils": "^39.1.0",
9
9
  "@octokit/rest": "^19.0.0",
10
10
  "chalk": "^4.0.0",
11
11
  "cli-table": "^0.3.1",
@@ -28,7 +28,7 @@
28
28
  "upath": "^2.0.1"
29
29
  },
30
30
  "engines": {
31
- "node": ">=16.0.0",
31
+ "node": ">=18.0.0",
32
32
  "npm": ">=5.7.1"
33
33
  },
34
34
  "files": [