From 41fb69417cd2847731b19ebfbd8dfffc55741564 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Thu, 21 Jul 2022 08:13:47 -0700 Subject: [PATCH] feat(tools): audit i18n challenges (#46968) * feat(tools): audit i18n challenges Co-authored-by: Oliver Eyton-Williams --- .github/workflows/i18n-builds.yml | 29 ++++++++++ package.json | 1 + tools/challenge-auditor/index.ts | 92 +++++++++++++++++++++++++++++++ tsconfig.json | 1 + 4 files changed, 123 insertions(+) create mode 100644 .github/workflows/i18n-builds.yml create mode 100644 tools/challenge-auditor/index.ts diff --git a/.github/workflows/i18n-builds.yml b/.github/workflows/i18n-builds.yml new file mode 100644 index 00000000000..d82d8fbaf09 --- /dev/null +++ b/.github/workflows/i18n-builds.yml @@ -0,0 +1,29 @@ +name: i18n Build Validation +on: + push: + branches: + - main + +jobs: + ci: + name: Validate i18n Builds + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x] + + steps: + - name: Checkout Source Files + uses: actions/checkout@v3 + + - name: Use Node.js v${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Install Dependencies + run: npm ci + + - name: Validate Challenge Files + run: npm run audit-challenges diff --git a/package.json b/package.json index c72c8b962e0..4b0466111d4 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "tools/ui-components" ], "scripts": { + "audit-challenges": "ts-node tools/challenge-auditor/index.ts", "analyze-bundle": "webpack-bundle-analyzer", "prebuild": "npm-run-all create:*", "build": "npm-run-all -p build:*", diff --git a/tools/challenge-auditor/index.ts b/tools/challenge-auditor/index.ts new file mode 100644 index 00000000000..92869bc8070 --- /dev/null +++ b/tools/challenge-auditor/index.ts @@ -0,0 +1,92 @@ +import { access, readdir } from 'fs/promises'; +import { join } from 'path'; + +import { availableLangs, auditedCerts } from '../../config/i18n/all-langs'; + +const superBlockFolderMap = { + 'responsive-web-design': '01-responsive-web-design', + 'javascript-algorithms-and-data-structures': + '02-javascript-algorithms-and-data-structures', + 'front-end-development-libraries': '03-front-end-development-libraries', + 'data-visualization': '04-data-visualization', + 'back-end-development-and-apis': '05-back-end-development-and-apis', + 'quality-assurance': '06-quality-assurance', + 'scientific-computing-with-python': '07-scientific-computing-with-python', + 'data-analysis-with-python': '08-data-analysis-with-python', + 'information-security': '09-information-security', + 'machine-learning-with-python': '10-machine-learning-with-python', + 'coding-interview-prep': '11-coding-interview-prep', + 'relational-database': '13-relational-database', + '2022/responsive-web-design': '14-responsive-web-design-22', + '2022/javascript-algorithms-and-data-structures': + '15-javascript-algorithms-and-data-structures-22' +}; + +// These blocks are in the incorrect superblock. They should be moved but, for +// the audit, we just ignore them. +const blocksThatNeedToMove = ['d3-dashboard']; + +void (async () => { + let actionShouldFail = false; + const languagesFailing: string[] = []; + const englishCurriculumDirectory = join( + process.cwd(), + 'curriculum', + 'challenges', + 'english' + ); + const englishFilePaths: string[] = []; + const englishSuperblocks = await readdir(englishCurriculumDirectory); + for (const englishSuperblock of englishSuperblocks) { + const englishBlocks = await readdir( + join(englishCurriculumDirectory, englishSuperblock) + ); + for (const englishBlock of englishBlocks) { + const englishChallenges = await readdir( + join(englishCurriculumDirectory, englishSuperblock, englishBlock) + ); + for (const englishChallenge of englishChallenges) { + englishFilePaths.push( + join(englishSuperblock, englishBlock, englishChallenge) + ); + } + } + } + const langsToCheck = availableLangs.curriculum.filter( + lang => lang !== 'english' + ); + for (const lang of langsToCheck) { + let languageIsFailing = false; + console.log(`\n=== ${lang} ===`); + const certs = auditedCerts[lang as keyof typeof auditedCerts]; + const langCurriculumDirectory = join( + process.cwd(), + 'curriculum', + 'challenges', + lang + ); + const auditedFiles = englishFilePaths.filter(file => + certs.some(cert => file.startsWith(superBlockFolderMap[cert])) + ); + for (const file of auditedFiles) { + if (blocksThatNeedToMove.some(block => file.includes(`/${block}/`))) { + continue; + } + const filePath = join(langCurriculumDirectory, file); + const fileExists = await access(filePath) + .then(() => true) + .catch(() => false); + if (!fileExists) { + console.log(`${filePath} does not exist.`); + languageIsFailing = true; + } + } + if (languageIsFailing) { + languagesFailing.push(lang); + actionShouldFail = true; + } else { + console.log(`All expected files found.`); + } + } + actionShouldFail ? process.exit(1) : process.exit(0); +})(); diff --git a/tsconfig.json b/tsconfig.json index f0658b8cac5..9e2f6e026d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "client/src/**/*", "client/utils/**/*", "curriculum/*.test.ts", + "tools/challenge-auditor/index.ts", "tools/challenge-editor/**/*", "tools/challenge-helper-scripts/**/*.ts", "tools/scripts/**/*.ts"