mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
refactor: use pre-built curriculum when starting client (#65878)
This commit is contained in:
committed by
GitHub
parent
052416e5bf
commit
990b64d229
@@ -2,10 +2,6 @@ const path = require('path');
|
|||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
const {
|
|
||||||
getChallengesForLang
|
|
||||||
} = require('@freecodecamp/curriculum/get-challenges');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getBlockCreator,
|
getBlockCreator,
|
||||||
getSuperblocks,
|
getSuperblocks,
|
||||||
@@ -14,12 +10,14 @@ const {
|
|||||||
const {
|
const {
|
||||||
getContentDir,
|
getContentDir,
|
||||||
getBlockStructure,
|
getBlockStructure,
|
||||||
getSuperblockStructure
|
getSuperblockStructure,
|
||||||
|
CURRICULUM_DIR
|
||||||
} = require('@freecodecamp/curriculum/file-handler');
|
} = require('@freecodecamp/curriculum/file-handler');
|
||||||
const {
|
const {
|
||||||
transformSuperBlock
|
transformSuperBlock
|
||||||
} = require('@freecodecamp/curriculum/build-superblock');
|
} = require('@freecodecamp/curriculum/build-superblock');
|
||||||
const { getSuperOrder } = require('@freecodecamp/curriculum/super-order');
|
const { getSuperOrder } = require('@freecodecamp/curriculum/super-order');
|
||||||
|
const { readFile } = require('fs/promises');
|
||||||
|
|
||||||
const curriculumLocale = process.env.CURRICULUM_LOCALE || 'english';
|
const curriculumLocale = process.env.CURRICULUM_LOCALE || 'english';
|
||||||
|
|
||||||
@@ -72,7 +70,12 @@ exports.replaceChallengeNodes = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.buildChallenges = async function buildChallenges() {
|
exports.buildChallenges = async function buildChallenges() {
|
||||||
const curriculum = await getChallengesForLang(curriculumLocale);
|
const curriculum = JSON.parse(
|
||||||
|
await readFile(
|
||||||
|
path.resolve(CURRICULUM_DIR, 'generated', 'curriculum.json'),
|
||||||
|
'utf-8'
|
||||||
|
)
|
||||||
|
);
|
||||||
const superBlocks = Object.keys(curriculum);
|
const superBlocks = Object.keys(curriculum);
|
||||||
const blocks = superBlocks
|
const blocks = superBlocks
|
||||||
.map(superBlock => curriculum[superBlock].blocks)
|
.map(superBlock => curriculum[superBlock].blocks)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { resolve } from 'path';
|
import { resolve } from 'node:path';
|
||||||
|
import assert from 'node:assert';
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
|
|
||||||
import { availableLangs } from '@freecodecamp/shared/config/i18n';
|
import { availableLangs } from '@freecodecamp/shared/config/i18n';
|
||||||
@@ -7,20 +8,15 @@ config({ path: resolve(__dirname, '../../.env') });
|
|||||||
|
|
||||||
const curriculumLangs = availableLangs.curriculum;
|
const curriculumLangs = availableLangs.curriculum;
|
||||||
|
|
||||||
// checks that the CURRICULUM_LOCALE exists and is an available language
|
function isAllowedLang(lang: string): lang is (typeof curriculumLangs)[number] {
|
||||||
export function testedLang() {
|
return curriculumLangs.includes(lang as (typeof curriculumLangs)[number]);
|
||||||
if (process.env.CURRICULUM_LOCALE) {
|
|
||||||
if (curriculumLangs.includes(process.env.CURRICULUM_LOCALE)) {
|
|
||||||
return process.env.CURRICULUM_LOCALE;
|
|
||||||
} else {
|
|
||||||
throw Error(`${process.env.CURRICULUM_LOCALE} is not a supported language.
|
|
||||||
Before the site can be built, this language needs to be manually approved`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw Error('CURRICULUM_LOCALE must be set for testing');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert.ok(process.env.CURRICULUM_LOCALE);
|
||||||
|
assert.ok(isAllowedLang(process.env.CURRICULUM_LOCALE));
|
||||||
|
|
||||||
|
export const CURRICULUM_LOCALE = process.env.CURRICULUM_LOCALE;
|
||||||
|
|
||||||
export const SHOW_UPCOMING_CHANGES =
|
export const SHOW_UPCOMING_CHANGES =
|
||||||
process.env.SHOW_UPCOMING_CHANGES === 'true';
|
process.env.SHOW_UPCOMING_CHANGES === 'true';
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ if (typeof __dirname !== 'undefined') {
|
|||||||
__dirnameCompat = dirname(fileURLToPath(metaUrl));
|
__dirnameCompat = dirname(fileURLToPath(metaUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
const CURRICULUM_DIR = resolve(__dirnameCompat, '..');
|
export const CURRICULUM_DIR = resolve(__dirnameCompat, '..');
|
||||||
const I18N_CURRICULUM_DIR = resolve(
|
const I18N_CURRICULUM_DIR = resolve(
|
||||||
CURRICULUM_DIR,
|
CURRICULUM_DIR,
|
||||||
'i18n-curriculum',
|
'i18n-curriculum',
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import fs from 'fs';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import { getChallengesForLang } from '../get-challenges';
|
import { getChallengesForLang } from '../get-challenges';
|
||||||
|
import { CURRICULUM_LOCALE } from '../config';
|
||||||
|
|
||||||
const globalConfigPath = path.resolve(__dirname, '../../generated/');
|
const globalConfigPath = path.resolve(__dirname, '../../generated/');
|
||||||
|
|
||||||
void getChallengesForLang('english')
|
void getChallengesForLang(CURRICULUM_LOCALE)
|
||||||
.then(JSON.stringify)
|
.then(JSON.stringify)
|
||||||
.then(json => {
|
.then(json => {
|
||||||
fs.mkdirSync(globalConfigPath, { recursive: true });
|
fs.mkdirSync(globalConfigPath, { recursive: true });
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { configure } from '@freecodecamp/challenge-linter';
|
import { configure } from '@freecodecamp/challenge-linter';
|
||||||
import { testedLang } from './config';
|
import { CURRICULUM_LOCALE } from './config';
|
||||||
|
|
||||||
const CONFIG_PATH = path.resolve(__dirname, '../challenges/.markdownlint.yaml');
|
const CONFIG_PATH = path.resolve(__dirname, '../challenges/.markdownlint.yaml');
|
||||||
const { lintAll } = configure(CONFIG_PATH);
|
const { lintAll } = configure(CONFIG_PATH);
|
||||||
|
|
||||||
lintAll(`challenges/${testedLang()}/**/*.md`);
|
lintAll(`challenges/${CURRICULUM_LOCALE}/**/*.md`);
|
||||||
|
|||||||
@@ -4,12 +4,11 @@ vi.stubEnv('SHOW_UPCOMING_CHANGES', 'true');
|
|||||||
|
|
||||||
// We need to use dynamic imports here to ensure the environment variable is set
|
// We need to use dynamic imports here to ensure the environment variable is set
|
||||||
// before the module is loaded.
|
// before the module is loaded.
|
||||||
const { testedLang } = await import('../config.js');
|
const { CURRICULUM_LOCALE } = await import('../config.js');
|
||||||
const { getChallenges } = await import('./test-challenges.js');
|
const { getChallenges } = await import('./test-challenges.js');
|
||||||
|
|
||||||
describe('Daily Coding Challenges', async () => {
|
describe('Daily Coding Challenges', async () => {
|
||||||
const lang = testedLang();
|
const challenges = await getChallenges(CURRICULUM_LOCALE, {
|
||||||
const challenges = await getChallenges(lang, {
|
|
||||||
superBlock: 'dev-playground'
|
superBlock: 'dev-playground'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ describe('Daily Coding Challenges', async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// skip these for non-English for now.
|
// skip these for non-English for now.
|
||||||
if (lang !== 'english') continue;
|
if (CURRICULUM_LOCALE !== 'english') continue;
|
||||||
|
|
||||||
if (jsChallenge.title !== pyChallenge.title) {
|
if (jsChallenge.title !== pyChallenge.title) {
|
||||||
errors.push(
|
errors.push(
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { challengeSchemaValidator } from '../../schema/challenge-schema.js';
|
|||||||
import { curriculumSchemaValidator } from '../../schema/curriculum-schema.js';
|
import { curriculumSchemaValidator } from '../../schema/curriculum-schema.js';
|
||||||
import { validateMetaSchema } from '../../schema/meta-schema.js';
|
import { validateMetaSchema } from '../../schema/meta-schema.js';
|
||||||
import { getBlockStructure } from '../file-handler.js';
|
import { getBlockStructure } from '../file-handler.js';
|
||||||
import { FCC_CHALLENGE_ID, testedLang } from '../config.js';
|
import { FCC_CHALLENGE_ID, CURRICULUM_LOCALE } from '../config.js';
|
||||||
import ChallengeTitles from './utils/challenge-titles.js';
|
import ChallengeTitles from './utils/challenge-titles.js';
|
||||||
import MongoIds from './utils/mongo-ids.js';
|
import MongoIds from './utils/mongo-ids.js';
|
||||||
import createPseudoWorker from './utils/pseudo-worker.js';
|
import createPseudoWorker from './utils/pseudo-worker.js';
|
||||||
@@ -79,8 +79,7 @@ async function newPageContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function defineTestsForBlock(testFilter) {
|
export async function defineTestsForBlock(testFilter) {
|
||||||
const lang = testedLang();
|
const challenges = await getChallenges(CURRICULUM_LOCALE, testFilter);
|
||||||
const challenges = await getChallenges(lang, testFilter);
|
|
||||||
const nonCertificationChallenges = challenges.filter(
|
const nonCertificationChallenges = challenges.filter(
|
||||||
({ challengeType }) => challengeType !== 7
|
({ challengeType }) => challengeType !== 7
|
||||||
);
|
);
|
||||||
@@ -107,7 +106,7 @@ export async function defineTestsForBlock(testFilter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const challengeData = { meta, challenges, lang };
|
const challengeData = { meta, challenges, lang: CURRICULUM_LOCALE };
|
||||||
|
|
||||||
describe('Check challenges', async () => {
|
describe('Check challenges', async () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"tasks": {
|
"tasks": {
|
||||||
"build": {
|
"build": {
|
||||||
"outputs": ["dist/**", "generated/**"],
|
"outputs": ["dist/**", "generated/**"],
|
||||||
"env": ["FCC_*", "SHOW_UPCOMING_CHANGES"]
|
"env": ["FCC_*", "SHOW_UPCOMING_CHANGES", "CURRICULUM_LOCALE"]
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"passThroughEnv": ["VITEST_POOL_ID", "PUPPETEER_WS_ENDPOINT"],
|
"passThroughEnv": ["VITEST_POOL_ID", "PUPPETEER_WS_ENDPOINT"],
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ RUN cd api && pnpm prisma generate
|
|||||||
# following env vars.
|
# following env vars.
|
||||||
ARG SHOW_UPCOMING_CHANGES=false
|
ARG SHOW_UPCOMING_CHANGES=false
|
||||||
ENV SHOW_UPCOMING_CHANGES=$SHOW_UPCOMING_CHANGES
|
ENV SHOW_UPCOMING_CHANGES=$SHOW_UPCOMING_CHANGES
|
||||||
|
ARG CURRICULUM_LOCALE=english
|
||||||
|
ENV CURRICULUM_LOCALE=$CURRICULUM_LOCALE
|
||||||
|
|
||||||
RUN pnpm turbo -F=@freecodecamp/api build
|
RUN pnpm turbo -F=@freecodecamp/api build
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://v2-8-7.turborepo.dev/schema.json",
|
||||||
|
"extends": ["//"],
|
||||||
|
"tasks": {
|
||||||
|
"test": {
|
||||||
|
"env": ["CURRICULUM_LOCALE", "SHOW_UPCOMING_CHANGES"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user