@ckeditor/ckeditor5-dev-release-tools 38.3.0 → 38.4.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.
@@ -12,10 +12,13 @@
12
12
  const chalk = require( 'chalk' );
13
13
  const columns = require( 'cli-columns' );
14
14
  const { tools } = require( '@ckeditor/ckeditor5-dev-utils' );
15
+ const util = require( 'util' );
16
+ const exec = util.promisify( require( 'child_process' ).exec );
15
17
  const assertNpmAuthorization = require( '../utils/assertnpmauthorization' );
16
18
 
17
19
  /**
18
20
  * Used to switch the tags from `staging` to `latest` for specified array of packages.
21
+ * Each operation will be retried up to 3 times in case of failure.
19
22
  *
20
23
  * @param {Object} options
21
24
  * @param {String} options.npmOwner User that is authorized to release packages.
@@ -33,30 +36,29 @@ module.exports = async function reassignNpmTags( { npmOwner, version, packages }
33
36
  const counter = tools.createSpinner( 'Reassigning npm tags...', { total: packages.length } );
34
37
  counter.start();
35
38
 
36
- for ( const packageName of packages ) {
37
- const latestVersion = await exec( `npm show ${ packageName }@latest version` )
38
- .then( version => version.trim() )
39
- .catch( error => {
40
- errors.push( trimErrorMessage( error.message ) );
41
- } );
42
-
43
- if ( latestVersion === version ) {
44
- packagesSkipped.push( packageName );
45
-
46
- continue;
47
- }
48
-
49
- await exec( `npm dist-tag add ${ packageName }@${ version } latest` )
50
- .then( () => {
51
- packagesUpdated.push( packageName );
39
+ const updateTagPromises = packages.map( async packageName => {
40
+ const updateLatestTagRetryable = retry( () => exec( `npm dist-tag add ${ packageName }@${ version } latest` ) );
41
+ await updateLatestTagRetryable()
42
+ .then( response => {
43
+ if ( response.stdout ) {
44
+ packagesUpdated.push( packageName );
45
+ } else if ( response.stderr ) {
46
+ throw new Error( response.stderr );
47
+ }
52
48
  } )
53
49
  .catch( error => {
54
- errors.push( trimErrorMessage( error.message ) );
50
+ if ( error.message.includes( 'is already set to version' ) ) {
51
+ packagesSkipped.push( packageName );
52
+ } else {
53
+ errors.push( trimErrorMessage( error.message ) );
54
+ }
55
55
  } )
56
56
  .finally( () => {
57
57
  counter.increase();
58
58
  } );
59
- }
59
+ } );
60
+
61
+ await Promise.allSettled( updateTagPromises );
60
62
 
61
63
  counter.finish();
62
64
 
@@ -85,9 +87,24 @@ function trimErrorMessage( message ) {
85
87
  }
86
88
 
87
89
  /**
88
- * @param {String} command
89
- * @returns {Promise.<String>}
90
+ * @param {Function} callback
91
+ * @param {Number} times
92
+ * @returns {RetryCallback}
90
93
  */
91
- async function exec( command ) {
92
- return tools.shExec( command, { verbosity: 'silent', async: true } );
94
+ function retry( callback, times = 3 ) {
95
+ return ( ...args ) => Promise.resolve()
96
+ .then( () => callback( ...args ) )
97
+ .catch( err => {
98
+ if ( times > 0 ) {
99
+ return retry( callback, times - 1 )( ...args );
100
+ }
101
+
102
+ throw err;
103
+ } );
93
104
  }
105
+
106
+ /**
107
+ * @callback RetryCallback
108
+ * @param {...*} args
109
+ * @returns {Promise}
110
+ */
@@ -28,7 +28,7 @@ const WORKER_SCRIPT = upath.join( __dirname, 'parallelworker.js' );
28
28
  * @param {String} options.packagesDirectory Relative path to a location of packages to execute a task.
29
29
  * @param {Function} options.taskToExecute A callback that is executed on all found packages.
30
30
  * It receives an absolute path to a package as an argument. It can be synchronous or may return a promise.
31
- * @param {ListrTaskObject} options.listrTask An instance of `ListrTask`.
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
34
  * @param {Function} [options.packagesDirectoryFilter=null] A function that is executed for each found package directory to filter out those
@@ -42,7 +42,7 @@ module.exports = async function executeInParallel( options ) {
42
42
  const {
43
43
  packagesDirectory,
44
44
  taskToExecute,
45
- listrTask,
45
+ listrTask = {},
46
46
  signal = null,
47
47
  taskOptions = null,
48
48
  packagesDirectoryFilter = null,
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-dev-release-tools",
3
- "version": "38.3.0",
3
+ "version": "38.4.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.3.0",
8
+ "@ckeditor/ckeditor5-dev-utils": "^38.4.0",
9
9
  "@octokit/rest": "^19.0.0",
10
10
  "chalk": "^4.0.0",
11
11
  "cli-table": "^0.3.1",