ckeditor5-image-upload-base64
Version:
The development environment of CKEditor 5 – the best browser-based rich text editor.
161 lines (121 loc) • 5.4 kB
JavaScript
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/
/* eslint-env node */
;
const childProcess = require( 'child_process' );
const crypto = require( 'crypto' );
const fs = require( 'fs' );
const path = require( 'path' );
const glob = require( 'glob' );
const failedChecks = {
dependency: new Set(),
unitTests: new Set(),
codeCoverage: new Set()
};
const RED = '\x1B[0;31m';
const YELLOW = '\x1B[33;1m';
const NO_COLOR = '\x1B[0m';
const travis = {
_lastTimerId: null,
_lastStartTime: null,
foldStart( packageName, foldLabel ) {
console.log( `travis_fold:start:${ packageName }${ YELLOW }${ foldLabel }${ NO_COLOR }` );
this._timeStart();
},
foldEnd( packageName ) {
this._timeFinish();
console.log( `\ntravis_fold:end:${ packageName }\n` );
},
_timeStart() {
const nanoSeconds = process.hrtime.bigint();
this._lastTimerId = crypto.createHash( 'md5' ).update( nanoSeconds.toString() ).digest( 'hex' );
this._lastStartTime = nanoSeconds;
// Intentional direct write to stdout, to manually control EOL.
process.stdout.write( `travis_time:start:${ this._lastTimerId }\r\n` );
},
_timeFinish() {
const travisEndTime = process.hrtime.bigint();
const duration = travisEndTime - this._lastStartTime;
// Intentional direct write to stdout, to manually control EOL.
process.stdout.write( `\ntravis_time:end:${ this._lastTimerId }:start=${ this._lastStartTime },` +
`finish=${ travisEndTime },duration=${ duration }\r\n` );
}
};
childProcess.execSync( 'rm -r -f .nyc_output' );
childProcess.execSync( 'mkdir .nyc_output' );
childProcess.execSync( 'rm -r -f .out' );
childProcess.execSync( 'mkdir .out' );
const packages = childProcess.execSync( 'ls packages -1', {
encoding: 'utf8'
} ).toString().trim().split( '\n' );
for ( const fullPackageName of packages ) {
const simplePackageName = fullPackageName.replace( /^ckeditor5?-/, '' );
const foldLabelName = 'pkg-' + simplePackageName;
travis.foldStart( foldLabelName, `Testing ${ fullPackageName }${ NO_COLOR }` );
appendCoverageReport();
runSubprocess( 'npx', [ 'ckeditor5-dev-tests-check-dependencies', `packages/${ fullPackageName }` ], simplePackageName, 'dependency',
'have a dependency problem' );
const testArguments = [ 'run', 'test', '-f', simplePackageName, '--reporter=dots', '--production', '--coverage' ];
runSubprocess( 'yarn', testArguments, simplePackageName, 'unitTests', 'failed to pass unit tests' );
childProcess.execSync( 'cp coverage/*/coverage-final.json .nyc_output' );
const nyc = [ 'nyc', 'check-coverage', '--branches', '100', '--functions', '100', '--lines', '100', '--statements', '100' ];
runSubprocess( 'npx', nyc, simplePackageName, 'codeCoverage', 'doesn\'t have required code coverage' );
travis.foldEnd( foldLabelName );
}
console.log( 'Uploading combined code coverage report…' );
// Comparing "organization/ckeditor5" and "ckeditor/ckeditor5".
if ( process.env.TRAVIS_PULL_REQUEST_SLUG === process.env.TRAVIS_REPO_SLUG ) {
childProcess.execSync( 'npx coveralls < .out/combined_lcov.info' );
} else {
console.log( 'Since the PR comes from the community, we do not upload code coverage report.' );
console.log( 'Read more why: https://github.com/ckeditor/ckeditor5/issues/7745.' );
}
console.log( 'Done' );
if ( Object.values( failedChecks ).some( checksSet => checksSet.size > 0 ) ) {
console.log( '\n---\n' );
showFailedCheck( 'dependency', 'The following packages have dependencies that are not included in its package.json' );
showFailedCheck( 'unitTests', 'The following packages did not pass unit tests' );
showFailedCheck( 'codeCoverage', 'The following packages did not provide required code coverage' );
process.exit( 1 ); // Exit code 1 will break the CI build.
}
/*
* @param {String} binaryName - Name of a CLI binary to be called.
* @param {String[]} cliArguments - An array of arguments to be passed to the `binaryName`.
* @param {String} packageName - Checked package name.
* @param {String} checkName - A key associated with the problem in the `failedChecks` dictionary.
* @param {String} failMessage - Message to be shown if check failed.
*/
function runSubprocess( binaryName, cliArguments, packageName, checkName, failMessage ) {
const subprocess = childProcess.spawnSync( binaryName, cliArguments, {
encoding: 'utf8',
shell: true
} );
console.log( subprocess.stdout );
if ( subprocess.stderr ) {
console.log( subprocess.stderr );
}
if ( subprocess.status !== 0 ) {
failedChecks.unitTests.add( packageName );
console.log( `💥 ${ RED }${ packageName }${ NO_COLOR } ` + failMessage + ' 💥' );
}
}
function showFailedCheck( checkKey, errorMessage ) {
const failedPackages = failedChecks[ checkKey ];
if ( failedPackages.size ) {
console.log( `${ errorMessage }: ${ RED }${ Array.from( failedPackages.values() ).join( ', ' ) }${ NO_COLOR }` );
}
}
function appendCoverageReport() {
// Appends coverage data to the combined code coverage info file. It's used because all the results
// needs to be uploaded at once (#6742).
const matches = glob.sync( 'coverage/*/lcov.info' );
matches.forEach( filePath => {
const buffer = fs.readFileSync( filePath );
fs.writeFileSync( [ '.out', 'combined_lcov.info' ].join( path.sep ), buffer, {
flag: 'as'
} );
} );
}