@ckeditor/ckeditor5-dev-ci 32.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.
- package/LICENSE.md +16 -0
- package/README.md +20 -0
- package/bin/notifytravisstatus.js +90 -0
- package/lib/index.js +12 -0
- package/lib/members.json +34 -0
- package/lib/notifytravisstatus.js +213 -0
- package/package.json +30 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Software License Agreement
|
|
2
|
+
==========================
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2003-2022, [CKSource](http://cksource.com) Holding sp. z o.o. All rights reserved.
|
|
5
|
+
|
|
6
|
+
Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
|
|
7
|
+
|
|
8
|
+
Sources of Intellectual Property Included in CKEditor
|
|
9
|
+
-----------------------------------------------------
|
|
10
|
+
|
|
11
|
+
Where not otherwise indicated, all CKEditor content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, CKEditor will incorporate work done by developers outside of CKSource with their express permission.
|
|
12
|
+
|
|
13
|
+
Trademarks
|
|
14
|
+
----------
|
|
15
|
+
|
|
16
|
+
**CKEditor** is a trademark of [CKSource](http://cksource.com) Holding sp. z o.o. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
|
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
CKEditor 5 CI utilities
|
|
2
|
+
=======================
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.com/package/@ckeditor/ckeditor5-dev-ci)
|
|
5
|
+
[](https://app.travis-ci.com/github/ckeditor/ckeditor5-dev)
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
Utils for [CKEditor 5](https://ckeditor.com) CI builds.
|
|
9
|
+
|
|
10
|
+
Contains tools for sending Slack notifications by Travis.
|
|
11
|
+
|
|
12
|
+
More information about development tools packages can be found at the following URL: <https://github.com/ckeditor/ckeditor5-dev>.
|
|
13
|
+
|
|
14
|
+
## Changelog
|
|
15
|
+
|
|
16
|
+
See the [`CHANGELOG.md`](https://github.com/ckeditor/ckeditor5-dev/blob/master/packages/ckeditor5-dev-ci/CHANGELOG.md) file.
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
|
|
20
|
+
Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html). For full details about the license, please check the `LICENSE.md` file.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
5
|
+
* For licensing, see LICENSE.md.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* eslint-env node */
|
|
9
|
+
|
|
10
|
+
// This script assumes that is being executed on Travis CI. It requires following environment variables:
|
|
11
|
+
//
|
|
12
|
+
// - SLACK_WEBHOOK_URL - a URL where the notification should be sent
|
|
13
|
+
// - START_TIME - POSIX time (when the script has begun the job)
|
|
14
|
+
// - END_TIME - POSIX time (when the script has finished the job)
|
|
15
|
+
// - GITHUB_TOKEN - token to a Github account with the scope: "repos". It is requires for obtaining an author of
|
|
16
|
+
// the commit if the build failed. The repository can be private and we can't use the public API.
|
|
17
|
+
//
|
|
18
|
+
// If the `SLACK_NOTIFY_COMMIT_URL` environment variable is defined, the script use the URL as the commit URL.
|
|
19
|
+
// Otherwise, a marge of variables `TRAVIS_REPO_SLUG` and `TRAVIS_COMMIT` will be used.
|
|
20
|
+
//
|
|
21
|
+
// Pinging an author of the commit can be disabled by defining the `SLACK_NOTIFY_HIDE_AUTHOR` environment variable
|
|
22
|
+
// to `"true"` (`SLACK_NOTIFY_HIDE_AUTHOR="true"`). See: https://github.com/ckeditor/ckeditor5/issues/9252.
|
|
23
|
+
//
|
|
24
|
+
// In order to enable the debug mode, set the `DEBUG=true` as the environment variable.
|
|
25
|
+
|
|
26
|
+
const buildBranch = process.env.TRAVIS_BRANCH;
|
|
27
|
+
|
|
28
|
+
const ALLOWED_BRANCHES = [
|
|
29
|
+
'stable',
|
|
30
|
+
'master'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const ALLOWED_EVENTS = [
|
|
34
|
+
'push',
|
|
35
|
+
'cron',
|
|
36
|
+
'api'
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// Send a notification only for main branches...
|
|
40
|
+
if ( !ALLOWED_BRANCHES.includes( buildBranch ) ) {
|
|
41
|
+
printDebugLog( `Aborting due to an invalid branch (${ buildBranch }).` );
|
|
42
|
+
|
|
43
|
+
process.exit();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ...and an event that triggered the build is correct...
|
|
47
|
+
if ( !ALLOWED_EVENTS.includes( process.env.TRAVIS_EVENT_TYPE ) ) {
|
|
48
|
+
printDebugLog( `Aborting due to an invalid event type (${ process.env.TRAVIS_EVENT_TYPE }).` );
|
|
49
|
+
|
|
50
|
+
process.exit();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ...and for builds that failed.
|
|
54
|
+
if ( process.env.TRAVIS_TEST_RESULT == 0 ) {
|
|
55
|
+
printDebugLog( 'The build did not fail. The notification will not be sent.' );
|
|
56
|
+
|
|
57
|
+
process.exit();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const notifyTravisStatus = require( '../lib/notifytravisstatus' );
|
|
61
|
+
|
|
62
|
+
const options = {
|
|
63
|
+
repositorySlug: process.env.TRAVIS_REPO_SLUG,
|
|
64
|
+
startTime: parseInt( process.env.START_TIME ),
|
|
65
|
+
endTime: parseInt( process.env.END_TIME ),
|
|
66
|
+
githubToken: process.env.GITHUB_TOKEN,
|
|
67
|
+
slackWebhookUrl: process.env.SLACK_WEBHOOK_URL,
|
|
68
|
+
branch: buildBranch,
|
|
69
|
+
commit: process.env.TRAVIS_COMMIT,
|
|
70
|
+
notifyCommitUrl: process.env.SLACK_NOTIFY_COMMIT_URL,
|
|
71
|
+
shouldHideAuthor: process.env.SLACK_NOTIFY_HIDE_AUTHOR === 'true',
|
|
72
|
+
jobUrl: process.env.TRAVIS_JOB_WEB_URL,
|
|
73
|
+
jobId: process.env.TRAVIS_JOB_NUMBER
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
notifyTravisStatus( options )
|
|
77
|
+
.catch( error => {
|
|
78
|
+
console.error( error );
|
|
79
|
+
|
|
80
|
+
throw error;
|
|
81
|
+
} );
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @param {String} message
|
|
85
|
+
*/
|
|
86
|
+
function printDebugLog( message ) {
|
|
87
|
+
if ( process.env.DEBUG == 'true' ) {
|
|
88
|
+
console.log( '[Slack Notification]', message );
|
|
89
|
+
}
|
|
90
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const notifyTravisStatus = require( './notifytravisstatus' );
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
notifyTravisStatus
|
|
12
|
+
};
|
package/lib/members.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Acrophost": "U03RMNJJUAG",
|
|
3
|
+
"AnnaTomanek": "U044RC5NQ",
|
|
4
|
+
"apadol-cksource": "U03HB5SSYCS",
|
|
5
|
+
"arkflpc": "U027XSCTX09",
|
|
6
|
+
"Comandeer": "U0BK6HSJJ",
|
|
7
|
+
"DawidKossowski": "U0401V31S9M",
|
|
8
|
+
"dufipl": "U02SG0U25GS",
|
|
9
|
+
"Dumluregn": "UGG2JE7JR",
|
|
10
|
+
"FilipTokarski": "URSK5KV9V",
|
|
11
|
+
"godai78": "U017DJLU7NX",
|
|
12
|
+
"gorzelinski": "U04DJ7BKSKU",
|
|
13
|
+
"illia-stv": "U048K896SCE",
|
|
14
|
+
"jacekbogdanski": "U8LAY97DE",
|
|
15
|
+
"kbinieda": "U0401V2TGG7",
|
|
16
|
+
"ldrobnik": "U04DJ7B7ZCJ",
|
|
17
|
+
"LukaszGudel": "U01FRHAT8T1",
|
|
18
|
+
"mabryl": "U045033D401",
|
|
19
|
+
"Mgsy": "U5A38S2PN",
|
|
20
|
+
"martnpaneq": "U045B560E00",
|
|
21
|
+
"mlewand": "U03UQQ1N3",
|
|
22
|
+
"mmotyczynska": "U02NSTQCTB8",
|
|
23
|
+
"mremiszewski": "U04ACUBMDGT",
|
|
24
|
+
"niegowski": "U01017YC7C7",
|
|
25
|
+
"oleq": "U03UU2MNN",
|
|
26
|
+
"pomek": "U1D6HMH5M",
|
|
27
|
+
"przemyslaw-zan": "U023HF765MK",
|
|
28
|
+
"psmyrek": "U01BJRWJCSJ",
|
|
29
|
+
"pszczesniak": "U04167FKV88",
|
|
30
|
+
"Reinmar": "U03UQRP0C",
|
|
31
|
+
"scofalik": "U05611ZMM",
|
|
32
|
+
"wwalc": "U03UQQ8PY",
|
|
33
|
+
"CKTravisBot": "CKTravisBot"
|
|
34
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
// A map that translates GitHub accounts to Slack ids.
|
|
9
|
+
const members = require( './members.json' );
|
|
10
|
+
|
|
11
|
+
const REPOSITORY_REGEXP = /github\.com\/([^/]+)\/([^/]+)/;
|
|
12
|
+
|
|
13
|
+
const fetch = require( 'node-fetch' );
|
|
14
|
+
const slackNotify = require( 'slack-notify' );
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @param {String} options.repositorySlug
|
|
19
|
+
* @param {Number} options.startTime
|
|
20
|
+
* @param {Number} options.endTime
|
|
21
|
+
* @param {String} options.githubToken
|
|
22
|
+
* @param {String} options.slackWebhookUrl
|
|
23
|
+
* @param {String} options.branch
|
|
24
|
+
* @param {String} options.commit
|
|
25
|
+
* @param {String} options.notifyCommitUrl
|
|
26
|
+
* @param {Boolean} options.shouldHideAuthor
|
|
27
|
+
* @param {String} options.jobUrl
|
|
28
|
+
* @param {String} options.jobId
|
|
29
|
+
* @returns {Promise}
|
|
30
|
+
*/
|
|
31
|
+
module.exports = async function notifyTravisStatus( options ) {
|
|
32
|
+
const commitUrl = getCommitUrl( {
|
|
33
|
+
commit: options.commit,
|
|
34
|
+
notifyCommitUrl: options.notifyCommitUrl,
|
|
35
|
+
repositorySlug: options.repositorySlug
|
|
36
|
+
} );
|
|
37
|
+
const commitDetails = await getCommitDetails( commitUrl, options.githubToken );
|
|
38
|
+
|
|
39
|
+
const [ buildRepoOwner, buildRepoName ] = options.repositorySlug.split( '/' );
|
|
40
|
+
const execTime = getExecutionTime( options.endTime, options.startTime );
|
|
41
|
+
|
|
42
|
+
const slackAccount = members[ commitDetails.author ];
|
|
43
|
+
const shortCommit = commitUrl.split( '/' ).pop().substring( 0, 7 );
|
|
44
|
+
const repoMatch = commitUrl.match( REPOSITORY_REGEXP );
|
|
45
|
+
|
|
46
|
+
const slack = slackNotify( options.slackWebhookUrl );
|
|
47
|
+
|
|
48
|
+
slack.onError = err => {
|
|
49
|
+
console.log( 'API error occurred:', err );
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return slack.send( {
|
|
53
|
+
username: 'Travis CI',
|
|
54
|
+
text: getNotifierMessage( {
|
|
55
|
+
slackAccount,
|
|
56
|
+
githubAccount: commitDetails.author,
|
|
57
|
+
shouldHideAuthor: options.shouldHideAuthor
|
|
58
|
+
} ),
|
|
59
|
+
icon_url: 'https://a.slack-edge.com/66f9/img/services/travis_36.png',
|
|
60
|
+
unfurl_links: 1,
|
|
61
|
+
attachments: [
|
|
62
|
+
{
|
|
63
|
+
color: 'danger',
|
|
64
|
+
fields: [
|
|
65
|
+
{
|
|
66
|
+
title: 'Repository (branch)',
|
|
67
|
+
value: [
|
|
68
|
+
`<https://github.com/${ buildRepoOwner }/${ buildRepoName }|${ buildRepoName }>`,
|
|
69
|
+
`(<https://github.com/${ buildRepoOwner }/${ buildRepoName }/tree/${ options.branch }|${ options.branch }>)`
|
|
70
|
+
].join( ' ' ),
|
|
71
|
+
short: true
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
title: 'Commit',
|
|
75
|
+
value: `<${ commitUrl }|${ shortCommit }>`,
|
|
76
|
+
short: true
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
title: 'Build number',
|
|
80
|
+
value: `<${ options.jobUrl }|#${ options.jobId }>`,
|
|
81
|
+
short: true
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: 'Build time',
|
|
85
|
+
value: `${ execTime.mins } min ${ execTime.secs } sec`,
|
|
86
|
+
short: true
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
title: 'Commit message',
|
|
90
|
+
value: getFormattedMessage( commitDetails.message, repoMatch[ 1 ], repoMatch[ 2 ] ),
|
|
91
|
+
short: false
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
} );
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Returns an object that compares two dates.
|
|
101
|
+
*
|
|
102
|
+
* @param {Number} endTime
|
|
103
|
+
* @param {Number} startTime
|
|
104
|
+
* @returns {Object}
|
|
105
|
+
*/
|
|
106
|
+
function getExecutionTime( endTime, startTime ) {
|
|
107
|
+
const execTime = {
|
|
108
|
+
ms: endTime - startTime
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
execTime.days = Math.floor( execTime.ms / 86400 );
|
|
112
|
+
execTime.hours = Math.floor( ( execTime.ms - 86400 * execTime.days ) / 3600 );
|
|
113
|
+
execTime.mins = Math.floor( ( ( execTime.ms - 86400 * execTime.days ) - 3600 * execTime.hours ) / 60 );
|
|
114
|
+
execTime.secs = ( ( execTime.ms - 86400 * execTime.days ) - 3600 * execTime.hours ) - 60 * execTime.mins;
|
|
115
|
+
|
|
116
|
+
return execTime;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Replaces `#Id` and `Repo/Owner#Id` with URls to Github Issues.
|
|
121
|
+
*
|
|
122
|
+
* @param {String} message
|
|
123
|
+
* @param {String} repoOwner
|
|
124
|
+
* @param {String} repoName
|
|
125
|
+
* @returns {string}
|
|
126
|
+
*/
|
|
127
|
+
function getFormattedMessage( message, repoOwner, repoName ) {
|
|
128
|
+
return message
|
|
129
|
+
.replace( / #(\d+)/g, ( _, issueId ) => {
|
|
130
|
+
return ` <https://github.com/${ repoOwner }/${ repoName }/issues/${ issueId }|#${ issueId }>`;
|
|
131
|
+
} )
|
|
132
|
+
.replace( /([\w-]+\/[\w-]+)#(\d+)/g, ( _, repoSlug, issueId ) => {
|
|
133
|
+
return `<https://github.com/${ repoSlug }/issues/${ issueId }|${ repoSlug }#${ issueId }>`;
|
|
134
|
+
} );
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns a URL to the commit details on GitHub.
|
|
139
|
+
*
|
|
140
|
+
* @param {Object} options
|
|
141
|
+
* @param {String} options.notifyCommitUrl
|
|
142
|
+
* @param {String} options.repositorySlug
|
|
143
|
+
* @param {String} options.commit
|
|
144
|
+
* @returns {String}
|
|
145
|
+
*/
|
|
146
|
+
function getCommitUrl( options ) {
|
|
147
|
+
if ( options.notifyCommitUrl ) {
|
|
148
|
+
return options.notifyCommitUrl;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return `https://github.com/${ options.repositorySlug }/commit/${ options.commit }`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Returns a URL to GitHub API which returns details of the commit that caused the CI to fail its job.
|
|
156
|
+
*
|
|
157
|
+
* @param {String} commitUrl The URL to the commit on GitHub.
|
|
158
|
+
* @returns {String}
|
|
159
|
+
*/
|
|
160
|
+
function getGithubApiUrl( commitUrl ) {
|
|
161
|
+
return commitUrl.replace( 'github.com/', 'api.github.com/repos/' ).replace( '/commit/', '/commits/' );
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Returns a promise that resolves the commit details (author and message) based on the specified GitHub URL.
|
|
166
|
+
*
|
|
167
|
+
* @param {String} commitUrl The URL to the commit on GitHub.
|
|
168
|
+
* @param {String} githubToken Github token used for authorization a request,
|
|
169
|
+
* @returns {Promise.<Object>}
|
|
170
|
+
*/
|
|
171
|
+
function getCommitDetails( commitUrl, githubToken ) {
|
|
172
|
+
const apiGithubUrlCommit = getGithubApiUrl( commitUrl );
|
|
173
|
+
const options = {
|
|
174
|
+
method: 'GET',
|
|
175
|
+
credentials: 'include',
|
|
176
|
+
headers: {
|
|
177
|
+
authorization: `token ${ githubToken }`
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return fetch( apiGithubUrlCommit, options )
|
|
182
|
+
.then( response => response.json() )
|
|
183
|
+
.then( json => ( {
|
|
184
|
+
author: json.author.login,
|
|
185
|
+
message: json.commit.message
|
|
186
|
+
} ) );
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Returns the additional message that will be added to the notifier post.
|
|
191
|
+
*
|
|
192
|
+
* @param {Object} options
|
|
193
|
+
* @param {Boolean} options.shouldHideAuthor
|
|
194
|
+
* @param {String} options.slackAccount
|
|
195
|
+
* @param {String} options.githubAccount
|
|
196
|
+
* @returns {String}
|
|
197
|
+
*/
|
|
198
|
+
function getNotifierMessage( options ) {
|
|
199
|
+
if ( options.shouldHideAuthor ) {
|
|
200
|
+
return '_The author of the commit was hidden. <https://github.com/ckeditor/ckeditor5/issues/9252|Read more about why.>_';
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if ( !options.slackAccount ) {
|
|
204
|
+
return '_The author of the commit could not be obtained._';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Slack and GitHub names for bots are equal.
|
|
208
|
+
if ( options.slackAccount === options.githubAccount ) {
|
|
209
|
+
return '_This commit is a result of merging a branch into another branch._';
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return `<@${ options.slackAccount }>, could you take a look?`;
|
|
213
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ckeditor/ckeditor5-dev-ci",
|
|
3
|
+
"version": "32.0.0",
|
|
4
|
+
"description": "Utils for CKEditor5 CI builds.",
|
|
5
|
+
"keywords": [],
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"node-fetch": "^2.6.7",
|
|
8
|
+
"slack-notify": "^0.1.7"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=14.0.0",
|
|
12
|
+
"npm": ">=5.7.1"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"bin",
|
|
16
|
+
"lib"
|
|
17
|
+
],
|
|
18
|
+
"bin": {
|
|
19
|
+
"ckeditor5-dev-ci-notify-travis-status": "bin/notifytravisstatus.js"
|
|
20
|
+
},
|
|
21
|
+
"author": "CKSource (http://cksource.com/)",
|
|
22
|
+
"license": "GPL-2.0-or-later",
|
|
23
|
+
"homepage": "https://github.com/ckeditor/ckeditor5-dev/tree/master/packages/ckeditor5-dev-ci",
|
|
24
|
+
"bugs": "https://github.com/ckeditor/ckeditor5/issues",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/ckeditor/ckeditor5-dev.git",
|
|
28
|
+
"directory": "packages/ckeditor5-dev-ci"
|
|
29
|
+
}
|
|
30
|
+
}
|