feat(ci): schema drift PR gate (TS<->DB) — #373 v2#588
Merged
Conversation
TS 상수 ↔ DB CHECK constraint 매핑 SSOT. scripts/check-schema-drift.ts 의 SOT_MAPPINGS 와 함께 갱신한다. v2 PR gate 의 동작/허용 constraint 형식/ 의도적 우회(drift-bypass label)/v3 후속 항목(posts.status, generated types) 명시.
…v2) ts-morph 로 TS 상수 (`export const X = [...] as const`) 값 set 추출 → psql 로 pg_get_constraintdef 파싱 → set-equality 비교. 세 가지 CHECK constraint 형식 (status::text=ANY ARRAY, col=ANY ARRAY, IN list) 지원. drift 1건 이상이면 exit 1, stdout 은 PR comment 용 markdown report. devDependency: ts-morph@^24.0.0 추가.
postgres:17 service + postgresql-client-17 + bun install + supabase migrations 순차 적용 + check-schema-drift.ts 실행 + sticky PR comment (marocchino/sticky-pull-request-comment@v2, header=schema-drift). drift-bypass label: continue-on-error 로 job green 유지 (comment 는 유지). branch protection 별도 설정 필요.
v1 nightly 와 v2 PR gate 채널을 분리 명시. v2 세부는 schema-drift-sot.md 에서 별도 owning.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced May 28, 2026
thxforall
added a commit
that referenced
this pull request
May 28, 2026
Conflicts resolved: - AGENTS.md: take origin/dev base (new structure/sections), preserve HEAD's "## Commit discipline" section, bump Last Updated to 2026-05-28 - packages/web/package.json: take both - scripts: notion:*/telegram:* (HEAD) + content-studio:video:local (dev) - deps: @notionhq/client (HEAD) + @next/third-parties (dev) - bun.lock: take origin/dev, then `bun install` to regen with both sets of deps (added ts-morph@24.0.0 from #588 merge)
thxforall
added a commit
that referenced
this pull request
May 28, 2026
* fix(ci): #373 drift gate — pgvector image, pipefail, sticky comment path #594 red-path smoke 가 노출한 3 가지 결함 동시 수정. 1. postgres service `image: postgres:17` → `pgvector/pgvector:pg17` - supabase/migrations 가 `CREATE EXTENSION vector` 를 호출하므로 vanilla postgres:17 으로는 setup 단계에서 첫 migration 부터 fail - 결과: SOT 비교 자체가 한 번도 실행된 적 없음 2. `bun run ... | tee /tmp/drift.md` → `set -eo pipefail` + `> drift.md` - GitHub Actions 의 default shell 은 `bash -e` (no pipefail) 이므로 pipe 의 last command (tee) exit 0 이 전체 exit code 가 된다. script `process.exit(1)` 이 가려져 job 이 항상 green 으로 표시됨 - pipe 자체를 제거하고 redirect → cat 으로 동일 효과 + log 가시성 유지 3. `hashFiles('/tmp/drift.md')` → `hashFiles('drift.md')` - `hashFiles()` 는 GITHUB_WORKSPACE 내부 파일만 해시화. `/tmp/*` 는 항상 빈 문자열 → `'' != ''` false → sticky comment step 영구 skip - drift.md 를 workspace 에 두고 path 도 동기화 ## 검증 본 PR self-validate: - workflow trigger (path 매치: `.github/workflows/schema-drift.yml`) - pgvector 이미지로 23 migration 정상 적용 기대 - MAGAZINE_STATUSES 는 dev 와 동일 → "OK — 1 SOT entries match" sticky comment 기대 머지 후 #594 (red-path smoke) 를 origin/dev rebase + force push 하면 의도된 DRIFT 결과 + drift-bypass label flow 까지 자동 재검증된다. ## Refs - 검증 PR: #594 (test/373-drift-smoke, DO NOT MERGE) - 원본 workflow: #588 - SOT: docs/database/schema-drift-sot.md * fix(ci): #373 drift gate — use supabase/postgres image for all required extensions self-validate 첫 시도 (PR #595 initial) 가 노출: pgvector/pgvector:pg17 도 부족. 20260409075040_remote_schema.sql 이 `CREATE EXTENSION pg_graphql` 요구. supabase/postgres 는 prod 에서 사용 중인 모든 ext (vector, pg_graphql, pgsodium, pg_net, pgaudit, pgjwt 등) 를 포함하는 공식 이미지. 17.6.1.131 (2026-05-27 stable) 태그 고정 — latest 사용 시 reproducibility 깨짐. cold start 가 vanilla 대비 다소 느릴 수 있으나 setup fail 위험 제거가 우선. * fix(ci): #373 drift gate — use default postgres DB to avoid supabase init permission issue #595 v2 self-validate 실패 노출: `POSTGRES_DB: drift` 로 별도 DB 를 만들면 supabase/postgres image 의 init script 가 default `postgres` DB 에서만 role/권한을 설정하므로 postgres user 가 `permission denied for database drift` 를 받는다. 별도 DB 만들지 말고 image 가 init 한 default `postgres` DB 위에서 migration 적용. * fix(ci): #373 drift gate — bootstrap supabase namespace stubs supabase/postgres image 의 init script 는 storage/auth/vault/graphql/realtime 객체를 만들지 않아 (그건 별도 docker-compose service 가 담당) storage.buckets INSERT 같은 migration 에서 setup 이 fail 함. 게이트 범위는 CHECK constraint 정합성이지 prod-parity 가 아니므로, migration 적용 전에 FK/INSERT target 만큼만 minimal stub 으로 만든다. stub: - auth, storage, vault, graphql, realtime schemas - auth.users(id uuid PRIMARY KEY) — FK + trigger target - auth.uid() — NULL 반환 stub (RLS USING/WITH CHECK 에서 호출) - storage.buckets(id, name, public) — INSERT target 신규 migration 이 다른 supabase namespace 객체를 참조하면 여기 추가. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ci): #373 drift gate v5 — drop+recreate auth/storage schemas 이전 v4 (commit 9f89ca4) 는 schema 가 supabase image 에 이미 존재하지만 ownership 이 supabase_admin 이라 postgres user 가 CREATE TABLE 시 `permission denied for schema auth` 로 fail 했음. 해결: auth / storage 만 DROP CASCADE 로 날리고 postgres owner 로 재생성. vault / graphql / realtime 은 첫 migration 의 CREATE EXTENSION 이 의존하므로 건드리지 않음. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ci): #373 drift gate v6 — connect as supabase_admin + diagnostic v5 (drop+create) 가 `must be owner of schema auth` 로 fail. postgres role 은 supabase/postgres image 에서 superuser 가 아님 — schema 가 supabase_admin 소유로 잡혀있어 DROP/CREATE TABLE 둘 다 막힘. v6 변경: - LOCAL_DATABASE_URL 의 user 를 supabase_admin 으로 변경 (POSTGRES_PASSWORD 공용) - DROP/CREATE SCHEMA 제거, IF NOT EXISTS stub 객체만 추가 - gen_random_uuid DEFAULT 제거 (stub PK 는 INSERT 안 함, extensions schema 의존 회피) - 진단 라인 (current_user / \du) 추가 — 다음 fail 시 즉시 원인 파악 v6 도 fail 하면 stub 접근 폐기 → supabase CLI 로 전환. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: empty commit to re-trigger drift workflow after drift-bypass label add --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
thxforall
added a commit
that referenced
this pull request
May 28, 2026
* docs(database): add schema-drift-sot.md SSOT mapping (#373 v2) TS 상수 ↔ DB CHECK constraint 매핑 SSOT. scripts/check-schema-drift.ts 의 SOT_MAPPINGS 와 함께 갱신한다. v2 PR gate 의 동작/허용 constraint 형식/ 의도적 우회(drift-bypass label)/v3 후속 항목(posts.status, generated types) 명시. * feat(scripts): add check-schema-drift.ts for TS<->DB enum drift (#373 v2) ts-morph 로 TS 상수 (`export const X = [...] as const`) 값 set 추출 → psql 로 pg_get_constraintdef 파싱 → set-equality 비교. 세 가지 CHECK constraint 형식 (status::text=ANY ARRAY, col=ANY ARRAY, IN list) 지원. drift 1건 이상이면 exit 1, stdout 은 PR comment 용 markdown report. devDependency: ts-morph@^24.0.0 추가. * feat(ci): add schema-drift.yml PR gate workflow (#373 v2) postgres:17 service + postgresql-client-17 + bun install + supabase migrations 순차 적용 + check-schema-drift.ts 실행 + sticky PR comment (marocchino/sticky-pull-request-comment@v2, header=schema-drift). drift-bypass label: continue-on-error 로 job green 유지 (comment 는 유지). branch protection 별도 설정 필요. * docs(database): drift-check.md mark v2 PR gate landed (#373) v1 nightly 와 v2 PR gate 채널을 분리 명시. v2 세부는 schema-drift-sot.md 에서 별도 owning.
thxforall
added a commit
that referenced
this pull request
May 28, 2026
MAGAZINE_STATUSES 에 'foo' 추가 — DB CHECK constraint 와 의도적 drift 발생. 목적: - #588 에서 머지된 schema-drift PR gate workflow 의 red path 검증 - 기대 결과: workflow fail + sticky comment 에 TS-only: foo 표기 부수 효과: - packages/web/lib/api/admin/__tests__/magazines.test.ts hardcoded toEqual fail (lint/test workflow 도 red — 무관) 검증 완료 후 PR close + branch 삭제 예정.
thxforall
added a commit
that referenced
this pull request
May 28, 2026
* feat(ci): schema drift PR gate (TS<->DB) — #373 v2 (#588) * docs(database): add schema-drift-sot.md SSOT mapping (#373 v2) TS 상수 ↔ DB CHECK constraint 매핑 SSOT. scripts/check-schema-drift.ts 의 SOT_MAPPINGS 와 함께 갱신한다. v2 PR gate 의 동작/허용 constraint 형식/ 의도적 우회(drift-bypass label)/v3 후속 항목(posts.status, generated types) 명시. * feat(scripts): add check-schema-drift.ts for TS<->DB enum drift (#373 v2) ts-morph 로 TS 상수 (`export const X = [...] as const`) 값 set 추출 → psql 로 pg_get_constraintdef 파싱 → set-equality 비교. 세 가지 CHECK constraint 형식 (status::text=ANY ARRAY, col=ANY ARRAY, IN list) 지원. drift 1건 이상이면 exit 1, stdout 은 PR comment 용 markdown report. devDependency: ts-morph@^24.0.0 추가. * feat(ci): add schema-drift.yml PR gate workflow (#373 v2) postgres:17 service + postgresql-client-17 + bun install + supabase migrations 순차 적용 + check-schema-drift.ts 실행 + sticky PR comment (marocchino/sticky-pull-request-comment@v2, header=schema-drift). drift-bypass label: continue-on-error 로 job green 유지 (comment 는 유지). branch protection 별도 설정 필요. * docs(database): drift-check.md mark v2 PR gate landed (#373) v1 nightly 와 v2 PR gate 채널을 분리 명시. v2 세부는 schema-drift-sot.md 에서 별도 owning. * docs(design-system): v2.2.0 동기화 — content fundamentals, animations, dual palette (#589) * docs(design-system): bump README to v2.2.0 with content fundamentals + dual palette - Version: 2.1.0 -> 2.2.0, Last Updated: 2026-05-28 - Add v2.2 변경사항: Content Fundamentals, Animations 카탈로그, Dual Palette, Magazine palette tokens (#573), Navigation Facts, Home sequence, IBM Plex Mono (inline), DecodedLogo WebGL - Document Index: 신규 Foundation (v2.2) 섹션 — content-fundamentals.md, animations.md 추가 - Tech Stack table 확장: OKLCH + Hex magazine palette, typography 4종, three.js + @chenglou/pretext (DecodedLogo) - Navigation Facts + Home Page Sequence 섹션 추가 (app/page.tsx:568 앵커) Closes #572 (part 1/7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(design-system): add content-fundamentals.md 7 sections covering Voice / Casing / Person / Language / Pricing / Numbers / Emoji policy with Do/Don't rules and code anchors: - Pricing: ko-KR locale + ₩ prefix, toLocaleString (앵커: DecodedSolutionsSection.tsx:40 — 마이그레이션 대상) - Numbers: 사용자 표면은 toLocaleString 통과 (앵커: lib/utils/format.ts:36) - Voice: editorial(큐레이션) vs product UI(명료) 분리 - Language: ko-KR 기본, 고유명사·기술 용어 원문 유지 - Emoji: editorial 표면 금지, product UI 절제, Lucide 우선 Closes #572 (part 2/7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(design-system): add animations.md catalog 15+ CSS keyframe catalog with file/line anchors from packages/web/app/globals.css: - dash-flow (L299), hologram-* family (L318-L351), spot-* family (L410-L458), slide-up (L487), shimmer (L503), ai-summary-* (L522-L535), card-glow (L551), marquee-c (L585) - duration/easing/용도/reduce-motion 컬럼 - Easing 함수 정리: ease-out (단방향 reveal), ease-in-out (펄스), linear (무한 flow), cubic-bezier(0.22, 1, 0.36, 1) — observe pattern, cubic-bezier(0.16, 1, 0.3, 1) — ai-summary smooth reveal - prefers-reduced-motion 정책: 4개 미디어 쿼리 블록 + .js-observe transition fallback - 사용 예시: spot 마커, skeleton shimmer, ai-summary, .js-observe Closes #572 (part 3/7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(design-system): patterns.md add 5.4 dual palette usage * docs(design-system): tokens.md add magazine palette sub-table * docs(agent): rewrite design-system-llm.md as v2.2.0 1-pager SSOT * docs(agent): design-system-summary.md add v2.2.0 entry --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(content-studio): Video Generation Pipeline — AI 영상 합성 통합 (#592) * feat(content-studio): add xAI scene video pipeline * docs(content-studio): plan video job pipeline * docs(content-studio): harden video job plan * feat(content-studio): add video job pipeline * feat(content-studio): abstract video providers * feat(content-studio): select video mode per scene * feat(content-studio): compose final video exports * feat(content-studio): resume persisted video jobs * feat(content-studio): attach governance to video jobs * fix(content-studio): strengthen short-form video prompts * feat(content-studio): add local video download runner * feat(content-studio): save source image for local videos * fix(content-studio): split long local video scenes * feat(content-studio): compose local video clips * fix(magazines): MAGAZINE_STATUSES — 'generating' 누락 복원 (#373 drift) DB constraint post_magazines_status_check 는 'generating' 포함 5-state 인데 TS MAGAZINE_STATUSES 는 4-state. 1주일+ 잠재한 schema drift. #373 drift gate fix (#595) 가 처음 정상 작동하며 발견. 발생 경위: - 20260430120000: 'generating' 추가 (api-server generate handler 초기 INSERT) - 20260430150000: 4-state 로 축소 (TS 와 동기화) - 20260504133842: 'generating' 복원 (api-server insert + UI 필요) - 마지막 migration 의 TS 동기화 누락 → drift magazines.ts 의 MAGAZINE_STATUSES 에 'generating' 추가 (DB 와 같은 순서). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #373 v2 (PR gate).
#372 trigger 사례(MAGAZINE_STATUSES 코드 ↔
post_magazines_status_checkCHECK constraint drift)를 PR 단계에서 자동 차단..github/workflows/schema-drift.yml: postgres:17 service + postgresql-client-17 + supabase migrations 순차 적용 + bun script 실행 + sticky PR comment (marocchino/sticky-pull-request-comment@v2, header=schema-drift)scripts/check-schema-drift.ts:ts-morph로 TS 상수 set 추출 →psql로pg_get_constraintdef파싱 → set-equality 비교. 세 가지 CHECK 형식 (status::text = ANY ARRAY,col = ANY ARRAY,IN (...)) 지원.docs/database/schema-drift-sot.md: SOT 매핑 SSOT — 신규 enum 추가 시 본 표 + 스크립트의SOT_MAPPINGS동시 갱신.docs/database/drift-check.md: v1 nightly + v2 PR gate 채널 분리 명시.우회
drift-bypasslabel 을 PR 에 붙이면 step 이continue-on-error로 전환되어 job 은 green, drift report 는 comment 에 그대로 남는다. branch protection 으로 머지 차단은 별도 설정 필요.한계 / v3 후속
export const X = [...] as const패턴만 지원posts.status는 DB CHECK constraint 가 없어 v2 SOT 미등록 — 별도 issue 권장 (CHECK 추가 마이그레이션 후 등록)packages/web/lib/api/generated/) drift 는 별도 채널 필요Test plan
status::text=ANY ARRAY,col=ANY ARRAY,IN list, apostrophe escape) 4/4 passMAGAZINE_STATUSES에'foo'추가) → workflow fail + DRIFT 표 확인drift-bypasslabel 붙이고 same PR 재실행 → job green + DRIFT comment 유지 확인Related
.github/workflows/db-drift-check.yml(PRD↔Supabase, 유지)Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com