Skip to content

Commit 00ad1e9

Browse files
Merge branch 'main' into fix-postgres-grants-clean
2 parents 58947c2 + 7a68c2a commit 00ad1e9

18 files changed

Lines changed: 658 additions & 74 deletions

File tree

.github/workflows/pr.yaml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
steps:
5151
- uses: actions/checkout@v7
5252
- name: Set up Python
53-
uses: actions/setup-python@v6
53+
uses: actions/setup-python@v7
5454
with:
5555
python-version: '3.10'
5656
- name: Install uv
@@ -83,7 +83,7 @@ jobs:
8383
with:
8484
fetch-depth: 0
8585
- name: Set up Python
86-
uses: actions/setup-python@v6
86+
uses: actions/setup-python@v7
8787
with:
8888
python-version: ${{ matrix.python-version }}
8989
- name: Install uv
@@ -135,7 +135,7 @@ jobs:
135135
- name: Install make
136136
run: choco install make which -y
137137
- name: Set up Python
138-
uses: actions/setup-python@v6
138+
uses: actions/setup-python@v7
139139
with:
140140
python-version: '3.12'
141141
- name: Install SQLMesh dev dependencies
@@ -172,7 +172,7 @@ jobs:
172172
with:
173173
fetch-depth: 0
174174
- name: Set up Python
175-
uses: actions/setup-python@v6
175+
uses: actions/setup-python@v7
176176
with:
177177
python-version: '3.10'
178178
- name: Install uv
@@ -194,16 +194,16 @@ jobs:
194194
runs-on: ubuntu-latest
195195
steps:
196196
- uses: actions/checkout@v7
197-
- uses: actions/setup-node@v6
197+
- uses: actions/setup-node@v7
198198
with:
199199
node-version: '22'
200-
- uses: pnpm/action-setup@v4
200+
- uses: pnpm/action-setup@v6
201201
with:
202202
version: latest
203203
- name: Get pnpm store directory
204204
id: pnpm-cache
205205
run: echo "store=$(pnpm store path)" >> $GITHUB_OUTPUT
206-
- uses: actions/cache@v5
206+
- uses: actions/cache@v6
207207
with:
208208
path: ${{ steps.pnpm-cache.outputs.store }}
209209
key: pnpm-store-${{ hashFiles('pnpm-lock.yaml') }}
@@ -260,7 +260,7 @@ jobs:
260260
steps:
261261
- uses: actions/checkout@v7
262262
- name: Set up Python
263-
uses: actions/setup-python@v6
263+
uses: actions/setup-python@v7
264264
with:
265265
python-version: '3.12'
266266
- name: Install uv
@@ -344,7 +344,7 @@ jobs:
344344
steps:
345345
- uses: actions/checkout@v7
346346
- name: Set up Python
347-
uses: actions/setup-python@v6
347+
uses: actions/setup-python@v7
348348
with:
349349
python-version: '3.12'
350350
- name: Install uv
@@ -399,10 +399,10 @@ jobs:
399399
if: false
400400
steps:
401401
- uses: actions/checkout@v7
402-
- uses: actions/setup-node@v6
402+
- uses: actions/setup-node@v7
403403
with:
404404
node-version: '22'
405-
- uses: pnpm/action-setup@v4
405+
- uses: pnpm/action-setup@v6
406406
with:
407407
version: latest
408408
- name: Install dependencies
@@ -416,16 +416,16 @@ jobs:
416416
if: false
417417
steps:
418418
- uses: actions/checkout@v7
419-
- uses: actions/setup-node@v6
419+
- uses: actions/setup-node@v7
420420
with:
421421
node-version: '22'
422-
- uses: pnpm/action-setup@v4
422+
- uses: pnpm/action-setup@v6
423423
with:
424424
version: latest
425425
- name: Install dependencies
426426
run: pnpm install
427427
- name: Set up Python
428-
uses: actions/setup-python@v6
428+
uses: actions/setup-python@v7
429429
with:
430430
python-version: '3.12'
431431
- name: Install uv
@@ -461,7 +461,7 @@ jobs:
461461
steps:
462462
- uses: actions/checkout@v7
463463
- name: Set up Python
464-
uses: actions/setup-python@v6
464+
uses: actions/setup-python@v7
465465
with:
466466
python-version: '3.10'
467467
- name: Install uv

.github/workflows/release.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- uses: actions/checkout@v7
13-
- uses: actions/setup-node@v6
13+
- uses: actions/setup-node@v7
1414
with:
1515
node-version: '22'
16-
- uses: pnpm/action-setup@v4
16+
- uses: pnpm/action-setup@v6
1717
with:
1818
version: latest
1919
- name: Install dependencies
@@ -38,7 +38,7 @@ jobs:
3838
name: ui-dist
3939
path: web/client/dist/
4040
- name: Set up Python
41-
uses: actions/setup-python@v6
41+
uses: actions/setup-python@v7
4242
with:
4343
python-version: '3.10'
4444
- name: Install uv
@@ -65,7 +65,7 @@ jobs:
6565
with:
6666
fetch-depth: 0
6767
- name: Create release on GitHub
68-
uses: softprops/action-gh-release@v2
68+
uses: softprops/action-gh-release@v3
6969
with:
7070
generate_release_notes: true
7171
tag_name: ${{ github.ref_name }}

.github/workflows/release_extension.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ jobs:
2828
fi
2929
echo "Version format is valid: $version"
3030
- name: Setup Node.js
31-
uses: actions/setup-node@v6
31+
uses: actions/setup-node@v7
3232
with:
3333
node-version: '22'
3434
- name: Install pnpm
35-
uses: pnpm/action-setup@v4
35+
uses: pnpm/action-setup@v6
3636
with:
3737
version: 10
3838
- name: Install dependencies

.github/workflows/release_shared_js.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
fi
3232
echo "Version format is valid: $version"
3333
- name: Setup Node.js
34-
uses: actions/setup-node@v6
34+
uses: actions/setup-node@v7
3535
with:
3636
node-version: '22'
3737
registry-url: 'https://registry.npmjs.org'
@@ -40,7 +40,7 @@ jobs:
4040
- name: Print npm version
4141
run: npm --version
4242
- name: Install pnpm
43-
uses: pnpm/action-setup@v4
43+
uses: pnpm/action-setup@v6
4444
with:
4545
version: 10
4646
- name: Install dependencies

docs/guides/configuration.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,16 @@ By default, the SQLMesh cache is stored in a `.cache` directory within your proj
329329

330330
The cache directory is automatically created if it doesn't exist. You can clear the cache using the `sqlmesh clean` command.
331331

332+
#### Project index
333+
334+
The `--use-project-index` option on supported commands maintains a persistent model dependency index in the cache directory. Each project writes a file named `<project>_<hash>_model_index.json`.
335+
336+
A full project load with the option enabled creates or refreshes the index. SQLMesh invalidates it when relevant configuration, gateway, macro, audit, or signal metadata changes, or when the set of model files changes. If the index is missing, invalid, or stale, SQLMesh safely falls back to a full project load and rebuilds it.
337+
338+
For operations targeting selected models, the index allows SQLMesh to load only those models and their upstream dependencies.
339+
340+
In multi-repository projects, dependencies that cross project boundaries may not be represented by an individual project's index. SQLMesh detects incomplete scoped loads and falls back to loading the full configured project set.
341+
332342
### Table/view storage locations
333343

334344
SQLMesh creates schemas, physical tables, and views in the data warehouse/engine. Learn more about why and how SQLMesh creates schema in the ["Why does SQLMesh create schemas?" FAQ](../faq/faq.md#schema-question).

docs/guides/linter.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@ $ sqlmesh lint --local
135135

136136
This can make linting faster in repositories where all referenced models are loaded from local files. In multi-repository setups, or when linting only a subset of projects, `--local` may cause additional linting errors because SQLMesh will not resolve references or schemas from models that exist only in remote state.
137137

138+
For faster targeted linting, enable the persistent project index with `--use-project-index`. When
139+
models are selected with `--model`, SQLMesh loads, resolves, and validates only those models and
140+
their transitive upstream dependencies. The same behavior can be enabled by default for the
141+
Python API and CLI with the `linter.use_project_index` configuration option:
142+
143+
```yaml
144+
linter:
145+
enabled: true
146+
use_project_index: true
147+
```
148+
149+
`Context.lint_models` uses this configuration value when `use_project_index` is omitted. Passing
150+
`use_project_index=False` explicitly disables it for that call. If a context was already loaded,
151+
an indexed lint of selected models reloads the context so the requested scope is applied.
152+
138153

139154
## Applying linting rules
140155

docs/reference/cli.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,12 @@ Usage: sqlmesh lint [OPTIONS]
650650
651651
Options:
652652
--model TEXT A model to lint. Multiple models can be linted. If no models are specified, every model will be linted.
653+
--use-project-index Use the persistent project index. With --model, only the selected models and their upstream dependencies
654+
are loaded, resolved, and validated, so errors in unrelated models are not reported. Without --model,
655+
every model is still loaded and linted.
653656
--local Lint using only locally loaded project files without loading state. In multi-repository setups, or when
654657
linting only a subset of projects, this may cause additional linting errors because SQLMesh will not resolve
655658
references or schemas from models that exist only in remote state.
656659
--help Show this message and exit.
657660
658-
```
661+
```

docs/reference/configuration.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ The `model_defaults` key is **required** and must contain a value for the `diale
6060

6161
See all the keys allowed in `model_defaults` at the [model configuration reference page](./model_configuration.md#model-defaults).
6262

63+
### Linter
64+
65+
| Option | Description | Type | Required |
66+
|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|---------|----------|
67+
| `linter.enabled` | Whether linting is enabled (Default: `False`) | boolean | N |
68+
| `linter.use_project_index` | Whether to use the persistent project index for linting. Targeted linting loads selected models and their upstream dependencies. (Default: `False`) | boolean | N |
69+
6370
### Variables
6471

6572
The `variables` key can be used to provide values for user-defined variables, accessed using the [`@VAR` macro function](../concepts/macros/sqlmesh_macros.md#global-variables) in SQL model definitions, [`context.var` method](../concepts/models/python_models.md#global-variables) in Python model definitions, and [`evaluator.var` method](../concepts/macros/sqlmesh_macros.md#accessing-global-variable-values) in Python macro functions.

sqlmesh/cli/main.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ def cli(
141141
if ctx.invoked_subcommand in SKIP_LOAD_COMMANDS:
142142
load = False
143143

144+
# Unlike the other commands above, lint can scope its own load for multi-project contexts.
145+
if ctx.invoked_subcommand == "lint":
146+
load = False
147+
144148
configs = load_configs(config, Context.CONFIG_TYPE, paths, dotenv_path=dotenv)
145149
log_limit = list(configs.values())[0].log_limit
146150

@@ -1209,6 +1213,12 @@ def environments(obj: Context) -> None:
12091213
multiple=True,
12101214
help="A model to lint. Multiple models can be linted. If no models are specified, every model will be linted.",
12111215
)
1216+
@click.option(
1217+
"--use-project-index",
1218+
is_flag=True,
1219+
default=None,
1220+
help="Use the persistent project index. With --model, only the selected models and their upstream dependencies are loaded, resolved, and validated, so errors in unrelated models are not reported. Without --model, every model is still loaded and linted. Can also be enabled with linter.use_project_index.",
1221+
)
12121222
@click.option(
12131223
"--local",
12141224
is_flag=True,
@@ -1221,9 +1231,18 @@ def environments(obj: Context) -> None:
12211231
def lint(
12221232
obj: Context,
12231233
models: t.Iterator[str],
1234+
use_project_index: t.Optional[bool],
12241235
) -> None:
12251236
"""Run the linter for the target model(s)."""
1226-
obj.lint_models(models)
1237+
obj.lint_models(
1238+
models,
1239+
use_project_index=use_project_index,
1240+
)
1241+
1242+
if not obj.models:
1243+
raise click.ClickException(
1244+
f"`{obj.path}` doesn't seem to have any models... cd into the proper directory or specify the path(s) with -p."
1245+
)
12271246

12281247

12291248
@cli.group(no_args_is_help=True)

sqlmesh/core/config/linter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ class LinterConfig(BaseConfig):
1616
Args:
1717
enabled: Flag indicating whether the linter should run
1818
19+
use_project_index: Whether to use the persistent project index when linting.
20+
1921
rules: A list of error rules to be applied on model
2022
warn_rules: A list of rules to be applied on models but produce warnings instead of raising errors.
2123
ignored_rules: A list of rules to be excluded/ignored
2224
2325
"""
2426

2527
enabled: bool = False
28+
use_project_index: bool = False
2629

2730
rules: t.Set[str] = set()
2831
warn_rules: t.Set[str] = set()

0 commit comments

Comments
 (0)