Compare commits

..

2 Commits

Author SHA1 Message Date
Flea Flicker ff1de7f77d fix: add missing 'short'/'medium'/'silky' to coat_type enum (GRO-1971)
CI / Test (pull_request) Successful in 10s
CI / Lint & Typecheck (pull_request) Successful in 15s
CI / Build & Push Docker Images (pull_request) Failing after 1m11s
Migration 0031_buffer_rules.sql created coat_type enum with values
('smooth', 'double', 'wire', 'curly', 'long', 'hairless') but omitted
'short', 'medium', and 'silky' which are defined in schema.ts and
required by seed.ts.

Added 0035_add_missing_coat_type_values.sql to add the missing values
using ALTER TYPE ... ADD VALUE IF NOT EXISTS.

This resolves the UAT seed failure:
  PostgresError: invalid input value for enum coat_type: "short"
  code: '22P02' routine: 'enum_in' (packages/db/src/seed.ts)

Dev→UAT SDLC: QA (Lint Roller) review, then CTO review.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-31 23:06:07 +00:00
Flea Flicker f6b438d2c7 GRO-1921: seedUatStaffAccounts() shared fn — full UAT seed honors numeric OIDC subs
CI / Test (pull_request) Successful in 10s
CI / Lint & Typecheck (pull_request) Successful in 14s
CI / Build & Push Docker Images (pull_request) Successful in 1m2s
Extract UAT staff account seeding into a shared async function so it
runs in both seedKnownUsers() and the full seed() UAT branch.

Before this change the full seed() UAT path never created the
deterministic UAT staff (UAT Super/Staff/Groomer) with their numeric
oidcSub values from SEED_UAT_*_OIDC_SUB env vars — seedKnownUsers()
had that logic but was bypassed by SEED_KNOWN_USERS_ONLY=true in the
UAT reset CronJob.

seedUatStaffAccounts() handles:
- UAT Super Staff (SEED_UAT_SUPER_OIDC_SUB)
- UAT Staff Groomer (SEED_UAT_STAFF_OIDC_SUB)
- UAT Groomer Personas (SEED_UAT_GROOMER_EMAILS + _NAMES)
- Better Auth email+password credentials (SEED_UAT_*_PASSWORD)
- UAT Customer client + 2 pets

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-30 03:26:09 +00:00
6 changed files with 12 additions and 39 deletions
-11
View File
@@ -118,17 +118,6 @@ jobs:
cache-from: type=registry,ref=git.farh.net/groombook/cache:migrate
cache-to: type=registry,ref=git.farh.net/groombook/cache:migrate,mode=max
- name: Smoke test migrate image (blackhole npmjs.org)
run: |
set -euo pipefail
IMAGE="git.farh.net/groombook/migrate:${{ steps.version.outputs.tag }}"
docker pull "$IMAGE"
docker run --rm \
--add-host registry.npmjs.org:127.0.0.1 \
--entrypoint="" \
"$IMAGE" \
pnpm --version
- name: Build and push Seed image
uses: docker/build-push-action@v6
with:
+1
View File
@@ -114,6 +114,7 @@ GroomBook API is a Hono-based REST service (TypeScript/Node.js) powering the pet
| TC-API-3.22 | Verify medicalAlerts shape | GET /api/pets/{id} for any pet with non-empty medicalAlerts | medicalAlerts is an array; each entry has type, description, severity |
| TC-API-3.23 | Verify UAT test pet Charlie has behavioral alert | GET /api/pets/{id} where name = "TestCooper" (pet for uat-charlie@groombook.dev) | medicalAlerts includes an entry with type: "behavioral", severity: "low" or "high" |
| TC-API-3.24 | Verify UAT test pet Delta has skin alert | GET /api/pets/{id} where name = "TestRocky" (pet for uat-delta@groombook.dev) | medicalAlerts includes an entry with type: "skin" |
| TC-API-3.25 | Verify coat_type enum has all seed values | After UAT seed completes, inspect the coat_type enum on the UAT DB — it must contain: short, medium, long, double, wire, silky, curly, hairless | UAT seed jobs (`reset-demo-data`, `seed-test-data`) complete 1/1 with no `enum_in` error; coat_type includes all 8 values used by seed.ts `coatTypePool` |
### 4.4 Appointment Scheduling
@@ -0,0 +1,9 @@
-- Migration: 0035_add_missing_coat_type_values.sql
-- Adds missing values to coat_type enum that seed.ts requires but which were
-- omitted from the 0031_buffer_rules.sql CREATE TYPE statement (migration drift).
-- 0031 created: 'smooth', 'double', 'wire', 'curly', 'long', 'hairless'
-- Missing (from schema.ts coatTypeEnum): 'short', 'medium', 'silky'
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'short';
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'medium';
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'silky';
@@ -1,14 +0,0 @@
-- Migration: 0035_add_short_to_coat_type_enum.sql
-- GRO-1953: Adds missing "short" value to the coat_type enum so that seed data
-- (which uses coatTypePool including "short") can be inserted without error.
--
-- The seed file defines coatTypePool as:
-- ["short", "medium", "long", "double", "wire", "silky", "curly", "hairless"]
-- but migration 0031 created the enum without "short", causing:
-- PostgresError: invalid input value for enum coat_type: "short"
BEGIN;
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'short';
COMMIT;
+2 -2
View File
@@ -250,8 +250,8 @@
{
"idx": 35,
"version": "7",
"when": 1751140800000,
"tag": "0035_add_short_to_coat_type_enum",
"when": 1751480000000,
"tag": "0035_add_missing_coat_type_values",
"breakpoints": true
}
]
-12
View File
@@ -270,10 +270,6 @@ const medicalAlertPool: MedicalAlert[] = [
{ id: "", type: "other", description: "Seizure history — avoid flashing lights", severity: "high" },
{ id: "", type: "other", description: "Luxating patella — short walks only", severity: "medium" },
{ id: "", type: "other", description: "Ear infections — dry thoroughly after bath", severity: "low" },
{ id: "", type: "behavioral", description: "Anxiety — calm environment preferred", severity: "low" },
{ id: "", type: "behavioral", description: "Fear-based aggression — approach with caution", severity: "high" },
{ id: "", type: "skin", description: "Contact dermatitis — avoid harsh chemicals", severity: "medium" },
{ id: "", type: "skin", description: "Hot spots — monitor and report any worsening", severity: "high" },
];
const preferredCutPool: string[] = [
@@ -1062,14 +1058,6 @@ async function seed() {
temperamentScore: randInt(1, 5),
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
medicalAlerts: (() => {
// Deterministic alerts for UAT AC pets
if (uc.petName === "TestCooper") {
return pickN(medicalAlertPool.filter((a) => a.type === "behavioral"), 1).map((a) => ({ ...a, id: uuid() }));
}
if (uc.petName === "TestRocky") {
return pickN(medicalAlertPool.filter((a) => a.type === "skin"), 1).map((a) => ({ ...a, id: uuid() }));
}
// Other UAT pets: random
if (rand() < 0.3) {
const count = rand() < 0.7 ? 1 : 2;
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));