@ckeditor/ckeditor5-dev-release-tools 51.1.0 → 52.0.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.
@@ -1,211 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md.
4
- */
5
-
6
- import fs from 'fs';
7
- import { tools, logger, workspaces } from '@ckeditor/ckeditor5-dev-utils';
8
- import chalk from 'chalk';
9
- import semver from 'semver';
10
- import displayCommits from '../utils/displaycommits.js';
11
- import generateChangelog from '../utils/generatechangelog.js';
12
- import getNewVersionType from '../utils/getnewversiontype.js';
13
- import getCommits from '../utils/getcommits.js';
14
- import getWriterOptions from '../utils/getwriteroptions.js';
15
- import transformCommitFactory from '../utils/transformcommitfactory.js';
16
- import getFormattedDate from '../utils/getformatteddate.js';
17
- import saveChangelog from '../utils/savechangelog.js';
18
- import getChangelog from '../utils/getchangelog.js';
19
- import provideVersion from '../utils/provideversion.js';
20
- import { CHANGELOG_FILE, CHANGELOG_HEADER, CLI_INDENT_SIZE } from '../utils/constants.js';
21
-
22
- const SKIP_GENERATE_CHANGELOG = 'Typed "skip" as a new version. Aborting.';
23
-
24
- /**
25
- * Generates the changelog based on commit messages in a package that is located under current work directory (cwd).
26
- *
27
- * If the package does not have any commit, the user has to confirm whether the changelog should be generated.
28
- *
29
- * @param {object} [options={}] Additional options.
30
- *
31
- * @param {boolean} [options.skipLinks=false] If set on true, links to release or commits will be omitted.
32
- *
33
- * @param {string} [options.from] A commit or tag name that will be the first param of the range of commits to collect.
34
- *
35
- * @param {string} [options.releaseBranch='master'] A name of the branch that should be used for releasing packages.
36
- *
37
- * @param {string} [options.mainBranch='master'] A name of the main branch in the repository.
38
- *
39
- * @param {FormatDateCallback} [options.formatDate] A callback allowing defining a custom format of the date inserted into the changelog.
40
- * If not specified, the default date matches the `YYYY-MM-DD` pattern.
41
- *
42
- * @returns {Promise}
43
- */
44
- export default async function generateChangelogForSinglePackage( options = {} ) {
45
- const log = logger();
46
- const pkgJson = workspaces.getPackageJson();
47
-
48
- logProcess( chalk.bold( `Generating changelog for "${ chalk.underline( pkgJson.name ) }"...` ) );
49
-
50
- const transformCommit = transformCommitFactory();
51
-
52
- logProcess( 'Collecting all commits since the last release...' );
53
-
54
- const commitOptions = {
55
- from: options.from ? options.from : 'v' + pkgJson.version,
56
- releaseBranch: options.releaseBranch || 'master',
57
- mainBranch: options.mainBranch || 'master'
58
- };
59
-
60
- // Initial release.
61
- if ( semver.eq( pkgJson.version, '0.0.1' ) ) {
62
- commitOptions.from = null;
63
- }
64
-
65
- // Collection of all entries (real commits + additional "fake" commits extracted from descriptions).
66
- let allCommits;
67
-
68
- // A new version inserted into the changelog.
69
- let newVersion;
70
-
71
- return getCommits( transformCommit, commitOptions )
72
- .then( commits => {
73
- allCommits = commits;
74
-
75
- logInfo( `Found ${ commits.length } entries to parse.`, { indentLevel: 1 } );
76
- } )
77
- .then( () => {
78
- logProcess( 'Preparing new version for the package...' );
79
-
80
- displayCommits( allCommits, { indentLevel: 1 } );
81
-
82
- return provideVersion( {
83
- packageName: pkgJson.name,
84
- version: pkgJson.version,
85
- indentLevel: 1,
86
- releaseTypeOrNewVersion: getNewVersionType( allCommits )
87
- } );
88
- } )
89
- .then( version => {
90
- if ( version === 'skip' ) {
91
- throw new Error( SKIP_GENERATE_CHANGELOG );
92
- }
93
-
94
- const isInternalRelease = version === 'internal';
95
-
96
- if ( version === 'internal' ) {
97
- version = semver.inc( pkgJson.version, 'patch' );
98
- }
99
-
100
- newVersion = version;
101
-
102
- logProcess( 'Generating the changelog...' );
103
-
104
- const writerContext = {
105
- version,
106
- commit: 'commit',
107
- repoUrl: workspaces.getRepositoryUrl(),
108
- currentTag: 'v' + version,
109
- previousTag: options.from ? options.from : 'v' + pkgJson.version,
110
- isPatch: semver.diff( version, pkgJson.version ) === 'patch',
111
- isInternalRelease,
112
- skipCommitsLink: Boolean( options.skipLinks ),
113
- skipCompareLink: Boolean( options.skipLinks ),
114
- date: options.formatDate ? options.formatDate( new Date() ) : getFormattedDate()
115
- };
116
-
117
- const writerOptions = getWriterOptions( commit => {
118
- // We do not allow modifying the commit hash value by the generator itself.
119
- return commit;
120
- } );
121
-
122
- const publicCommits = [ ...allCommits ]
123
- .filter( commit => commit.isPublicCommit )
124
- .map( commit => {
125
- commit.scope = null;
126
- commit.notes = commit.notes.map( note => {
127
- note.scope = null;
128
-
129
- return note;
130
- } );
131
-
132
- return commit;
133
- } );
134
-
135
- return generateChangelog( publicCommits, writerContext, writerOptions )
136
- .then( changes => {
137
- logInfo( 'Changes based on commits have been generated.', { indentLevel: 1 } );
138
-
139
- return Promise.resolve( changes );
140
- } );
141
- } )
142
- .then( changesFromCommits => {
143
- logProcess( 'Saving changelog...' );
144
-
145
- if ( !fs.existsSync( CHANGELOG_FILE ) ) {
146
- logInfo( 'Changelog file does not exist. Creating...', { isWarning: true, indentLevel: 1 } );
147
-
148
- saveChangelog( CHANGELOG_HEADER );
149
- }
150
-
151
- let currentChangelog = getChangelog();
152
-
153
- // Remove header from current changelog.
154
- currentChangelog = currentChangelog.replace( CHANGELOG_HEADER, '' );
155
-
156
- // Concat header, new and current changelog.
157
- let newChangelog = CHANGELOG_HEADER + changesFromCommits + currentChangelog.trim();
158
- newChangelog = newChangelog.trim() + '\n';
159
-
160
- // Save the changelog.
161
- saveChangelog( newChangelog );
162
-
163
- tools.shExec( `git add ${ CHANGELOG_FILE }`, { verbosity: 'error' } );
164
- tools.shExec( 'git commit -m "Docs: Changelog. [skip ci]"', { verbosity: 'error' } );
165
-
166
- logInfo( 'Saved.', { indentLevel: 1 } );
167
- } )
168
- .then( () => {
169
- logInfo( `Changelog for "${ chalk.underline( pkgJson.name ) }" (v${ newVersion }) has been generated.`, { indentLevel: 1 } );
170
- } )
171
- .catch( err => {
172
- if ( err.message === SKIP_GENERATE_CHANGELOG ) {
173
- logInfo( `Skipping generating the changelog for "${ chalk.underline( pkgJson.name ) }".`, {
174
- indentLevel: 1,
175
- isWarning: true,
176
- startWithNewLine: true
177
- } );
178
-
179
- return;
180
- }
181
-
182
- throw err;
183
- } );
184
-
185
- function logProcess( message ) {
186
- log.info( '\n📍 ' + chalk.cyan( message ) );
187
- }
188
-
189
- /**
190
- * @param {string} message
191
- * @param {object} [options={}]
192
- * @param {number} [options.indentLevel=0]
193
- * @param {boolean} [options.startWithNewLine=false] Whether to append a new line before the message.
194
- * @param {boolean} [options.isWarning=false] Whether to use `warning` method instead of `log`.
195
- */
196
- function logInfo( message, options = {} ) {
197
- const indentLevel = options.indentLevel || 0;
198
- const startWithNewLine = options.startWithNewLine || false;
199
- const method = options.isWarning ? 'warning' : 'info';
200
-
201
- log[ method ]( `${ startWithNewLine ? '\n' : '' }${ ' '.repeat( indentLevel * CLI_INDENT_SIZE ) }` + message );
202
- }
203
- }
204
-
205
- /**
206
- * @callback FormatDateCallback
207
- *
208
- * @param {Date} now The current date.
209
- *
210
- * @returns {string} The formatted date inserted into the changelog.
211
- */
@@ -1,29 +0,0 @@
1
- * {{#if scope}}**{{~scope.[0]}}**: {{/if}}{{subject}}
2
-
3
- {{~#unless @root.skipCommitsLink }}
4
- {{~#unless skipCommitsLink }}
5
- {{~!-- commit link --}} {{#if @root.linkReferences~}}
6
- ([commit](
7
- {{~#if @root.repository}}
8
- {{~#if @root.host}}
9
- {{~@root.host}}/
10
- {{~/if}}
11
- {{~#if @root.owner}}
12
- {{~@root.owner}}/
13
- {{~/if}}
14
- {{~@root.repository}}
15
- {{~else}}
16
- {{~@root.repoUrl}}
17
- {{~/if}}/
18
- {{~@root.commit}}/{{hash}}))
19
- {{~else}}
20
- {{~hash}}
21
- {{~/if}}
22
- {{/unless}}
23
- {{/unless}}
24
- {{#if body}}
25
-
26
-
27
- {{body}}
28
- {{~/if}}
29
-
@@ -1,10 +0,0 @@
1
- {{#if noteGroups}}
2
- {{#each noteGroups}}
3
- ### {{title}}
4
-
5
- {{#each notes}}
6
- * {{#if scope}}**{{~scope.[0]}}**: {{/if}}{{text}}
7
- {{/each}}
8
-
9
- {{/each}}
10
- {{/if}}
@@ -1,23 +0,0 @@
1
- ## {{#unless @root.skipCompareLink~}}
2
- [{{version}}](
3
- {{~#if @root.repository~}}
4
- {{~#if @root.host}}
5
- {{~@root.host}}/
6
- {{~/if}}
7
- {{~#if @root.owner}}
8
- {{~@root.owner}}/
9
- {{~/if}}
10
- {{~@root.repository}}
11
- {{~else}}
12
- {{~@root.repoUrl}}
13
- {{~/if~}}
14
- {{~#if previousTag~}}
15
- /compare/{{previousTag}}...{{currentTag}}
16
- {{~else~}}
17
- /tree/{{currentTag}}
18
- {{~/if}})
19
- {{~else}}
20
- {{~version}}
21
- {{~/unless}}
22
- {{~#if date}} ({{date}})
23
- {{/if}}
@@ -1,12 +0,0 @@
1
- {
2
- "name": null,
3
- "version": null,
4
- "description": null,
5
- "keywords": null,
6
- "engines": null,
7
- "author": null,
8
- "license": null,
9
- "homepage": null,
10
- "bugs": null,
11
- "repository": null
12
- }
@@ -1,25 +0,0 @@
1
- {{> header}}
2
-
3
- {{#if isInternalRelease}}
4
- Internal changes only (updated dependencies, documentation, etc.).
5
-
6
-
7
- {{else}}
8
- {{> footer}}
9
- {{#each commitGroups}}
10
- ### {{title}}
11
-
12
- {{#if (lookup @root.additionalNotes title)}}
13
- {{ lookup @root.additionalNotes title }}
14
-
15
- {{/if}}
16
- {{#each commits}}
17
- {{> commit root=@root}}
18
- {{/each}}
19
-
20
- {{else}}
21
- Internal changes only (updated dependencies, documentation, etc.).
22
-
23
- {{/each}}
24
-
25
- {{/if}}
@@ -1,103 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md.
4
- */
5
-
6
- import chalk from 'chalk';
7
- import { logger } from '@ckeditor/ckeditor5-dev-utils';
8
- import * as utils from './transformcommitutils.js';
9
- import { CLI_COMMIT_INDENT_SIZE, CLI_INDENT_SIZE } from './constants.js';
10
-
11
- /**
12
- * @param {Array.<Commit>|Set.<Commit>} commits
13
- * @param {object} [options={}]
14
- * @param {boolean} [options.attachLinkToCommit=false] Whether to attach a link to parsed commit.
15
- * @param {number} [options.indentLevel=1] The indent level.
16
- */
17
- export default function displayCommits( commits, options = {} ) {
18
- const log = logger();
19
-
20
- const attachLinkToCommit = options.attachLinkToCommit || false;
21
- const indentLevel = options.indentLevel || 1;
22
- const listIndent = ' '.repeat( CLI_INDENT_SIZE * indentLevel );
23
-
24
- if ( !( commits.length || commits.size ) ) {
25
- log.info( listIndent + chalk.italic( 'No commits to display.' ) );
26
- }
27
-
28
- const COMMITS_SEPARATOR = listIndent + chalk.gray( '-'.repeat( 112 ) );
29
-
30
- // Group of commits by the commit's hash.
31
- /** @type {Map.<string, Set.<Commit>>} */
32
- const commitGroups = new Map();
33
-
34
- for ( const singleCommit of commits ) {
35
- getCommitGroup( singleCommit ).add( singleCommit );
36
- }
37
-
38
- // A flag that helps avoid duplication separators if two groups are consecutive one after another.
39
- let finishedWithSeparator = false;
40
-
41
- for ( const [ hash, commits ] of commitGroups ) {
42
- // Do not duplicate the separator if it was already added.
43
- if ( commits.size > 1 && !finishedWithSeparator ) {
44
- log.info( COMMITS_SEPARATOR );
45
- }
46
-
47
- for ( const singleCommit of commits.values() ) {
48
- const hasCorrectType = utils.availableCommitTypes.has( singleCommit.rawType );
49
- const isCommitIncluded = utils.availableCommitTypes.get( singleCommit.rawType );
50
-
51
- const indent = commits.size > 1 ? listIndent.slice( 0, listIndent.length - 1 ) + chalk.gray( '|' ) : listIndent;
52
- const noteIndent = indent + ' '.repeat( CLI_COMMIT_INDENT_SIZE );
53
-
54
- let logMessage = `${ indent }* ${ chalk.yellow( hash.slice( 0, 7 ) ) } "${ utils.truncate( singleCommit.header, 100 ) }" `;
55
-
56
- if ( hasCorrectType && isCommitIncluded ) {
57
- logMessage += chalk.green( 'INCLUDED' );
58
- } else if ( hasCorrectType && !isCommitIncluded ) {
59
- logMessage += chalk.gray( 'SKIPPED' );
60
- } else {
61
- logMessage += chalk.red( 'INVALID' );
62
- }
63
-
64
- // Avoid displaying singleCommit merge twice.
65
- if ( singleCommit.merge && singleCommit.merge !== singleCommit.header ) {
66
- logMessage += `\n${ noteIndent }${ chalk.italic( singleCommit.merge ) }`;
67
- }
68
-
69
- for ( const note of singleCommit.notes ) {
70
- const limit = 100 - note.title.length;
71
-
72
- logMessage += `\n${ noteIndent }${ note.title }: ${ utils.truncate( note.text, limit ) } `;
73
- }
74
-
75
- if ( attachLinkToCommit ) {
76
- const url = `${ singleCommit.repositoryUrl }/commit/${ singleCommit.hash }`;
77
-
78
- logMessage += `\n${ noteIndent }${ chalk.gray( url ) }`;
79
- }
80
-
81
- log.info( logMessage );
82
- }
83
-
84
- if ( commits.size > 1 ) {
85
- finishedWithSeparator = true;
86
- log.info( COMMITS_SEPARATOR );
87
- } else {
88
- finishedWithSeparator = false;
89
- }
90
- }
91
-
92
- /**
93
- * @param {Commit} commit
94
- * @returns {Set.<Commit>}
95
- */
96
- function getCommitGroup( commit ) {
97
- if ( !commitGroups.has( commit.hash ) ) {
98
- commitGroups.set( commit.hash, new Set() );
99
- }
100
-
101
- return commitGroups.get( commit.hash );
102
- }
103
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md.
4
- */
5
-
6
- import { logger, workspaces } from '@ckeditor/ckeditor5-dev-utils';
7
- import chalk from 'chalk';
8
- import { CLI_INDENT_SIZE } from './constants.js';
9
-
10
- /**
11
- * Displays skipped packages.
12
- *
13
- * @param {Set} skippedPackagesPaths
14
- */
15
- export default function displaySkippedPackages( skippedPackagesPaths ) {
16
- if ( !skippedPackagesPaths.size ) {
17
- return;
18
- }
19
-
20
- const indent = ' '.repeat( CLI_INDENT_SIZE );
21
- const packageNames = Array.from( skippedPackagesPaths )
22
- .map( packagePath => {
23
- const { name } = workspaces.getPackageJson( packagePath );
24
-
25
- return name;
26
- } );
27
-
28
- let message = indent + chalk.bold.underline( 'Packages listed below have been skipped:' ) + '\n';
29
- message += packageNames.map( line => indent + ` * ${ line }` ).join( '\n' );
30
-
31
- logger().info( message );
32
- }
@@ -1,117 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md.
4
- */
5
-
6
- import { Readable } from 'stream';
7
- import { stream } from '@ckeditor/ckeditor5-dev-utils';
8
- import { writeChangelogStream } from 'conventional-changelog-writer';
9
-
10
- const UPDATED_TRANSLATION_COMMIT = '* Updated translations.';
11
-
12
- /**
13
- * Generates the changelog based on commits.
14
- *
15
- * @param {Array.<Commit>} commits
16
- *
17
- * @param {object} context
18
- * @param {string} context.version Current version for the release.
19
- * @param {string} context.repoUrl The repository URL.
20
- * @param {string} context.currentTag A tag for the current version.
21
- * @param {string} context.commit Commit keyword in the URL.
22
- * @param {string} [context.previousTag] A tag for the previous version.
23
- * @param {boolean} [context.skipCommitsLink=false] Whether to skip adding links to commit.
24
- * @param {boolean} [context.skipCompareLink=false] Whether to remove the compare URL in the header.
25
- *
26
- * @param {object} options
27
- * @param {object} options.transform
28
- * @param {function} options.transform.hash A function for mapping the commit's hash.
29
- * @param {Array.<string>|string} options.groupBy A key for grouping the commits.
30
- * @param {function} options.commitGroupsSort A sort function for the groups.
31
- * @param {function} options.noteGroupsSort A soft function for the notes.
32
- * @param {string} options.mainTemplate The main template for the changelog.
33
- * @param {string} options.headerPartial The "header" partial used in the main template.
34
- * @param {string} options.commitPartial The "commit" partial used in the main template.
35
- * @param {string} options.footerPartial The "footer" partial used in the main template.
36
- *
37
- * @returns {Promise.<string>}
38
- */
39
- export default function generateChangelog( commits, context, options ) {
40
- const commitStream = new Readable( { objectMode: true } );
41
- /* istanbul ignore next */
42
- commitStream._read = function() {};
43
-
44
- for ( const commitItem of commits ) {
45
- commitStream.push( commitItem );
46
- }
47
-
48
- commitStream.push( null );
49
-
50
- return new Promise( ( resolve, reject ) => {
51
- commitStream
52
- .pipe( writeChangelogStream( context, options ) )
53
- .pipe( stream.noop( changes => {
54
- changes = mergeUpdateTranslationsCommits( changes.toString(), {
55
- skipCommitsLink: context.skipCommitsLink
56
- } );
57
-
58
- resolve( changes );
59
- } ) )
60
- .on( 'error', reject );
61
- } );
62
- }
63
-
64
- /**
65
- * Merges multiple "Updated translations." entries into the single commit.
66
- *
67
- * @param {string} changelog Generated changelog.
68
- * @param {object} [options={}]
69
- * @param {boolean} [options.skipCommitsLink=false] Whether to skip adding links to commit.
70
- * @returns {string}
71
- */
72
- function mergeUpdateTranslationsCommits( changelog, options = {} ) {
73
- let foundUpdatedTranslationCommit = false;
74
-
75
- const changelogAsArray = changelog.split( '\n' );
76
-
77
- // An array that contains duplicated commits.
78
- const removedEntries = [];
79
-
80
- // An array that contains changelog without duplicated entries.
81
- const uniqueEntries = changelogAsArray.filter( line => {
82
- if ( !line.startsWith( UPDATED_TRANSLATION_COMMIT ) ) {
83
- return true;
84
- }
85
-
86
- if ( foundUpdatedTranslationCommit ) {
87
- removedEntries.push( line );
88
-
89
- return false;
90
- }
91
-
92
- foundUpdatedTranslationCommit = true;
93
-
94
- return true;
95
- } );
96
-
97
- if ( options.skipCommitsLink ) {
98
- return uniqueEntries.join( '\n' );
99
- }
100
-
101
- return uniqueEntries.map( line => {
102
- if ( !line.startsWith( UPDATED_TRANSLATION_COMMIT ) ) {
103
- return line;
104
- }
105
-
106
- const newLine = line + ' ' + removedEntries
107
- .map( entry => {
108
- const match = entry.match( /(\(\[commit\].*)$/ );
109
-
110
- return match ? match[ 1 ] : null;
111
- } )
112
- .filter( item => !!item )
113
- .join( ' ' );
114
-
115
- return newLine.trim().replace( /\) \(/g, ', ' );
116
- } ).join( '\n' );
117
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md.
4
- */
5
-
6
- import { tools } from '@ckeditor/ckeditor5-dev-utils';
7
-
8
- /**
9
- * Returns an array with paths to changed files for given commit.
10
- *
11
- * @param {string} commitId
12
- * @returns {Array.<string>}
13
- */
14
- export default function getChangedFilesForCommit( commitId ) {
15
- const gitCommand = `git log -m -1 --name-only --pretty="format:" ${ commitId }`;
16
- const changedFiles = tools.shExec( gitCommand, { verbosity: 'error' } ).trim();
17
-
18
- // Merge commits can have two parents. Returned files for merge commits looks like:
19
- // file1 <-- files from merged branch
20
- // file2 <-- files from merged branch
21
- // file <-- files from merged branch
22
- //
23
- // other-file1 <-- files from last commit before merge
24
- // other-file2 <-- files from last commit before merge
25
- // We need to filter out files from commit before merge.
26
-
27
- return changedFiles.split( '\n\n' )[ 0 ]
28
- .split( '\n' )
29
- .map( file => file.trim() )
30
- .filter( item => item );
31
- }