feat(curriculum): implement selective build mode for curriculum processing (#63081)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Sem Bauke
2025-11-07 12:24:11 +01:00
committed by GitHub
parent 92cf2228ee
commit 52aa25b991
3 changed files with 41 additions and 17 deletions

View File

@@ -338,13 +338,18 @@ export async function parseCurriculumStructure(filter?: Filter) {
export async function buildCurriculum(lang: string, filters?: Filter) {
const contentDir = getContentDir(lang);
const fccSuperblock = process.env.FCC_SUPERBLOCK;
const combinedFilters: Filter | undefined = fccSuperblock
? { ...filters, superBlock: fccSuperblock }
: filters;
const builder = new SuperblockCreator(
getBlockCreator(lang, !isEmpty(filters))
getBlockCreator(lang, !isEmpty(combinedFilters))
);
const { fullSuperblockList, certifications } =
await parseCurriculumStructure(filters);
await parseCurriculumStructure(combinedFilters);
const fullCurriculum: {
[key: string]: unknown;
@@ -357,7 +362,6 @@ export async function buildCurriculum(lang: string, filters?: Filter) {
const superOrder = getSuperOrder(name);
const upcomingSuperOrder = getSuperOrder(name, true);
// If a superblock is not in either order list it should not exist.
if (isUndefined(superOrder) && isUndefined(upcomingSuperOrder)) {
throw Error(`Invalid superBlock: ${name}`);
}
@@ -365,8 +369,8 @@ export async function buildCurriculum(lang: string, filters?: Filter) {
});
for (const superblock of liveSuperblocks) {
fullCurriculum[superblock.name] =
await builder.processSuperblock(superblock);
const processedSuperblock = await builder.processSuperblock(superblock);
fullCurriculum[superblock.name] = processedSuperblock;
}
for (const cert of certifications) {

View File

@@ -73,20 +73,27 @@ export function filterByBlock<T extends { blocks: { dashedName: string }[] }>(
}
/**
* Filters the superblocks array to only include the superblock with the specified name.
* Filters the superblocks array to only include superblocks with the specified name(s).
* If no superBlock is provided, returns the original superblocks array.
* Supports comma-separated superblock names for filtering multiple superblocks.
*
* @param {Array<Object>} superblocks - Array of superblock objects.
* @param {Object} [options] - Options object
* @param {string} [options.superBlock] - The name of the superblock to filter for.
* @returns {Array<Object>} Filtered array of superblocks containing only the specified superblock, or the original array if superBlock is not provided.
* @param {string} [options.superBlock] - The name(s) of the superblock(s) to filter for (comma-separated for multiple).
* @returns {Array<Object>} Filtered array of superblocks containing only the specified superblock(s), or the original array if superBlock is not provided.
*/
export function filterBySuperblock<T extends { name: string }>(
superblocks: T[],
{ superBlock }: { superBlock?: string } = {}
): T[] {
if (!superBlock) return superblocks;
return superblocks.filter(({ name }) => name === superBlock);
const superBlockList = superBlock
.split(',')
.map(s => s.trim())
.filter(s => s.length > 0);
return superblocks.filter(({ name }) => superBlockList.includes(name));
}
/**
@@ -175,6 +182,12 @@ export function closestFilters(
): Filter | undefined {
if (target?.superBlock) {
const superblockNames = superblocks.map(({ name }) => name);
// If there are multiple superblocks, do not attempt to find a closest match.
if (target.superBlock.includes(',')) {
return target;
}
return {
...target,
superBlock: closestMatch(target.superBlock, superblockNames)

View File

@@ -15,16 +15,23 @@ import {
const globalConfigPath = path.resolve(__dirname, '../../../shared-dist/config');
// We are defaulting to English because the ids for the challenges are same
// across all languages.
const isSelectiveBuild = !!process.env.FCC_SUPERBLOCK;
void getChallengesForLang('english')
.then(result => {
buildExtCurriculumDataV1(
result as unknown as CurriculumV1<CurriculumPropsV1>
);
buildExtCurriculumDataV2(
result as unknown as CurriculumV2<CurriculumPropsV2>
);
if (!isSelectiveBuild) {
console.log('Building external curriculum data...');
buildExtCurriculumDataV1(
result as unknown as CurriculumV1<CurriculumPropsV1>
);
buildExtCurriculumDataV2(
result as unknown as CurriculumV2<CurriculumPropsV2>
);
} else {
console.log(
'Skipping external curriculum build (selective build mode active)'
);
}
return result;
})
.then(JSON.stringify)