Skip to content

Commit 060eacb

Browse files
committed
feat: Package scaffolding, CI, lint/mypy/coverage gating
Adds the repo plumbing the rest of the branch builds on: - pyproject (uv build backend, mypy strict, 100% branch coverage gate, clickhouse-connect dev dep) - Makefile (install / lint / typecheck / test) - pre-commit (ruff, uv-lock, flagsmith-lint-tests, local mypy) - GitHub Actions CI: lint → typecheck → ClickHouse docker-compose → test → cobertura coverage gate - engine-test-data submodule pinned at v3.7.0 - docker-compose for the ClickHouse parity harness - CODEOWNERS, renovate, .python-version, gitignore additions - py.typed marker and empty package skeleton beep boop
1 parent 0d41586 commit 060eacb

15 files changed

Lines changed: 1222 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [ main ]
7+
8+
jobs:
9+
ci:
10+
name: CI
11+
runs-on: ubuntu-latest
12+
env:
13+
CLICKHOUSE_HOST: localhost
14+
CLICKHOUSE_PORT: "8123"
15+
steps:
16+
- uses: actions/checkout@v5
17+
with:
18+
submodules: recursive
19+
- uses: astral-sh/setup-uv@v7
20+
with:
21+
enable-cache: true
22+
- run: make lint
23+
- run: make typecheck
24+
- name: Start ClickHouse
25+
run: docker compose up --detach --wait clickhouse
26+
- run: make test
27+
- name: Check Coverage
28+
uses: 5monkeys/cobertura-action@v14
29+
with:
30+
minimum_coverage: 100
31+
fail_below_threshold: true
32+
show_missing: true

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ wheels/
1313
.pytest_cache/
1414
.mypy_cache/
1515
.ruff_cache/
16+
17+
# Coverage
18+
.coverage
19+
coverage.xml
20+
htmlcov/
21+
22+
# Local secrets
23+
.env

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "engine-test-data"]
2+
path = engine-test-data
3+
url = https://github.com/Flagsmith/engine-test-data.git
4+
branch = v3.7.0

.pre-commit-config.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.15.6
4+
hooks:
5+
- id: ruff-check
6+
args: [--fix]
7+
- id: ruff-format
8+
- repo: https://github.com/astral-sh/uv-pre-commit
9+
rev: 0.10.10
10+
hooks:
11+
- id: uv-lock
12+
- repo: https://github.com/pre-commit/pre-commit-hooks
13+
rev: v6.0.0
14+
hooks:
15+
- id: check-yaml
16+
- id: check-json
17+
- id: check-toml
18+
- repo: https://github.com/Flagsmith/flagsmith-common
19+
rev: v3.8.2
20+
hooks:
21+
- id: flagsmith-lint-tests
22+
- repo: local
23+
hooks:
24+
- id: python-typecheck
25+
name: python-typecheck
26+
language: system
27+
entry: make typecheck
28+
require_serial: true
29+
pass_filenames: false
30+
types: [python]

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.10

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @flagsmith/flagsmith-back-end

Makefile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.PHONY: install-packages
2+
install-packages: ## Install all required packages
3+
uv sync
4+
5+
.PHONY: install-pre-commit
6+
install-pre-commit: ## Install pre-commit hooks
7+
uv run prek install
8+
9+
.PHONY: install
10+
install: install-packages install-pre-commit ## Ensure the environment is set up
11+
12+
.PHONY: lint
13+
lint: ## Run linters (pre-commit hooks across the tree)
14+
uv run prek run --all-files
15+
16+
.PHONY: test
17+
test: ## Run unit tests. Override scope with opts, e.g. `make test opts='-m engine_parity'`
18+
uv run pytest $(opts)
19+
20+
.PHONY: typecheck
21+
typecheck: ## Run mypy
22+
uv run mypy
23+
24+
.PHONY: help
25+
help:
26+
@echo "Usage: make [target]"
27+
@echo ""
28+
@echo "Available targets:"
29+
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

docker-compose.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
services:
2+
clickhouse:
3+
image: clickhouse/clickhouse-server:25.5.6
4+
environment:
5+
# Skip the random-password bootstrap. The container is only ever
6+
# reachable from the harness on the same compose network / host
7+
# loopback, so the default `default` user with no password is fine.
8+
CLICKHOUSE_SKIP_USER_SETUP: "1"
9+
ports:
10+
- "8123:8123"
11+
ulimits:
12+
nofile:
13+
soft: 262144
14+
hard: 262144
15+
healthcheck:
16+
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8123/ping"]
17+
interval: 2s
18+
timeout: 2s
19+
retries: 15

engine-test-data

Submodule engine-test-data added at 4b29dc7

pyproject.toml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
[project]
2+
name = "flagsmith-sql-flag-engine"
3+
version = "0.1.0a2"
4+
description = "SQL translator for Flagsmith segment predicates."
5+
readme = "README.md"
6+
authors = [{ name = "Flagsmith", email = "engineering@flagsmith.com" }]
7+
requires-python = ">=3.10"
8+
license = "BSD-3-Clause"
9+
classifiers = [
10+
"Programming Language :: Python :: 3 :: Only",
11+
"Programming Language :: SQL",
12+
"Topic :: Database",
13+
]
14+
dependencies = ["flagsmith-flag-engine>=10", "jsonpath-rfc9535>=0.2"]
15+
16+
[project.urls]
17+
Homepage = "https://github.com/Flagsmith/flagsmith-sql-flag-engine"
18+
19+
[dependency-groups]
20+
dev = [
21+
"pytest>=8",
22+
"pytest-xdist>=3",
23+
"mypy>=1.10",
24+
"prek>=0.3",
25+
"clickhouse-connect>=0.7",
26+
"json5>=0.14.0",
27+
"pytest-cov>=7.1.0",
28+
]
29+
30+
[build-system]
31+
requires = ["uv_build>=0.8.14,<0.9.0"]
32+
build-backend = "uv_build"
33+
34+
[tool.pytest.ini_options]
35+
addopts = [
36+
"-ra",
37+
"--cov",
38+
"src",
39+
"--cov-report",
40+
"term-missing",
41+
"--cov-report",
42+
"xml",
43+
]
44+
testpaths = ["tests"]
45+
46+
[tool.coverage.run]
47+
branch = true
48+
source = ["src"]
49+
50+
[tool.coverage.report]
51+
# `match` statements exhaustive over a Literal type record a phantom
52+
# fall-through branch from the last case to function exit; coverage.py
53+
# can't see the type-system exhaustiveness mypy enforces. Treat any
54+
# `case` line as a possibly-partial branch so the gate stays at 100%
55+
# without us littering the source with `# pragma: no branch`.
56+
partial_branches = [
57+
"pragma: no branch",
58+
"case .+:",
59+
]
60+
61+
[tool.ruff]
62+
target-version = "py310"
63+
line-length = 100
64+
65+
[tool.ruff.lint]
66+
select = ["E", "F", "I", "B", "UP"]
67+
68+
[tool.mypy]
69+
strict = true
70+
python_version = "3.10"
71+
files = ["src/flagsmith_sql_flag_engine", "tests"]
72+
73+
[[tool.mypy.overrides]]
74+
module = "clickhouse_connect.*"
75+
ignore_missing_imports = true

0 commit comments

Comments
 (0)