sqlproof 0.1.0a1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqlproof-0.2.2/.github/ISSUE_TEMPLATE/bug_report.yml +79 -0
- sqlproof-0.2.2/.github/ISSUE_TEMPLATE/config.yml +5 -0
- sqlproof-0.2.2/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
- sqlproof-0.2.2/.github/ISSUE_TEMPLATE/question.yml +28 -0
- sqlproof-0.2.2/.github/PULL_REQUEST_TEMPLATE.md +43 -0
- sqlproof-0.2.2/.github/actions/setup-supabase-test-db/action.yml +42 -0
- sqlproof-0.2.2/.github/actions/setup-supabase-test-db/sql/supabase-test-init.sql +52 -0
- sqlproof-0.2.2/.github/dependabot.yml +45 -0
- sqlproof-0.2.2/.github/workflows/ci.yml +73 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/.github/workflows/deploy-website.yml +6 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/.github/workflows/nightly.yml +1 -1
- sqlproof-0.2.2/.github/workflows/pr-title.yml +42 -0
- sqlproof-0.2.2/.github/workflows/release-please.yml +33 -0
- sqlproof-0.2.2/.github/workflows/release.yml +71 -0
- sqlproof-0.2.2/.github/workflows/uv-lock-refresh.yml +45 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/.gitignore +2 -0
- sqlproof-0.2.2/.release-please-manifest.json +3 -0
- sqlproof-0.2.2/.sqlproof/failures/property_fails.json +24 -0
- sqlproof-0.2.2/AGENTS.md +465 -0
- sqlproof-0.2.2/CHANGELOG.md +162 -0
- sqlproof-0.2.2/CONTRIBUTING.md +230 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/PKG-INFO +61 -13
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/README.md +59 -11
- sqlproof-0.2.2/SECURITY.md +60 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/SPEC.md +52 -7
- sqlproof-0.2.2/docs/superpowers/specs/2026-05-30-release-engineering-design.md +368 -0
- sqlproof-0.2.2/examples/supabase_rls/README.md +121 -0
- sqlproof-0.2.2/examples/supabase_rls/schema.sql +100 -0
- sqlproof-0.2.2/examples/supabase_rls/test_rls.pgtap.sql +177 -0
- sqlproof-0.2.2/examples/supabase_rls/test_rls.py +284 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/pyproject.toml +2 -10
- sqlproof-0.2.2/release-please-config.json +30 -0
- sqlproof-0.2.2/src/sqlproof/_version.py +1 -0
- sqlproof-0.2.2/src/sqlproof/contrib/plpgsql_coverage.py +494 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/contrib/supabase.py +78 -10
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/core.py +9 -6
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/columns.py +4 -2
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/graph.py +2 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/rows.py +7 -2
- sqlproof-0.2.2/src/sqlproof/pytest_plugin.py +289 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/property.py +30 -6
- sqlproof-0.2.2/tests/integration/test_plpgsql_coverage.py +204 -0
- sqlproof-0.2.2/tests/integration/test_pytest_plugin_fixtures_integration.py +89 -0
- sqlproof-0.2.2/tests/integration/test_supabase_auth_surface.py +110 -0
- sqlproof-0.2.2/tests/unit/test_column_strategies.py +217 -0
- sqlproof-0.2.2/tests/unit/test_constraint_strategies.py +317 -0
- sqlproof-0.2.2/tests/unit/test_contrib_plpgsql_coverage.py +489 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_contrib_supabase.py +114 -0
- sqlproof-0.2.2/tests/unit/test_parse_sql_edge_cases.py +78 -0
- sqlproof-0.2.2/tests/unit/test_pytest_plugin_fixtures.py +144 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_runner_slice.py +164 -1
- sqlproof-0.2.2/tests/unit/test_well_known.py +126 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/uv.lock +1 -1
- sqlproof-0.2.2/website/.env.example +12 -0
- sqlproof-0.2.2/website/astro.config.mjs +71 -0
- sqlproof-0.2.2/website/src/content/docs/examples/data-generation.md +309 -0
- sqlproof-0.2.2/website/src/content/docs/examples/property-patterns.md +234 -0
- sqlproof-0.2.2/website/src/content/docs/examples/testing-sql-functions.md +400 -0
- sqlproof-0.2.2/website/src/content/docs/guides/ci-cd.md +181 -0
- sqlproof-0.2.2/website/src/content/docs/guides/vs-pgtap.md +187 -0
- sqlproof-0.2.2/website/src/content/docs/supabase-quickstart.md +214 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/pages/index.astro +12 -6
- sqlproof-0.2.2/website/src/posthog.mjs +41 -0
- sqlproof-0.1.0a1/.github/workflows/ci.yml +0 -38
- sqlproof-0.1.0a1/.github/workflows/release.yml +0 -36
- sqlproof-0.1.0a1/CHANGELOG.md +0 -58
- sqlproof-0.1.0a1/src/sqlproof/_version.py +0 -1
- sqlproof-0.1.0a1/src/sqlproof/pytest_plugin.py +0 -24
- sqlproof-0.1.0a1/website/astro.config.mjs +0 -42
- sqlproof-0.1.0a1/website/src/content/docs/guides/ci-cd.md +0 -67
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/examples/ecommerce/schema.sql +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/examples/ecommerce/test_orders.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/examples/ripenn_scoring/schema.sql +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/examples/ripenn_scoring/test_scoring.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/cli.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/client.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/config.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/contrib/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/coverage/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/coverage/diversity.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/coverage/plpgsql.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/coverage/schema_shape.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/exceptions.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/constraints.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/functions.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/sampling.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/generators/well_known.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/reporter/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/reporter/console.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/reporter/json_io.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/db.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/migration.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/overload.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/rls.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/runners/stateful.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/schema/__init__.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/schema/dependency_graph.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/schema/fingerprint.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/schema/introspect.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/schema/model.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/schema/parse_sql.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/testing.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/src/sqlproof/types.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/benchmarks/test_generation_benchmark.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/conftest.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/integration/test_postgres_execution.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/meta/test_meta_properties.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_cli_smoke.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_db_manager.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_generators_core.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_package_scaffold.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_schema_core.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_state_machine.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/tests/unit/test_v01_surfaces.py +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/package-lock.json +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/package.json +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/public/CNAME +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/public/favicon.svg +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/config.ts +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/api/check-options.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/api/sqlproof-class.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/api/state-machine.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/api/table-customization.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/examples/orders.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/getting-started.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/guides/custom-generators.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/guides/fk-distributions.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/guides/local-dev.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/guides/security.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/content/docs/guides/supabase.md +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/src/styles/custom.css +0 -0
- {sqlproof-0.1.0a1 → sqlproof-0.2.2}/website/tsconfig.json +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something is broken or behaving unexpectedly.
|
|
3
|
+
title: "fix: <one-line summary>"
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for filing a bug. The clearer the repro, the faster we can fix it.
|
|
10
|
+
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: summary
|
|
13
|
+
attributes:
|
|
14
|
+
label: Summary
|
|
15
|
+
description: One or two sentences on what's wrong.
|
|
16
|
+
placeholder: "`SqlProof.check()` raises X when the schema contains Y."
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: reproduction
|
|
22
|
+
attributes:
|
|
23
|
+
label: Minimal reproduction
|
|
24
|
+
description: |
|
|
25
|
+
Smallest code/schema/dataset that triggers the bug. A self-contained
|
|
26
|
+
Python script we can paste and run is ideal.
|
|
27
|
+
render: python
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
|
|
31
|
+
- type: textarea
|
|
32
|
+
id: expected
|
|
33
|
+
attributes:
|
|
34
|
+
label: Expected behavior
|
|
35
|
+
placeholder: "Should have returned ... / shouldn't have raised."
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
|
|
39
|
+
- type: textarea
|
|
40
|
+
id: actual
|
|
41
|
+
attributes:
|
|
42
|
+
label: Actual behavior
|
|
43
|
+
description: Include the full traceback if applicable.
|
|
44
|
+
render: shell
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
|
|
48
|
+
- type: input
|
|
49
|
+
id: sqlproof-version
|
|
50
|
+
attributes:
|
|
51
|
+
label: sqlproof version
|
|
52
|
+
placeholder: "e.g. 0.1.0a1 (or `uv pip show sqlproof`)"
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
55
|
+
|
|
56
|
+
- type: input
|
|
57
|
+
id: python-version
|
|
58
|
+
attributes:
|
|
59
|
+
label: Python version
|
|
60
|
+
placeholder: "e.g. 3.12.2"
|
|
61
|
+
validations:
|
|
62
|
+
required: true
|
|
63
|
+
|
|
64
|
+
- type: input
|
|
65
|
+
id: postgres-version
|
|
66
|
+
attributes:
|
|
67
|
+
label: Postgres version
|
|
68
|
+
description: Output of `SELECT version();` against your test database. Skip if not DB-related.
|
|
69
|
+
placeholder: "e.g. PostgreSQL 15.8 (Supabase)"
|
|
70
|
+
validations:
|
|
71
|
+
required: false
|
|
72
|
+
|
|
73
|
+
- type: textarea
|
|
74
|
+
id: additional
|
|
75
|
+
attributes:
|
|
76
|
+
label: Additional context
|
|
77
|
+
description: Anything else that might help — workarounds you tried, related issues, screenshots.
|
|
78
|
+
validations:
|
|
79
|
+
required: false
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a new feature or capability.
|
|
3
|
+
title: "feat: <one-line summary>"
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for the suggestion. Helping us understand the *problem* you're
|
|
10
|
+
solving is more useful than a fully-specified solution — we may have
|
|
11
|
+
ideas you haven't considered.
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: problem
|
|
15
|
+
attributes:
|
|
16
|
+
label: Problem
|
|
17
|
+
description: What are you trying to do that sqlproof doesn't currently let you do well? Include a concrete use case.
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: proposed
|
|
23
|
+
attributes:
|
|
24
|
+
label: Proposed solution
|
|
25
|
+
description: What you have in mind. Rough is fine — API sketch, behavior description, prior art elsewhere.
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: alternatives
|
|
31
|
+
attributes:
|
|
32
|
+
label: Alternatives considered
|
|
33
|
+
description: What workarounds have you tried? Why aren't they good enough?
|
|
34
|
+
validations:
|
|
35
|
+
required: false
|
|
36
|
+
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: additional
|
|
39
|
+
attributes:
|
|
40
|
+
label: Additional context
|
|
41
|
+
description: Links, screenshots, references to other libraries that solve this well.
|
|
42
|
+
validations:
|
|
43
|
+
required: false
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Question
|
|
2
|
+
description: Ask about how to do something with sqlproof.
|
|
3
|
+
title: "question: <one-line summary>"
|
|
4
|
+
labels: ["question"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Questions are welcome. Before filing, please skim the [README](https://github.com/alialavia/sqlproof#readme)
|
|
10
|
+
and the [examples directory](https://github.com/alialavia/sqlproof/tree/main/examples) — the answer
|
|
11
|
+
might already be there.
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: question
|
|
15
|
+
attributes:
|
|
16
|
+
label: Your question
|
|
17
|
+
description: What are you trying to do? What have you tried so far?
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: context
|
|
23
|
+
attributes:
|
|
24
|
+
label: Context
|
|
25
|
+
description: Code snippets, schema, your environment — whatever helps frame the question.
|
|
26
|
+
render: python
|
|
27
|
+
validations:
|
|
28
|
+
required: false
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Thanks for the contribution! A few quick notes before you fill this in:
|
|
3
|
+
|
|
4
|
+
1. The PR title must follow Conventional Commits (e.g. `feat(generator):`,
|
|
5
|
+
`fix(core):`, `docs(readme):`). CI will fail if it doesn't parse.
|
|
6
|
+
See CONTRIBUTING.md for the full list of accepted types.
|
|
7
|
+
|
|
8
|
+
2. The PR title becomes the squash-merge commit message on main and is what
|
|
9
|
+
release-please uses to compute the next version + changelog entry. Make
|
|
10
|
+
it accurate and self-contained.
|
|
11
|
+
|
|
12
|
+
3. Delete sections below that don't apply.
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
## Summary
|
|
16
|
+
|
|
17
|
+
<!-- What changed? Bullets are great. -->
|
|
18
|
+
|
|
19
|
+
-
|
|
20
|
+
|
|
21
|
+
## Why
|
|
22
|
+
|
|
23
|
+
<!-- The motivation. What problem does this solve, or what user request does
|
|
24
|
+
it satisfy? Link to the issue if there is one. -->
|
|
25
|
+
|
|
26
|
+
## Test plan
|
|
27
|
+
|
|
28
|
+
<!-- Checklist of what you ran/verified locally. Tick the boxes you've
|
|
29
|
+
completed; leave unticked the things you'd like a reviewer to verify. -->
|
|
30
|
+
|
|
31
|
+
- [ ] `uv run pytest` passes
|
|
32
|
+
- [ ] `uv run ruff check src/ tests/` clean
|
|
33
|
+
- [ ] `uv run pyright` clean
|
|
34
|
+
- [ ] `uv run mypy src/sqlproof/` clean
|
|
35
|
+
- [ ] (if integration-affecting) tested locally against `supabase/postgres:15.8.1.040`
|
|
36
|
+
- [ ] (if user-facing) updated docs / README / examples
|
|
37
|
+
- [ ] (if breaking) PR title includes `!` or body includes `BREAKING CHANGE:` footer
|
|
38
|
+
|
|
39
|
+
## Related
|
|
40
|
+
|
|
41
|
+
<!-- Issues this closes, PRs this depends on, follow-ups filed. -->
|
|
42
|
+
|
|
43
|
+
- Closes #
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: 'Set up Supabase-shaped test database'
|
|
2
|
+
description: |
|
|
3
|
+
Apply SqlProof's Supabase test-init SQL to a running Postgres so a bare
|
|
4
|
+
`supabase/postgres` image matches managed Supabase semantics (plpgsql_check
|
|
5
|
+
extension, JSON-aware auth.uid/role/email/jwt). Call this AFTER your
|
|
6
|
+
service container's healthcheck passes and BEFORE running your tests.
|
|
7
|
+
|
|
8
|
+
inputs:
|
|
9
|
+
database-url:
|
|
10
|
+
description: |
|
|
11
|
+
PostgreSQL DSN to apply the migration against. Use the same value you
|
|
12
|
+
pass to your tests as SQLPROOF_DATABASE_URL.
|
|
13
|
+
required: true
|
|
14
|
+
verbose:
|
|
15
|
+
description: |
|
|
16
|
+
If "true", print the resulting extension list and auth surface to the
|
|
17
|
+
job log so you can see what's installed. Default "false".
|
|
18
|
+
required: false
|
|
19
|
+
default: 'false'
|
|
20
|
+
|
|
21
|
+
runs:
|
|
22
|
+
using: composite
|
|
23
|
+
steps:
|
|
24
|
+
- name: Apply Supabase test-init SQL
|
|
25
|
+
shell: bash
|
|
26
|
+
env:
|
|
27
|
+
DSN: ${{ inputs.database-url }}
|
|
28
|
+
run: |
|
|
29
|
+
# Resolve this action's own checkout path so the SQL file is found
|
|
30
|
+
# regardless of where the caller mounted things.
|
|
31
|
+
psql -v ON_ERROR_STOP=1 "$DSN" -f "${GITHUB_ACTION_PATH}/sql/supabase-test-init.sql"
|
|
32
|
+
|
|
33
|
+
- name: Print resulting Postgres surface
|
|
34
|
+
if: inputs.verbose == 'true'
|
|
35
|
+
shell: bash
|
|
36
|
+
env:
|
|
37
|
+
DSN: ${{ inputs.database-url }}
|
|
38
|
+
run: |
|
|
39
|
+
echo "=== installed extensions ==="
|
|
40
|
+
psql "$DSN" -c "SELECT extname, extversion FROM pg_extension ORDER BY extname;"
|
|
41
|
+
echo "=== auth schema functions ==="
|
|
42
|
+
psql "$DSN" -c "SELECT n.nspname || '.' || p.proname AS function FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = 'auth' ORDER BY proname;"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- Bring a bare `supabase/postgres` container into lockstep with managed
|
|
2
|
+
-- Supabase semantics, so SqlProof's RLS-aware helpers (auth.uid(),
|
|
3
|
+
-- auth.role(), as_rls_user) behave the same way they would in production.
|
|
4
|
+
--
|
|
5
|
+
-- This applies two things the bare image is missing:
|
|
6
|
+
--
|
|
7
|
+
-- 1. `plpgsql_check` extension. The binary ships with the image but isn't
|
|
8
|
+
-- installed in the default database. Needed by
|
|
9
|
+
-- sqlproof.contrib.plpgsql_coverage.
|
|
10
|
+
--
|
|
11
|
+
-- 2. GoTrue's `20220224000811_update_auth_functions` migration. The bare
|
|
12
|
+
-- image's `auth.uid()` only reads the legacy singular GUC
|
|
13
|
+
-- `request.jwt.claim.sub`. PostgREST 8+ (and SqlProof's
|
|
14
|
+
-- `as_rls_user` helper) write the modern JSON `request.jwt.claims`
|
|
15
|
+
-- GUC. Managed Supabase patches this at deploy time via GoTrue; we
|
|
16
|
+
-- apply the same migration here so the bare image matches.
|
|
17
|
+
--
|
|
18
|
+
-- Source: https://github.com/supabase/auth/blob/master/migrations/20220224000811_update_auth_functions.up.sql
|
|
19
|
+
|
|
20
|
+
CREATE EXTENSION IF NOT EXISTS plpgsql_check;
|
|
21
|
+
|
|
22
|
+
CREATE OR REPLACE FUNCTION auth.uid()
|
|
23
|
+
RETURNS uuid LANGUAGE sql STABLE AS $$
|
|
24
|
+
SELECT COALESCE(
|
|
25
|
+
NULLIF(current_setting('request.jwt.claim.sub', true), ''),
|
|
26
|
+
(NULLIF(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')
|
|
27
|
+
)::uuid
|
|
28
|
+
$$;
|
|
29
|
+
|
|
30
|
+
CREATE OR REPLACE FUNCTION auth.role()
|
|
31
|
+
RETURNS text LANGUAGE sql STABLE AS $$
|
|
32
|
+
SELECT COALESCE(
|
|
33
|
+
NULLIF(current_setting('request.jwt.claim.role', true), ''),
|
|
34
|
+
(NULLIF(current_setting('request.jwt.claims', true), '')::jsonb ->> 'role')
|
|
35
|
+
)::text
|
|
36
|
+
$$;
|
|
37
|
+
|
|
38
|
+
CREATE OR REPLACE FUNCTION auth.email()
|
|
39
|
+
RETURNS text LANGUAGE sql STABLE AS $$
|
|
40
|
+
SELECT COALESCE(
|
|
41
|
+
NULLIF(current_setting('request.jwt.claim.email', true), ''),
|
|
42
|
+
(NULLIF(current_setting('request.jwt.claims', true), '')::jsonb ->> 'email')
|
|
43
|
+
)::text
|
|
44
|
+
$$;
|
|
45
|
+
|
|
46
|
+
CREATE OR REPLACE FUNCTION auth.jwt()
|
|
47
|
+
RETURNS jsonb LANGUAGE sql STABLE AS $$
|
|
48
|
+
SELECT COALESCE(
|
|
49
|
+
NULLIF(current_setting('request.jwt.claim', true), ''),
|
|
50
|
+
NULLIF(current_setting('request.jwt.claims', true), '')
|
|
51
|
+
)::jsonb
|
|
52
|
+
$$;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Python runtime + dev dependencies declared in pyproject.toml.
|
|
4
|
+
# Dependabot bumps declared versions; uv-lock-refresh.yml regenerates
|
|
5
|
+
# uv.lock on each dependabot PR.
|
|
6
|
+
- package-ecosystem: pip
|
|
7
|
+
directory: "/"
|
|
8
|
+
schedule:
|
|
9
|
+
interval: weekly
|
|
10
|
+
day: monday
|
|
11
|
+
open-pull-requests-limit: 5
|
|
12
|
+
labels:
|
|
13
|
+
- dependencies
|
|
14
|
+
- python
|
|
15
|
+
commit-message:
|
|
16
|
+
prefix: chore
|
|
17
|
+
include: scope
|
|
18
|
+
|
|
19
|
+
# GitHub Actions versions (actions/checkout@vN, etc.)
|
|
20
|
+
- package-ecosystem: github-actions
|
|
21
|
+
directory: "/"
|
|
22
|
+
schedule:
|
|
23
|
+
interval: weekly
|
|
24
|
+
day: monday
|
|
25
|
+
open-pull-requests-limit: 5
|
|
26
|
+
labels:
|
|
27
|
+
- dependencies
|
|
28
|
+
- ci
|
|
29
|
+
commit-message:
|
|
30
|
+
prefix: chore
|
|
31
|
+
include: scope
|
|
32
|
+
|
|
33
|
+
# supabase/postgres image pin in workflows
|
|
34
|
+
- package-ecosystem: docker
|
|
35
|
+
directory: ".github/workflows"
|
|
36
|
+
schedule:
|
|
37
|
+
interval: weekly
|
|
38
|
+
day: monday
|
|
39
|
+
open-pull-requests-limit: 3
|
|
40
|
+
labels:
|
|
41
|
+
- dependencies
|
|
42
|
+
- ci
|
|
43
|
+
commit-message:
|
|
44
|
+
prefix: chore
|
|
45
|
+
include: scope
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
python:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
14
|
+
services:
|
|
15
|
+
postgres:
|
|
16
|
+
# Supabase's Postgres image bundles plpgsql_check, pgvector,
|
|
17
|
+
# pgsodium, pgjwt, etc., and creates the `auth` schema with
|
|
18
|
+
# `auth.uid()` / `auth.jwt()` helpers on first boot. This lets
|
|
19
|
+
# the plpgsql_coverage and (future) RLS-helper integration tests
|
|
20
|
+
# run against a realistic Supabase-shaped database.
|
|
21
|
+
image: supabase/postgres:15.8.1.040
|
|
22
|
+
env:
|
|
23
|
+
POSTGRES_PASSWORD: postgres
|
|
24
|
+
ports:
|
|
25
|
+
- 5432:5432
|
|
26
|
+
options: >-
|
|
27
|
+
--health-cmd "pg_isready -U postgres -d postgres"
|
|
28
|
+
--health-interval 10s
|
|
29
|
+
--health-timeout 5s
|
|
30
|
+
--health-retries 15
|
|
31
|
+
env:
|
|
32
|
+
SQLPROOF_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/postgres
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-python@v6
|
|
36
|
+
with:
|
|
37
|
+
python-version: ${{ matrix.python-version }}
|
|
38
|
+
- uses: astral-sh/setup-uv@v5
|
|
39
|
+
- run: uv sync --extra dev
|
|
40
|
+
- name: Bring Postgres surface into lockstep with managed Supabase
|
|
41
|
+
uses: ./.github/actions/setup-supabase-test-db
|
|
42
|
+
with:
|
|
43
|
+
database-url: ${{ env.SQLPROOF_TEST_DATABASE_URL }}
|
|
44
|
+
verbose: 'true'
|
|
45
|
+
- run: uv run ruff check src/ tests/
|
|
46
|
+
- run: uv run pyright
|
|
47
|
+
- run: uv run mypy src/sqlproof/
|
|
48
|
+
- run: uv run pytest --cov=sqlproof --cov-fail-under=94 --cov-report=xml
|
|
49
|
+
- name: Upload coverage to Codecov
|
|
50
|
+
if: matrix.python-version == '3.11'
|
|
51
|
+
uses: codecov/codecov-action@v6
|
|
52
|
+
with:
|
|
53
|
+
files: ./coverage.xml
|
|
54
|
+
fail_ci_if_error: false
|
|
55
|
+
# Codecov v4 requires a token on protected branches even for
|
|
56
|
+
# public repos. Get the token from
|
|
57
|
+
# https://app.codecov.io/gh/alialavia/sqlproof/config/general
|
|
58
|
+
# and add as repo secret CODECOV_TOKEN.
|
|
59
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
60
|
+
|
|
61
|
+
website:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v4
|
|
65
|
+
- uses: actions/setup-node@v4
|
|
66
|
+
with:
|
|
67
|
+
node-version: 20
|
|
68
|
+
cache: npm
|
|
69
|
+
cache-dependency-path: website/package-lock.json
|
|
70
|
+
- run: npm ci
|
|
71
|
+
working-directory: website
|
|
72
|
+
- run: npm run build
|
|
73
|
+
working-directory: website
|
|
@@ -33,6 +33,12 @@ jobs:
|
|
|
33
33
|
- name: Build
|
|
34
34
|
run: npm run build
|
|
35
35
|
working-directory: website
|
|
36
|
+
env:
|
|
37
|
+
# Optional. Set under Settings → Secrets and variables → Actions
|
|
38
|
+
# to enable PostHog tracking on the deployed site. When unset
|
|
39
|
+
# the snippet is omitted from the build (see website/src/posthog.mjs).
|
|
40
|
+
PUBLIC_POSTHOG_KEY: ${{ secrets.PUBLIC_POSTHOG_KEY }}
|
|
41
|
+
PUBLIC_POSTHOG_HOST: ${{ secrets.PUBLIC_POSTHOG_HOST }}
|
|
36
42
|
|
|
37
43
|
- name: Deploy to GitHub Pages
|
|
38
44
|
uses: peaceiris/actions-gh-pages@v4
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: PR title
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, edited, reopened, synchronize]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
pull-requests: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: lint
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
16
|
+
env:
|
|
17
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
18
|
+
with:
|
|
19
|
+
# Accepted types — keep in sync with release-please-config.json
|
|
20
|
+
# `changelog-sections`. The action validates the PR title matches
|
|
21
|
+
# `<type>(<optional-scope>)!?: <subject>` per Conventional Commits.
|
|
22
|
+
types: |
|
|
23
|
+
feat
|
|
24
|
+
fix
|
|
25
|
+
perf
|
|
26
|
+
docs
|
|
27
|
+
refactor
|
|
28
|
+
test
|
|
29
|
+
chore
|
|
30
|
+
ci
|
|
31
|
+
build
|
|
32
|
+
style
|
|
33
|
+
revert
|
|
34
|
+
# Scopes are optional; we don't enforce an allowlist (subsystem
|
|
35
|
+
# naming is too fluid to constrain at this scale).
|
|
36
|
+
requireScope: false
|
|
37
|
+
# Subject must start with a lowercase letter to match the
|
|
38
|
+
# project's existing commit style (`feat(core): skip insert ...`).
|
|
39
|
+
subjectPattern: ^[a-z].+$
|
|
40
|
+
subjectPatternError: |
|
|
41
|
+
The PR title subject must start with a lowercase letter
|
|
42
|
+
(e.g. "feat(core): add support for ..." not "Add support for ...").
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: release-please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
# No top-level permissions: release-please acts via the GitHub App token
|
|
8
|
+
# below, not the default GITHUB_TOKEN. The App's installation token
|
|
9
|
+
# carries its own permissions (contents:write, pull_requests:write,
|
|
10
|
+
# metadata:read) configured when the App was created.
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-please:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
# Mint a short-lived installation token from the `sqlproof-releases`
|
|
17
|
+
# GitHub App. Tags + commits pushed with this token DO trigger
|
|
18
|
+
# downstream workflows (unlike the default GITHUB_TOKEN, which
|
|
19
|
+
# GitHub Actions explicitly blocks from triggering recursive runs).
|
|
20
|
+
# That's what lets release.yml fire when release-please creates a
|
|
21
|
+
# v*.*.* tag.
|
|
22
|
+
- name: Mint release-please token from sqlproof-releases App
|
|
23
|
+
uses: actions/create-github-app-token@v1
|
|
24
|
+
id: app-token
|
|
25
|
+
with:
|
|
26
|
+
app-id: ${{ secrets.RELEASE_PLEASE_APP_ID }}
|
|
27
|
+
private-key: ${{ secrets.RELEASE_PLEASE_PRIVATE_KEY }}
|
|
28
|
+
|
|
29
|
+
- uses: googleapis/release-please-action@v5
|
|
30
|
+
with:
|
|
31
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
32
|
+
config-file: release-please-config.json
|
|
33
|
+
manifest-file: .release-please-manifest.json
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
# Manual fallback. Use this to publish a tag that was created before
|
|
8
|
+
# the sqlproof-releases GitHub App was wired into release-please.yml
|
|
9
|
+
# (where tag-push didn't auto-trigger this workflow), or to retry a
|
|
10
|
+
# failed publish without re-tagging. Specify the tag in the input.
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
tag:
|
|
14
|
+
description: 'Tag to build and publish (e.g. v0.2.0)'
|
|
15
|
+
required: true
|
|
16
|
+
type: string
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
services:
|
|
22
|
+
postgres:
|
|
23
|
+
# Mirror the CI service container so pre-publish testing
|
|
24
|
+
# exercises the same integration surface that PR CI does.
|
|
25
|
+
image: supabase/postgres:15.8.1.040
|
|
26
|
+
env:
|
|
27
|
+
POSTGRES_PASSWORD: postgres
|
|
28
|
+
ports:
|
|
29
|
+
- 5432:5432
|
|
30
|
+
options: >-
|
|
31
|
+
--health-cmd "pg_isready -U postgres -d postgres"
|
|
32
|
+
--health-interval 10s
|
|
33
|
+
--health-timeout 5s
|
|
34
|
+
--health-retries 15
|
|
35
|
+
env:
|
|
36
|
+
SQLPROOF_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/postgres
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
with:
|
|
40
|
+
# For workflow_dispatch, check out the tag the operator passed
|
|
41
|
+
# as input. For push events, default behavior checks out the
|
|
42
|
+
# tag-ref that triggered the workflow (no override needed).
|
|
43
|
+
ref: ${{ inputs.tag || github.ref }}
|
|
44
|
+
- uses: actions/setup-python@v6
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.11"
|
|
47
|
+
- uses: astral-sh/setup-uv@v5
|
|
48
|
+
- run: uv sync --extra dev
|
|
49
|
+
- name: Bring Postgres surface into lockstep with managed Supabase
|
|
50
|
+
uses: ./.github/actions/setup-supabase-test-db
|
|
51
|
+
with:
|
|
52
|
+
database-url: ${{ env.SQLPROOF_TEST_DATABASE_URL }}
|
|
53
|
+
- run: uv run pytest -m "not nocover"
|
|
54
|
+
- run: uv build
|
|
55
|
+
- uses: actions/upload-artifact@v4
|
|
56
|
+
with:
|
|
57
|
+
name: dist
|
|
58
|
+
path: dist/
|
|
59
|
+
|
|
60
|
+
publish:
|
|
61
|
+
needs: build
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
environment: pypi
|
|
64
|
+
permissions:
|
|
65
|
+
id-token: write
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/download-artifact@v4
|
|
68
|
+
with:
|
|
69
|
+
name: dist
|
|
70
|
+
path: dist/
|
|
71
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: uv-lock-refresh
|
|
2
|
+
|
|
3
|
+
# Dependabot's `pip` ecosystem bumps declared deps in pyproject.toml but
|
|
4
|
+
# doesn't know how to regenerate uv.lock. This workflow runs `uv lock` on
|
|
5
|
+
# every dependabot PR and pushes the updated lockfile back to the PR
|
|
6
|
+
# branch so the merge is internally consistent.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
pull_request:
|
|
10
|
+
paths:
|
|
11
|
+
- pyproject.toml
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
refresh:
|
|
18
|
+
# Only run on PRs opened by Dependabot. Other PRs that touch
|
|
19
|
+
# pyproject.toml should update uv.lock manually (and reviewers can
|
|
20
|
+
# catch drift).
|
|
21
|
+
if: github.actor == 'dependabot[bot]'
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
ref: ${{ github.head_ref }}
|
|
27
|
+
# GH Actions can't push back to a PR branch by default; use a
|
|
28
|
+
# PAT-less approach via `actions/checkout` with the default
|
|
29
|
+
# token, which works because we're pushing to the same repo
|
|
30
|
+
# the workflow runs in.
|
|
31
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
+
- uses: astral-sh/setup-uv@v5
|
|
33
|
+
- name: Refresh uv.lock
|
|
34
|
+
run: uv lock
|
|
35
|
+
- name: Commit and push if lockfile changed
|
|
36
|
+
run: |
|
|
37
|
+
if git diff --quiet uv.lock; then
|
|
38
|
+
echo "uv.lock unchanged; nothing to do."
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
git config user.name "github-actions[bot]"
|
|
42
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
43
|
+
git add uv.lock
|
|
44
|
+
git commit -m "chore(deps): refresh uv.lock"
|
|
45
|
+
git push
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://sqlproof.dev/schemas/counterexample-v1.json",
|
|
3
|
+
"dataset": {
|
|
4
|
+
"orders": [
|
|
5
|
+
{
|
|
6
|
+
"id": 1,
|
|
7
|
+
"total": 0
|
|
8
|
+
}
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
"failure": {
|
|
12
|
+
"kind": "UndefinedTable",
|
|
13
|
+
"locals": {},
|
|
14
|
+
"message": "relation \"orders\" does not exist\nLINE 1: SELECT id FROM orders\n ^",
|
|
15
|
+
"traceback": []
|
|
16
|
+
},
|
|
17
|
+
"property_name": "property_fails",
|
|
18
|
+
"row_context": {},
|
|
19
|
+
"runs": 110,
|
|
20
|
+
"schema_fingerprint": "sha256:10216d67c52fe4492028569c0a44ea070c450fb3488ad02a3599c35192366658",
|
|
21
|
+
"seed": null,
|
|
22
|
+
"shrink_steps": 0,
|
|
23
|
+
"version": 1
|
|
24
|
+
}
|