diff --git a/README.md b/README.md index 76ae6fb..99f0d1e 100644 --- a/README.md +++ b/README.md @@ -56,13 +56,14 @@ valk-guard-example/ Workflow install target is configured as: ```text -github.com/valkdb/valk-guard/cmd/valk-guard@latest +github.com/valkdb/valk-guard/cmd/valk-guard.0.0-20260304065917-b9d9468a4ea3@latest ``` Rationale: -- This repository is a demo showcase; tracking latest keeps examples aligned with current built-in behavior. -- If you need strict reproducibility, pin a fixed tag in workflow `VALK_GUARD_INSTALL_REF`. +- This repository is a demo showcase, but CI is pinned to a known-good valk-guard build to keep output shape stable. +- Pinning avoids format drift that can break downstream tooling steps (for example: `Convert to reviewdog format`). +- When upgrading, bump `VALK_GUARD_INSTALL_REF` intentionally and verify the full workflow output. ## Creating Demo PRs (one rule at a time) diff --git a/demo/violations/dist3-vg007-008-101-105/README.md b/demo/violations/dist3-vg007-008-101-105/README.md new file mode 100644 index 0000000..11fb99c --- /dev/null +++ b/demo/violations/dist3-vg007-008-101-105/README.md @@ -0,0 +1,17 @@ +# Dist 3: VG007, VG008, VG101-VG105 + +This demo bundle intentionally triggers: + +- VG007 (destructive DDL) +- VG008 (non-concurrent index) +- VG101 (model column missing in migration) +- VG102 (required migration column missing in model) +- VG103 (model/migration type mismatch) +- VG104 (explicit model table not found) +- VG105 (unknown projection column) + +Coverage in this bundle: + +- SQL migrations and SQL queries +- Python ORM models (schema drift) +- Python non-ORM query execution diff --git a/demo/violations/dist3-vg007-008-101-105/python/orm_models.py b/demo/violations/dist3-vg007-008-101-105/python/orm_models.py new file mode 100644 index 0000000..0691b67 --- /dev/null +++ b/demo/violations/dist3-vg007-008-101-105/python/orm_models.py @@ -0,0 +1,32 @@ +from sqlalchemy import Column, Integer, String +from sqlalchemy.orm import DeclarativeBase + + +class Base(DeclarativeBase): + pass + + +class VG101User(Base): + __tablename__ = "vg101_users" + + id = Column(Integer, primary_key=True) + ghost_col = Column(String(64)) + + +class VG102Account(Base): + __tablename__ = "vg102_accounts" + + id = Column(Integer, primary_key=True) + + +class VG103Order(Base): + __tablename__ = "vg103_orders" + + id = Column(Integer, primary_key=True) + total = Column(String(32)) + + +class VG104AuditEvent(Base): + __tablename__ = "vg104_audit_events" + + id = Column(Integer, primary_key=True) diff --git a/demo/violations/dist3-vg007-008-101-105/python/raw_queries.py b/demo/violations/dist3-vg007-008-101-105/python/raw_queries.py new file mode 100644 index 0000000..0e0d253 --- /dev/null +++ b/demo/violations/dist3-vg007-008-101-105/python/raw_queries.py @@ -0,0 +1,6 @@ +from sqlalchemy import text +from sqlalchemy.orm import Session + + +def raw_unknown_projection_column(session: Session): + return session.execute(text("SELECT vg105_users.ghost_col FROM vg105_users LIMIT 1")).all() diff --git a/demo/violations/dist3-vg007-008-101-105/sql/vg007_destructive_ddl.sql b/demo/violations/dist3-vg007-008-101-105/sql/vg007_destructive_ddl.sql new file mode 100644 index 0000000..6864517 --- /dev/null +++ b/demo/violations/dist3-vg007-008-101-105/sql/vg007_destructive_ddl.sql @@ -0,0 +1 @@ +DROP TABLE vg101_users; diff --git a/demo/violations/dist3-vg007-008-101-105/sql/vg008_non_concurrent_index.sql b/demo/violations/dist3-vg007-008-101-105/sql/vg008_non_concurrent_index.sql new file mode 100644 index 0000000..2016873 --- /dev/null +++ b/demo/violations/dist3-vg007-008-101-105/sql/vg008_non_concurrent_index.sql @@ -0,0 +1 @@ +CREATE INDEX idx_vg105_users_email_bad ON vg105_users(email); diff --git a/demo/violations/dist3-vg007-008-101-105/sql/vg_schema.sql b/demo/violations/dist3-vg007-008-101-105/sql/vg_schema.sql new file mode 100644 index 0000000..246f5e8 --- /dev/null +++ b/demo/violations/dist3-vg007-008-101-105/sql/vg_schema.sql @@ -0,0 +1,18 @@ +CREATE TABLE vg101_users ( + id INTEGER PRIMARY KEY +); + +CREATE TABLE vg102_accounts ( + id INTEGER PRIMARY KEY, + required_code TEXT NOT NULL +); + +CREATE TABLE vg103_orders ( + id INTEGER PRIMARY KEY, + total NUMERIC(10,2) NOT NULL +); + +CREATE TABLE vg105_users ( + id INTEGER PRIMARY KEY, + email TEXT NOT NULL +);