Conversation
| __tablename__ = "vg101_users" | ||
|
|
||
| id = Column(Integer, primary_key=True) | ||
| ghost_col = Column(String(64)) |
There was a problem hiding this comment.
🚫 [valk-guard] reported by reviewdog 🐶
VG101: model "vg101_users" references column "ghost_col" not found in table "vg101_users" schema; check migration DDL or update model mapping
| ghost_col = Column(String(64)) | ||
|
|
||
|
|
||
| class VG102Account(Base): |
There was a problem hiding this comment.
VG102: table "vg102_accounts" has NOT NULL column "required_code" but model "vg102_accounts" does not define it; add the field or make the migration column nullable/defaulted
| __tablename__ = "vg103_orders" | ||
|
|
||
| id = Column(Integer, primary_key=True) | ||
| total = Column(String(32)) |
There was a problem hiding this comment.
VG103: column "total" type mismatch: model has "String(32)" but migration has "NUMERIC(10,2)"; align model type or migration column type
| total = Column(String(32)) | ||
|
|
||
|
|
||
| class VG104AuditEvent(Base): |
There was a problem hiding this comment.
🚫 [valk-guard] reported by reviewdog 🐶
VG104: table "vg104_audit_events" referenced by model has no CREATE TABLE in migrations; add migration DDL or fix TableName()
|
|
||
|
|
||
| def raw_unknown_projection_column(session: Session): | ||
| return session.execute(text("SELECT vg105_users.ghost_col FROM vg105_users LIMIT 1")).all() |
There was a problem hiding this comment.
🚫 [valk-guard] reported by reviewdog 🐶
VG105: projection column "ghost_col" not found in table "vg105_users" schema; check SELECT list and schema/model mappings | Query: SELECT vg105_users.ghost_col FROM vg105_users LIMIT 1
| @@ -0,0 +1 @@ | |||
| DROP TABLE vg101_users; | |||
There was a problem hiding this comment.
🚫 [valk-guard] reported by reviewdog 🐶
VG007: destructive DDL detected: DROP TABLE vg101_users | Query: DROP TABLE vg101_users
| @@ -0,0 +1 @@ | |||
| CREATE INDEX idx_vg105_users_email_bad ON vg105_users(email); | |||
There was a problem hiding this comment.
VG008: CREATE INDEX idx_vg105_users_email_bad without CONCURRENTLY may block writes; add CONCURRENTLY | Query: CREATE INDEX idx_vg105_users_email_bad ON vg105_users(email)
858eb17 to
1e4089b
Compare
Purpose
This PR demonstrates destructive DDL and schema-aware drift checks with focused fixtures.
Expected Findings In This PR
VG007(destructive-ddl): expected due to intentionalDROP TABLEdemo.VG008(non-concurrent-index): expected due to intentional non-CONCURRENTLYindex creation.VG101(dropped-column): expected because model references a non-existent migration column.VG102(missing-not-null): expected because model omits a required NOT NULL migration column.VG103(type-mismatch): expected because model and migration types intentionally diverge.VG104(table-not-found): expected because model table mapping intentionally has no matching migration table.VG105(unknown-projection-column): expected because projection references a column absent from schema.All of these are intentional fixtures.
Why We Previously Failed In CI
Previous CI failure happened in
Convert to reviewdog formatbecause jq expected one JSON layout. It was not a schema-rule correctness issue.This branch includes the conversion compatibility fix and pins install ref to the validated build to keep output and reviewdog conversion aligned.
How ORM AST Crawl Works In This PR
For SQLAlchemy models, Valk Guard crawls AST definitions to extract:
__tablename__Column(...)names and typesIt then combines this model snapshot with migration DDL snapshot and runs VG101-VG105 against the merged schema context.
What We Gain