diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbafc46..69b8800 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -188,6 +188,19 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Build and push Reset image + uses: docker/build-push-action@v6 + with: + context: . + file: apps/api/Dockerfile + target: reset + push: true + tags: | + ghcr.io/groombook/reset:${{ steps.version.outputs.tag }} + ${{ github.ref == 'refs/heads/main' && 'ghcr.io/groombook/reset:latest' || '' }} + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Build and push Web image uses: docker/build-push-action@v6 with: @@ -356,6 +369,7 @@ jobs: yq -i '(.images[] | select(.name == "ghcr.io/groombook/web")).newTag = env(TAG)' "$DEV_KUST" yq -i '(.images[] | select(.name == "ghcr.io/groombook/migrate")).newTag = env(TAG)' "$DEV_KUST" yq -i '(.images[] | select(.name == "ghcr.io/groombook/seed")).newTag = env(TAG)' "$DEV_KUST" + yq -i '(.images[] | select(.name == "ghcr.io/groombook/reset")).newTag = env(TAG)' "$DEV_KUST" # Update migrate Job name to include short SHA (immutable template fix) MIGRATE_JOB="apps/groombook/base/migrate-job.yaml" diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index e7a0882..1a89f85 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -43,3 +43,7 @@ CMD ["pnpm", "db:migrate"] # Seed stage — populates the database with test data FROM builder AS seed CMD ["pnpm", "db:seed"] + +# Reset stage — drops all tables, re-runs migrations, and re-seeds +FROM builder AS reset +CMD ["pnpm", "db:reset"] diff --git a/packages/db/src/reset.ts b/packages/db/src/reset.ts index c390f1c..41c3ce8 100644 --- a/packages/db/src/reset.ts +++ b/packages/db/src/reset.ts @@ -16,8 +16,8 @@ async function reset() { process.exit(1); } - if (process.env.NODE_ENV === "production") { - console.error("[FATAL] db:reset must not be run in production."); + if (process.env.NODE_ENV === "production" && process.env.ALLOW_RESET !== "true") { + console.error("[FATAL] db:reset must not be run in production without ALLOW_RESET=true."); process.exit(1); }