From ebc33607a2b2c665df7cd4c1a739ff33edf260f5 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 3 Aug 2026 22:30:33 +0200 Subject: [PATCH] chore(ci): remove the one-off TML-3157 docs state migration The migration ran green on 2026-08-03 (run 30850338761): 7 resource rows re-staged from 'dev_runner' to the default Branch's id, deploy and smoke-check passed. The step and script were one-off by design. Signed-off-by: willbot Signed-off-by: Will Madden --- .github/workflows/deploy-docs.yml | 2 - scripts/migrate-docs-state-tml3157.ts | 99 --------------------------- 2 files changed, 101 deletions(-) delete mode 100644 scripts/migrate-docs-state-tml3157.ts diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 5e457bc58..11ca15a28 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -72,8 +72,6 @@ jobs: - name: Reset the production project (destroy-then-redeploy cutover) if: github.event_name == 'workflow_dispatch' && inputs.reset run: bun scripts/delete-project.ts composer-docs - - name: One-off TML-3157 state-scope migration (remove once the deploy is green) - run: bun scripts/migrate-docs-state-tml3157.ts # No --stage: this targets production. The CLI is invoked directly rather # than through the package's `deploy` script, which sources a local .env # that does not exist on a runner (the credentials are already in env). diff --git a/scripts/migrate-docs-state-tml3157.ts b/scripts/migrate-docs-state-tml3157.ts deleted file mode 100644 index 04886f36a..000000000 --- a/scripts/migrate-docs-state-tml3157.ts +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bun -/** - * ONE-OFF migration for the docs site's deploy state (TML-3157). Remove this - * script and its workflow step once the docs deploy is green. - * - * v0.6.0 scopes deploy state by the target Branch's id; the docs site's - * existing state sits under the pre-0.6.0 scope (Alchemy's dev_${USER} - * default), so the empty-scope guard stops the deploy. This performs the - * remedy the guard's message prescribes: re-stage the docs stack's rows to - * the default Branch's id, in that Branch's prisma-composer-state database. - * - * Idempotent: if the branch-id scope already holds the stack's rows, exits 0 - * without touching anything, so re-runs of the workflow stay green. - */ -import { createManagementApiClient } from '@prisma/management-api-sdk'; -import postgres from 'postgres'; - -const PROJECT_NAME = 'composer-docs'; -const STACK = 'composer-docs'; -const STATE_DATABASE_NAME = 'prisma-composer-state'; - -function fail(message: string): never { - console.error(message); - process.exit(1); -} - -const token = process.env['PRISMA_SERVICE_TOKEN']; -const workspaceId = process.env['PRISMA_WORKSPACE_ID']; -if (!token || !workspaceId) fail('PRISMA_SERVICE_TOKEN and PRISMA_WORKSPACE_ID must be set'); - -const client = createManagementApiClient({ token }); - -const projects = await client.GET('/v1/projects', { params: { query: { workspaceId } } }); -if (projects.error) fail(`listing projects failed: ${JSON.stringify(projects.error)}`); -const project = projects.data.data.find((p) => p.name === PROJECT_NAME); -if (!project) fail(`no project named "${PROJECT_NAME}" in this workspace`); - -const branches = await client.GET('/v1/projects/{projectId}/branches', { - params: { path: { projectId: project.id } }, -}); -if (branches.error) fail(`listing branches failed: ${JSON.stringify(branches.error)}`); -const defaultBranch = branches.data.data.find((b) => b.isDefault); -if (!defaultBranch) fail(`project ${project.id} has no default Branch`); -const newStage = defaultBranch.id; - -const databases = await client.GET('/v1/databases', { - params: { query: { projectId: project.id, branchId: defaultBranch.id } }, -}); -if (databases.error) fail(`listing databases failed: ${JSON.stringify(databases.error)}`); -const stateDb = databases.data.data.find((d) => d.name === STATE_DATABASE_NAME); -if (!stateDb) fail(`no database named "${STATE_DATABASE_NAME}" on branch ${defaultBranch.id}`); - -const created = await client.POST('/v1/databases/{databaseId}/connections', { - params: { path: { databaseId: stateDb.id } }, - body: { name: `tml3157-migration-${Date.now()}` }, -}); -if (created.error) fail(`creating a connection failed: ${JSON.stringify(created.error)}`); -const connectionId = created.data.data.id; -const dsn = created.data.data.endpoints.direct?.connectionString; -if (!dsn) fail('connection has no direct connection string'); - -const sql = postgres(dsn, { max: 1, onnotice: () => {} }); -try { - const scopes = await sql` - SELECT stack, stage, count(*)::int AS rows FROM ( - SELECT stack, stage FROM alchemy_resource_state - UNION ALL - SELECT stack, stage FROM alchemy_stack_output - ) AS both_tables GROUP BY stack, stage ORDER BY stack, stage`; - console.log('scopes present:', JSON.stringify(scopes)); - - const stackScopes = scopes.filter((r) => r.stack === STACK); - if (stackScopes.some((r) => r.stage === newStage)) { - console.log(`scope "${newStage}" already holds "${STACK}" rows — nothing to migrate`); - } else if (stackScopes.length === 0) { - console.log(`no "${STACK}" rows in either table — nothing to migrate`); - } else if (stackScopes.length > 1) { - fail( - `multiple legacy scopes for "${STACK}": ${stackScopes.map((r) => r.stage).join(', ')} — ` + - 'refusing to guess; clean up manually per the deploy guard message.', - ); - } else { - const oldStage = stackScopes[0]?.stage; - if (typeof oldStage !== 'string') fail('unreachable: single legacy scope has no stage value'); - await sql.begin(async (tx) => { - const a = - await tx`UPDATE alchemy_resource_state SET stage = ${newStage} WHERE stack = ${STACK} AND stage = ${oldStage}`; - const b = - await tx`UPDATE alchemy_stack_output SET stage = ${newStage} WHERE stack = ${STACK} AND stage = ${oldStage}`; - console.log( - `migrated "${STACK}" from scope "${oldStage}" to "${newStage}": ` + - `${a.count} resource row(s), ${b.count} output row(s)`, - ); - }); - } -} finally { - await sql.end(); - await client.DELETE('/v1/connections/{id}', { params: { path: { id: connectionId } } }); -}