#!/usr/bin/env node // ci-export-env.mjs [environment] // // CI's counterpart to scripts/export-env: prints an Infisical environment // (default `staging`) as dotenv on stdout, in the same quoting export-env uses. // It logs in as the `convexmonorepo-ci` machine identity through Universal Auth, using // INFISICAL_CLIENT_ID and INFISICAL_CLIENT_SECRET from the job's Gitea secrets, // and reads the project and host from .infisical.json. Plain Node, no CLI to // install, so it runs in every job whether or not Bun is set up. import { readFile } from 'node:fs/promises'; const environment = process.argv[2] ?? 'staging'; const { INFISICAL_CLIENT_ID: clientId, INFISICAL_CLIENT_SECRET: clientSecret } = process.env; const fail = (message) => { console.error(`ci-export-env: ${message}`); process.exit(1); }; if (!clientId || !clientSecret) fail('INFISICAL_CLIENT_ID and INFISICAL_CLIENT_SECRET must be set.'); const { workspaceId, domain } = JSON.parse( await readFile(new URL('../.infisical.json', import.meta.url), 'utf8'), ); const request = async (path, init) => { const response = await fetch(`${domain}${path}`, init); if (!response.ok) fail(`${init?.method ?? 'GET'} ${path} returned ${response.status}.`); return response.json(); }; const { accessToken } = await request('/v1/auth/universal-auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientId, clientSecret }), }); const query = new URLSearchParams({ workspaceId, environment, secretPath: '/', expandSecretReferences: 'true', include_imports: 'true', }); const { secrets, imports = [] } = await request(`/v3/secrets/raw?${query}`, { headers: { Authorization: `Bearer ${accessToken}` }, }); // Imported secrets first so the environment's own values win. const values = new Map(); for (const { secretKey, secretValue } of [ ...imports.flatMap((folder) => folder.secrets), ...secrets, ]) values.set(secretKey, secretValue); const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`; for (const [key, value] of [...values].sort(([a], [b]) => a.localeCompare(b))) process.stdout.write(`${key}=${quote(value)}\n`);