Skip to content

Commit f0cc885

Browse files
committed
Interactive project setup for sqlmesh init
1 parent 11ce8c8 commit f0cc885

2 files changed

Lines changed: 242 additions & 29 deletions

File tree

sqlmesh/cli/example_project.py

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from pathlib import Path
44
from dataclasses import dataclass
55

6-
import click
76
from sqlglot import Dialect
87
from sqlmesh.integrations.dlt import generate_dlt_models_and_settings
98
from sqlmesh.utils.date import yesterday_ds
9+
from sqlmesh.utils.errors import SQLMeshError
1010

1111
from sqlmesh.core.config.connection import CONNECTION_CONFIG_TO_TYPE
1212

@@ -15,17 +15,23 @@
1515

1616

1717
class ProjectTemplate(Enum):
18+
DEFAULT = "default"
19+
EMPTY = "empty"
1820
DBT = "dbt"
1921
DLT = "dlt"
22+
23+
24+
class InitCliMode(Enum):
2025
DEFAULT = "default"
21-
EMPTY = "empty"
26+
SIMPLE = "simple"
2227

2328

2429
def _gen_config(
2530
dialect: t.Optional[str],
2631
settings: t.Optional[str],
2732
start: t.Optional[str],
2833
template: ProjectTemplate,
34+
cli_mode: InitCliMode,
2935
) -> str:
3036
connection_settings = (
3137
settings
@@ -76,16 +82,29 @@ def _gen_config(
7682
)
7783

7884
default_configs = {
79-
ProjectTemplate.DEFAULT: f"""gateways:
85+
ProjectTemplate.DEFAULT: f"""# --- Gateway Connection ---
86+
gateways:
8087
{dialect}:
8188
connection:
8289
{connection_settings}
83-
8490
default_gateway: {dialect}
8591
92+
# --- Model Defaults ---
93+
# https://sqlmesh.readthedocs.io/en/stable/reference/model_configuration/#model-defaults
94+
8695
model_defaults:
8796
dialect: {dialect}
8897
start: {start or yesterday_ds()}
98+
99+
# --- Linting Rules ---
100+
# Enforce standards for your team
101+
# https://sqlmesh.readthedocs.io/en/stable/guides/linter/
102+
103+
linter:
104+
enabled: true
105+
rules:
106+
- ambiguousorinvalidcolumn
107+
- invalidselectstarexpansion
89108
""",
90109
ProjectTemplate.DBT: """from pathlib import Path
91110
@@ -97,7 +116,29 @@ def _gen_config(
97116

98117
default_configs[ProjectTemplate.EMPTY] = default_configs[ProjectTemplate.DEFAULT]
99118
default_configs[ProjectTemplate.DLT] = default_configs[ProjectTemplate.DEFAULT]
100-
return default_configs[template]
119+
120+
simple_cli_mode = """
121+
# --- SIMPLE CLI MODE ---
122+
# Minimal prompts, automatic changes, summary output
123+
# https://sqlmesh.readthedocs.io/en/stable/reference/configuration/#plan
124+
125+
plan:
126+
enable_preview: true # Enable preview for forward-only models when targeting a development environment
127+
no_diff: true # Hide detailed text differences for changed models
128+
use_finalized_state: true # Compare only against finalized snapshots
129+
no_prompts: true # No interactive prompts
130+
auto_apply: true # Apply changes automatically
131+
132+
# --- Optional: Set a default target environment ---
133+
# default_target_environment: dev_{{ env_var('USER', 'your_name') }}
134+
135+
# Example usage:
136+
# export USER=your_name
137+
# sqlmesh plan # Resolves to: sqlmesh plan dev_your_name
138+
# sqlmesh plan prod # To apply changes to production
139+
"""
140+
141+
return default_configs[template] + (simple_cli_mode if cli_mode == InitCliMode.SIMPLE else "")
101142

102143

103144
@dataclass
@@ -237,7 +278,8 @@ def init_example_project(
237278
pipeline: t.Optional[str] = None,
238279
dlt_path: t.Optional[str] = None,
239280
schema_name: str = "sqlmesh_example",
240-
) -> None:
281+
cli_mode: InitCliMode = InitCliMode.DEFAULT,
282+
) -> t.Union[str, Path]:
241283
root_path = Path(path)
242284
config_extension = "py" if template == ProjectTemplate.DBT else "yaml"
243285
config_path = root_path / f"config.{config_extension}"
@@ -248,12 +290,12 @@ def init_example_project(
248290
tests_path = root_path / "tests"
249291

250292
if config_path.exists():
251-
raise click.ClickException(f"Found an existing config in '{config_path}'")
293+
raise SQLMeshError(
294+
f"Found an existing config file '{config_path}'.\n\nPlease change to another directory or remove the existing file."
295+
)
252296

253297
if not dialect and template != ProjectTemplate.DBT:
254-
raise click.ClickException(
255-
"Default SQL dialect is a required argument for SQLMesh projects"
256-
)
298+
raise SQLMeshError("Please provide a default SQL dialect for your project's models.")
257299

258300
models: t.Set[t.Tuple[str, str]] = set()
259301
settings = None
@@ -264,19 +306,19 @@ def init_example_project(
264306
pipeline_name=pipeline, dialect=dialect, dlt_path=dlt_path
265307
)
266308
else:
267-
raise click.ClickException(
268-
"DLT pipeline is a required argument to generate a SQLMesh project from DLT"
309+
raise SQLMeshError(
310+
"Please provide a DLT pipeline with the `--dlt-pipeline` flag to generate a SQLMesh project from DLT."
269311
)
270312

271-
_create_config(config_path, dialect, settings, start, template)
313+
_create_config(config_path, dialect, settings, start, template, cli_mode)
272314
if template == ProjectTemplate.DBT:
273-
return
315+
return config_path
274316

275317
_create_folders([audits_path, macros_path, models_path, seeds_path, tests_path])
276318

277319
if template == ProjectTemplate.DLT:
278320
_create_models(models_path, models)
279-
return
321+
return config_path
280322

281323
example_objects = _gen_example_objects(schema_name=schema_name)
282324

@@ -287,6 +329,8 @@ def init_example_project(
287329
_create_seeds(seeds_path, example_objects)
288330
_create_tests(tests_path, example_objects)
289331

332+
return config_path
333+
290334

291335
def _create_folders(target_folders: t.Sequence[Path]) -> None:
292336
for folder_path in target_folders:
@@ -300,11 +344,12 @@ def _create_config(
300344
settings: t.Optional[str],
301345
start: t.Optional[str],
302346
template: ProjectTemplate,
347+
cli_mode: InitCliMode,
303348
) -> None:
304349
if dialect:
305350
Dialect.get_or_raise(dialect)
306351

307-
project_config = _gen_config(dialect, settings, start, template)
352+
project_config = _gen_config(dialect, settings, start, template, cli_mode)
308353

309354
_write_file(
310355
config_path,

0 commit comments

Comments
 (0)