// Replaces #{TOKEN-NAME}# with values from SECRETS/VARIABLES // Converts: #{api-base-url}# -> API_BASE_URL (uppercase, - to _) // Special: #{buildid}# -> RUN_ID const fs = require('fs'); const path = require('path'); function replaceInFile(file, mapToken) { let data = fs.readFileSync(file, 'utf8'); const re = /#\{(.*?)\}#/g; let changed = false; data = data.replace(re, (_, raw) => { const token = (raw || '').replace(/-/g, '_').toUpperCase(); const val = mapToken(token); if (val == null || val === '') { return `#{${raw}}#`; // leave unchanged, will error later } changed = true; return String(val); }); if (changed) { fs.writeFileSync(file, data, 'utf8'); } return changed; } (async () => { // DEFENSIVE: handle null/undefined gracefully let secrets = {}; let variables = {}; try { secrets = JSON.parse(process.env.SECRETS || '{}'); } catch (e) { console.warn('āš ļø Failed to parse SECRETS:', e.message); } try { variables = JSON.parse(process.env.VARIABLES || '{}'); } catch (e) { console.warn('āš ļø Failed to parse VARIABLES:', e.message); } const RUN_ID = process.env.RUN_ID || process.env.GITHUB_RUN_ID || ''; console.log(`šŸ“¦ Loaded ${Object.keys(secrets).length} secrets, ${Object.keys(variables).length} variables`); const mapToken = (token) => { if (token === 'BUILDID') return RUN_ID; // Check variables first, then secrets if (variables && variables[token] != null) { return variables[token]; } if (secrets && secrets[token] != null) { return secrets[token]; } return null; }; const files = [ 'artifacts/api/appsettings.Production.json', 'artifacts/ui/appsettings.Production.json' ].map(f => path.resolve(f)).filter(f => fs.existsSync(f)); if (files.length === 0) { console.error('āŒ No appsettings.Production.json files found in artifacts/'); process.exit(1); } console.log(`šŸ”Ž Tokenizing ${files.length} file(s):`); files.forEach(f => console.log(` - ${f}`)); const missing = new Set(); // First pass: replace tokens for (const file of files) { console.log(`\nšŸ“ Processing: ${path.basename(file)}`); replaceInFile(file, mapToken); } // Second pass: check for remaining tokens for (const file of files) { const content = fs.readFileSync(file, 'utf8'); const reLeft = /#\{(.*?)\}#/g; let m; while ((m = reLeft.exec(content))) { const token = (m[1] || '').replace(/-/g, '_').toUpperCase(); missing.add(token); } } if (missing.size > 0) { console.error(`\nāŒ Missing values for tokens: ${Array.from(missing).join(', ')}`); console.error('\nšŸ’” Make sure these secrets/variables are configured in Gitea repo settings:'); console.error(' Settings → Secrets → Add secret'); process.exit(1); } console.log('\nāœ… Tokenization complete. All placeholders replaced.'); })().catch(err => { console.error('āŒ Error during tokenization:'); console.error(err.stack || err.message || String(err)); process.exit(1); });