Skip to content

Commit

Permalink
Separated feature tests on ci into batches.
Browse files Browse the repository at this point in the history
  • Loading branch information
przemyslaw-zan committed Sep 18, 2024
1 parent 08f77fd commit 8b2cd89
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 19 deletions.
12 changes: 6 additions & 6 deletions .circleci/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ jobs:

workflows:
version: 2
# `cke5_tests_framework` and `cke5_tests_features` jobs are generated by the `scripts/ci/generate-config-tests.js` script.
# `cke5_tests_framework` and `cke5_tests_features_batch_n` jobs are generated by the `scripts/ci/generate-config-tests.js` script.
main:
when:
and:
Expand All @@ -275,15 +275,15 @@ workflows:
branches:
ignore:
- stable
- cke5_tests_features:
- cke5_tests_features_batch_n:
filters:
branches:
ignore:
- stable
- cke5_coverage:
requires:
- cke5_tests_framework
- cke5_tests_features
- cke5_tests_features_batch_n
filters:
branches:
only:
Expand All @@ -304,7 +304,7 @@ workflows:
- cke5_trigger_uber_ci:
requires:
- cke5_tests_framework
- cke5_tests_features
- cke5_tests_features_batch_n
- cke5_coverage
- cke5_validators
- cke5_manual
Expand All @@ -316,7 +316,7 @@ workflows:
- cke5_trigger_release_process:
requires:
- cke5_tests_framework
- cke5_tests_features
- cke5_tests_features_batch_n
- cke5_validators
- cke5_manual
- release_prepare
Expand All @@ -336,7 +336,7 @@ workflows:
when: << pipeline.parameters.isNightly >>
jobs:
- cke5_tests_framework
- cke5_tests_features
- cke5_tests_features_batch_n
- cke5_validators
- cke5_manual
- release_prepare
Expand Down
112 changes: 99 additions & 13 deletions scripts/ci/generate-circleci-configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ const IS_COMMUNITY_PR = require( './is-community-pr' );
const CKEDITOR5_ROOT_DIRECTORY = upath.join( __dirname, '..', '..' );
const CIRCLECI_CONFIGURATION_DIRECTORY = upath.join( CKEDITOR5_ROOT_DIRECTORY, '.circleci' );

const FEATURE_BATCH_NAME_PLACEHOLDER = 'cke5_tests_features_batch_n';

/**
* This variable determines amount and size of feature test batches.
*
* If there are more feature packages than the sum of all batches defined here,
* one batch will be automatically added to cover remaining tests.
*/
const FEATURE_BATCH_SIZES = [
30
];

const NON_FULL_COVERAGE_PACKAGES = [
'ckeditor5-minimap'
];
Expand Down Expand Up @@ -67,6 +79,29 @@ const persistToWorkspace = fileName => ( {
await fs.readFile( upath.join( CIRCLECI_CONFIGURATION_DIRECTORY, 'template.yml' ) )
);

const featureTestBatches = featurePackages.reduce( ( output, packageName, packageIndex ) => {
let currentBatch = FEATURE_BATCH_SIZES.findIndex( ( batchSize, batchIndex, allBatches ) => {
return packageIndex < allBatches.slice( 0, batchIndex + 1 ).reduce( ( a, b ) => a + b );
} );

// Additional batch for the remaining tests not included in defined batch sizes.
if ( currentBatch === -1 ) {
currentBatch = FEATURE_BATCH_SIZES.length;
}

if ( !output[ currentBatch ] ) {
output[ currentBatch ] = [];
}

output[ currentBatch ].push( packageName );

return output;
}, [] );

const featureTestBatchNames = featureTestBatches.map( ( batch, batchIndex ) => {
return FEATURE_BATCH_NAME_PLACEHOLDER.replace( /(?<=_)n$/, batchIndex + 1 );
} );

config.jobs.cke5_tests_framework = {
machine: true,
steps: [
Expand All @@ -81,19 +116,60 @@ const persistToWorkspace = fileName => ( {
]
};

config.jobs.cke5_tests_features = {
machine: true,
steps: [
...bootstrapCommands(),
prepareCodeCoverageDirectories(),
...generateTestSteps( featurePackages, {
checkCoverage: true,
coverageFile: '.out/combined_features.info'
} ),
'community_verification_command',
persistToWorkspace( 'combined_features.info' )
]
};
// Adding batches to the root `jobs`.
featureTestBatches.forEach( ( batch, batchIndex ) => {
config.jobs[ featureTestBatchNames[ batchIndex ] ] = {
machine: true,
steps: [
...bootstrapCommands(),
prepareCodeCoverageDirectories(),
...generateTestSteps( batch, {
checkCoverage: true,
coverageFile: '.out/combined_features.info'
} ),
'community_verification_command',
persistToWorkspace( 'combined_features.info' )
]
};
} );

Object.values( config.workflows ).forEach( workflow => {
if ( !( workflow instanceof Object ) ) {
return;
}

if ( !workflow.jobs ) {
return;
}

// Replacing the placeholder batch names in `requires` arrays in `workflows`.
workflow.jobs.forEach( job => {
const { requires } = Object.values( job )[ 0 ];

if ( requires ) {
replacePlaceholderBatchNameInArray( requires, featureTestBatchNames );
}
} );

// Replacing the placeholder batch names in `jobs` arrays in `workflows`.
replacePlaceholderBatchNameInArray( workflow.jobs, featureTestBatchNames );

// Replacing the placeholder batch objects in `jobs` arrays in `workflows`.
const placeholderJobIndex = workflow.jobs.findIndex( job => job[ FEATURE_BATCH_NAME_PLACEHOLDER ] );

if ( placeholderJobIndex === -1 ) {
return;
}

const placeholderJobContent = workflow.jobs[ placeholderJobIndex ][ FEATURE_BATCH_NAME_PLACEHOLDER ];
const newBatchJobs = featureTestBatchNames.map( featureTestBatchName => {
return {
[ featureTestBatchName ]: placeholderJobContent
};
} );

workflow.jobs.splice( placeholderJobIndex, 1, ...newBatchJobs );
} );

if ( IS_COMMUNITY_PR ) {
// CircleCI does not understand custom cloning when a PR comes from the community.
Expand Down Expand Up @@ -158,6 +234,16 @@ function replaceShortCheckout( config, jobName ) {
} );
}

function replacePlaceholderBatchNameInArray( array, featureTestBatchNames ) {
const placeholderIndex = array.findIndex( item => item === FEATURE_BATCH_NAME_PLACEHOLDER );

if ( placeholderIndex === -1 ) {
return;
}

array.splice( placeholderIndex, 1, ...featureTestBatchNames );
}

/**
* This type partially covers supported options on CircleCI.
* To see the complete guide, follow: https://circleci.com/docs/configuration-reference.
Expand Down

0 comments on commit 8b2cd89

Please sign in to comment.