diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index a7a9bd2..88115f5 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -115,7 +115,15 @@ jobs: - name: Sync vocab course content if: steps.vocab_course_changes.outputs.changed == 'true' || steps.vocab_course_changes.outputs.force_deploy == 'true' run: | + # Decide whether to actually run the phase3 update on the server. + # By default we run the deploy script in --dry-run mode. To enable the + # actual run set the secret PHASE3_UPDATE=1 in the repo settings. + RUN_FLAG="--dry-run" + if [ "${{ secrets.PHASE3_UPDATE:-}}" = "1" ]; then + RUN_FLAG="" + fi + ssh -i ~/.ssh/id_ed25519 \ -p "${{ secrets.PROD_PORT }}" \ "${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \ - "cd /opt/yourpart && npm --prefix backend run sync:vocab-courses" + "cd /opt/yourpart && npm --prefix backend run sync:vocab-courses && if [ -x backend/scripts/deploy-phase3-update.sh ]; then bash backend/scripts/deploy-phase3-update.sh $RUN_FLAG; else echo 'deploy-phase3-update.sh not found or not executable'; fi" diff --git a/backend/scripts/fix-bisaya-review-field.mjs b/backend/scripts/fix-bisaya-review-field.mjs new file mode 100644 index 0000000..8ff9936 --- /dev/null +++ b/backend/scripts/fix-bisaya-review-field.mjs @@ -0,0 +1,50 @@ +#!/usr/bin/env node +import fs from 'fs/promises'; +import path from 'path'; + +const ROOT = path.resolve(process.cwd()); +const SEARCH_DIR = path.join(ROOT, 'backend', 'scripts'); +const exts = new Set(['.js', '.mjs', '.cjs', '.json']); + +const APPLY = process.argv.includes('--apply'); + +async function* walk(dir) { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const e of entries) { + const full = path.join(dir, e.name); + if (e.isDirectory()) { + yield* walk(full); + } else if (exts.has(path.extname(e.name))) { + yield full; + } + } +} + +const re = /\breview\s*:\s*true\b/g; +const reCompact = /\breview\s*:\s*true\s*,?/g; + +let files = []; +for await (const f of walk(SEARCH_DIR)) files.push(f); + +let found = 0; +for (const file of files) { + const txt = await fs.readFile(file, 'utf8'); + if (!re.test(txt)) continue; + found++; + const newTxt = txt.replace(reCompact, "type: 'review',"); + console.log('---', file); + const oldMatches = txt.match(/.{0,80}review\s*:\s*true.{0,80}/g) || []; + const newMatches = newTxt.match(/.{0,80}type:\s*'review'.{0,80}/g) || []; + for (let i = 0; i < Math.max(oldMatches.length, newMatches.length); i++) { + console.log(' -', (oldMatches[i] || '').trim()); + console.log(' +', (newMatches[i] || '').trim()); + } + if (APPLY) { + await fs.writeFile(file, newTxt, 'utf8'); + console.log(' [wrote]'); + } else { + console.log(' [dry-run]'); + } +} + +console.log(`${found} file(s) with \`review: true\` ${APPLY ? 'updated' : 'would be changed (dry-run)'}.`);