Files
vibn-agent-runner/vibn-frontend/scripts/provision-workspace-gcs.ts

87 lines
3.1 KiB
TypeScript

/**
* One-shot: run ensureWorkspaceGcsProvisioned() for a specific workspace
* slug against PROD GCP + PROD Postgres. Idempotent — safe to re-run.
*
* Unlike scripts/smoke-storage-e2e.ts this does NOT clean up; the whole
* point is to persist the workspace's provisioned state into the DB.
*
* Usage:
* cd vibn-frontend
* npx -y dotenv-cli -e ../.google.env -e .env.local -- \
* npx tsx scripts/provision-workspace-gcs.ts <slug>
*
* Required env:
* GOOGLE_SERVICE_ACCOUNT_KEY_B64 (from ../.google.env)
* DATABASE_URL (from .env.local, points at prod vibn-postgres)
* VIBN_SECRETS_KEY (from .env.local, ≥16 chars)
*/
import { queryOne } from '../lib/db-postgres';
import { ensureWorkspaceGcsProvisioned } from '../lib/workspace-gcs';
import type { VibnWorkspace } from '../lib/workspaces';
async function main(): Promise<void> {
const slug = process.argv[2];
if (!slug) {
console.error('Usage: tsx scripts/provision-workspace-gcs.ts <workspace-slug>');
process.exit(2);
}
console.log('━'.repeat(72));
console.log(` Provision GCS for workspace: ${slug}`);
console.log('━'.repeat(72));
// Fetch the current row.
const ws = await queryOne<VibnWorkspace>(
`SELECT * FROM vibn_workspaces WHERE slug = $1`,
[slug],
);
if (!ws) {
console.error(`No vibn_workspaces row found for slug=${slug}`);
process.exit(1);
}
console.log(` id : ${ws.id}`);
console.log(` name : ${ws.name}`);
console.log(` owner_user_id : ${ws.owner_user_id}`);
// @ts-expect-error — new columns not yet in VibnWorkspace type
console.log(` gcp_status : ${ws.gcp_provision_status ?? 'pending'}`);
console.log('');
console.log('Running ensureWorkspaceGcsProvisioned()…');
const result = await ensureWorkspaceGcsProvisioned(ws);
console.log('');
console.log('━'.repeat(72));
console.log(' RESULT');
console.log('━'.repeat(72));
console.log(` status : ${result.status}`);
console.log(` SA : ${result.serviceAccountEmail}`);
console.log(` bucket : ${result.bucket.name}`);
console.log(` location : ${result.bucket.location}`);
console.log(` created : ${result.bucket.timeCreated ?? '(pre-existing)'}`);
console.log(` HMAC accessId : ${result.hmac.accessId}`);
console.log('');
// Re-read to confirm persistence.
const after = await queryOne<Record<string, unknown>>(
`SELECT gcp_service_account_email,
CASE WHEN gcp_service_account_key_enc IS NOT NULL THEN '<enc '||length(gcp_service_account_key_enc)||' b64>' ELSE 'null' END AS sa_key,
gcs_default_bucket_name,
gcs_hmac_access_id,
CASE WHEN gcs_hmac_secret_enc IS NOT NULL THEN '<enc '||length(gcs_hmac_secret_enc)||' b64>' ELSE 'null' END AS hmac_secret,
gcp_provision_status,
gcp_provision_error
FROM vibn_workspaces WHERE id = $1`,
[ws.id],
);
console.log('DB row after:');
console.log(JSON.stringify(after, null, 2));
process.exit(0);
}
main().catch(err => {
console.error('[provision-workspace-gcs] FAILED:', err);
process.exit(1);
});