SHELL := /bin/bash

.PHONY: verify coverage

format:
	uv run ruff format .


lint:
	uv run ruff check --fix .


type:
	uv run ty check src tests


test:
	uv run pytest tests/unit tests/integration -m "not real_warehouse and not dbt" -vv


test-all:
	uv run pytest tests -m "not real_warehouse and not dbt" -vv


test-e2e-duckdb:
	uv run pytest tests/e2e -m "not real_warehouse and not dbt and not performance" -vv -n auto --dist loadfile
	uv run pytest tests/e2e -m "performance and not real_warehouse and not dbt" -vv


test-virtual:
	TESTCONTAINERS_RYUK_DISABLED=true SQLBUILD_CONCURRENCY=$(SQLBUILD_CONCURRENCY) uv run pytest \
		$(VIRTUAL_TEST_ROOTS) \
		-k "$(VIRTUAL_TEST_KEYWORD)" \
		-m "not dbt and not performance" -vv -n auto --dist loadfile


skills:
	uv run sqb skills update --global --target opencode
	uv run python -m scripts.skills.update_structure_skill


# dbt executable used by interop tests. Defaults to `dbt` on PATH; override with
# the Fusion binary for faster compiles, e.g. `make test-dbt DBT_EXECUTABLE=dbtf`
# or by exporting DBT_EXECUTABLE in your shell.
DBT_EXECUTABLE ?= dbt
export DBT_EXECUTABLE

# Default per-project SQLBuild execution concurrency for verify runs. Override with
# `make verify SQLBUILD_CONCURRENCY=8` or by exporting SQLBUILD_CONCURRENCY.
SQLBUILD_CONCURRENCY ?= 8

# Virtual-environment focused test selection. Override roots/keyword to zoom in,
# e.g. `make test-virtual VIRTUAL_TEST_ROOTS=tests/e2e/src/sqlbuild/cli/commands/main/build`.
VIRTUAL_TEST_ROOTS ?= tests/e2e/src/sqlbuild/cli/commands/main tests/e2e/src/sqlbuild/integrations/dagster
VIRTUAL_TEST_KEYWORD ?= virtual or reconcile or diff or janitor or snapshot or dagster


test-dbt:
	@mkdir -p /tmp/opencode
	@log=/tmp/opencode/test-dbt-$$(date +%Y%m%d-%H%M%S).log; \
	echo "Logging to $$log (DBT_EXECUTABLE=$(DBT_EXECUTABLE))"; \
	uv run pytest tests/integration/src/sqlbuild/integrations/dbt tests/e2e/src/sqlbuild/cli/commands/main/dbt -m "dbt and not real_warehouse" -vv --color=yes -n auto --dist load 2>&1 | tee "$$log"; \
	status=$${PIPESTATUS[0]}; \
	echo "Full output saved to $$log"; \
	exit $$status


DBT_TEST_PATHS := tests/integration/src/sqlbuild/integrations/dbt tests/e2e/src/sqlbuild/cli/commands/main/dbt


test-dbt-real:
	uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse" -vv -n auto --dist load


test-dbt-real-snowflake:
	uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse and snowflake" -vv -n auto --dist load


test-dbt-real-bigquery:
	uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse and bigquery" -vv -n auto --dist load


test-dbt-real-databricks:
	uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse and databricks" -vv -n auto --dist load


test-dbt-real-postgres:
	TESTCONTAINERS_RYUK_DISABLED=true uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse and postgres" -vv -n auto --dist load


test-dbt-real-sqlserver:
	uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse and sqlserver" -vv -n auto --dist load


test-dbt-real-motherduck:
	uv run pytest $(DBT_TEST_PATHS) -m "dbt and real_warehouse and motherduck" -vv -n auto --dist load


waffle-shop:
	cd tests/e2e/fixtures/waffle_shop && $${SHELL:-/bin/sh}


test-real:
	uv run pytest tests -m real_warehouse -vv


test-real-all: test-real


test-real-snowflake:
	uv run pytest tests -m "real_warehouse and snowflake" -vv


test-real-bigquery:
	uv run pytest tests -m "real_warehouse and bigquery" -vv


test-real-databricks:
	uv run pytest tests -m "real_warehouse and databricks" -vv


test-real-postgres:
	TESTCONTAINERS_RYUK_DISABLED=true uv run pytest tests -m "real_warehouse and postgres" -vv -n auto --dist load


test-real-sqlserver:
	uv run pytest tests -m "real_warehouse and sqlserver" -vv


test-real-motherduck:
	uv run pytest tests -m "real_warehouse and motherduck" -vv


test-e2e-real-snowflake:
	uv run pytest tests/e2e -m "real_warehouse and snowflake" -vv


test-e2e-real-bigquery:
	uv run pytest tests/e2e -m "real_warehouse and bigquery" -vv


test-e2e-real-databricks:
	uv run pytest tests/e2e -m "real_warehouse and databricks" -vv


check-test-conventions:
	uv run check-test-conventions tests


check-structure-conventions:
	uv run check-structure-conventions src/sqlbuild scripts


check-type-annotation-conventions:
	uv run check-type-annotation-conventions src tests


check:
	uv run ruff format .
	uv run ruff check --fix .
	uv run ty check src tests
	uv run pytest tests/unit/src/sqlbuild/adapter/strict/test_strict_adapter.py -q
	uv run check-test-conventions tests
	uv run check-structure-conventions src/sqlbuild scripts
	uv run check-type-annotation-conventions src tests


verify:
	@mkdir -p /tmp/opencode
	@log="/tmp/opencode/verify-$$(date +%Y%m%d-%H%M%S).log"; \
	{ \
		status=0; \
		run_verify_step() { \
			label="$$1"; \
			shift; \
			echo; \
			echo "==> $$label"; \
			"$$@"; \
			rc=$$?; \
			if [ $$rc -ne 0 ]; then \
				echo "STEP_FAILED[$$rc]: $$label"; \
				if [ $$status -eq 0 ]; then status=$$rc; fi; \
			fi; \
		}; \
		run_verify_step "ruff format" uv run ruff format .; \
		run_verify_step "ruff check" uv run ruff check --fix .; \
		run_verify_step "type check" uv run ty check src tests; \
		run_verify_step "tests" env PYTHONUNBUFFERED=1 TESTCONTAINERS_RYUK_DISABLED=true SQLBUILD_CONCURRENCY=$(SQLBUILD_CONCURRENCY) uv run pytest tests/unit tests/integration tests/e2e -m "((not real_warehouse and not dbt) or (dbt and not real_warehouse) or (real_warehouse and postgres)) and not performance" -vv --color=yes -n auto --dist loadfile; \
		run_verify_step "performance tests" env PYTHONUNBUFFERED=1 SQLBUILD_CONCURRENCY=$(SQLBUILD_CONCURRENCY) uv run pytest tests/e2e -m "performance and not real_warehouse and not dbt" -vv --color=yes; \
		run_verify_step "test conventions" uv run check-test-conventions tests; \
		run_verify_step "structure conventions" uv run check-structure-conventions src/sqlbuild scripts; \
		run_verify_step "type annotation conventions" uv run check-type-annotation-conventions src tests; \
		exit $$status; \
	} 2>&1 | tee "$$log"; \
	status=$${PIPESTATUS[0]}; \
	echo "VERIFY_EXIT=$$status (log: $$log)" | tee -a "$$log"; \
	exit $$status


coverage:
	@mkdir -p /tmp/opencode
	@log="/tmp/opencode/coverage-$$(date +%Y%m%d-%H%M%S).log"; \
	PYTHONUNBUFFERED=1 uv run pytest tests -m "not real_warehouse and not dbt" -vv --color=yes \
		--cov=src/sqlbuild --cov-branch \
		--cov-report=term-missing --cov-report=html --cov-report=xml \
		2>&1 | tee "$$log"; \
	status=$${PIPESTATUS[0]}; \
	echo "COVERAGE_EXIT=$$status (log: $$log)" | tee -a "$$log"; \
	exit $$status


verify-quick:
	uv run ruff format .
	uv run ruff check --fix .
	uv run ty check src tests
	uv run pytest tests/unit tests/integration -m "not real_warehouse and not dbt" -vv
	uv run check-test-conventions tests
	uv run check-structure-conventions src/sqlbuild scripts
	uv run check-type-annotation-conventions src tests


check-ci:
	uv run ruff format --check .
	uv run ruff check .
	uv run ty check src tests
	uv run pytest tests/unit/src/sqlbuild/adapter/strict/test_strict_adapter.py -q
	uv run check-test-conventions tests
	uv run check-structure-conventions src/sqlbuild scripts
	uv run check-type-annotation-conventions src tests


verify-ci:
	uv run ruff format --check .
	uv run ruff check .
	uv run ty check src tests
	uv run pytest tests/unit tests/integration -m "not real_warehouse and not dbt" -vv
	uv run pytest tests/e2e -m "not real_warehouse and not dbt and not performance" -vv -n auto --dist loadfile
	uv run pytest tests/e2e -m "performance and not real_warehouse and not dbt" -vv
	uv run check-test-conventions tests
	uv run check-structure-conventions src/sqlbuild scripts
	uv run check-type-annotation-conventions src tests
