recce-nightly 1.3.0.20250507__py3-none-any.whl → 1.4.0.20250515__py3-none-any.whl
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.
Potentially problematic release.
This version of recce-nightly might be problematic. Click here for more details.
- recce/VERSION +1 -1
- recce/__init__.py +22 -22
- recce/adapter/base.py +11 -14
- recce/adapter/dbt_adapter/__init__.py +355 -316
- recce/adapter/dbt_adapter/dbt_version.py +3 -0
- recce/adapter/sqlmesh_adapter.py +24 -35
- recce/apis/check_api.py +39 -28
- recce/apis/check_func.py +33 -27
- recce/apis/run_api.py +25 -19
- recce/apis/run_func.py +29 -23
- recce/artifact.py +44 -49
- recce/cli.py +484 -285
- recce/config.py +42 -33
- recce/core.py +52 -44
- recce/data/404.html +1 -1
- recce/data/_next/static/chunks/{368-7587b306577df275.js → 778-aef312bffb4c0312.js} +15 -15
- recce/data/_next/static/chunks/8d700b6a.ed11a130057c7a47.js +1 -0
- recce/data/_next/static/chunks/app/layout-c713a2829d3279e4.js +1 -0
- recce/data/_next/static/chunks/app/page-7086764277331fcb.js +1 -0
- recce/data/_next/static/chunks/{cd9f8d63-cf0d5a7b0f7a92e8.js → cd9f8d63-e020f408095ed77c.js} +3 -3
- recce/data/_next/static/chunks/webpack-b787cb1a4f2293de.js +1 -0
- recce/data/_next/static/css/88b8abc134cfd59a.css +3 -0
- recce/data/index.html +2 -2
- recce/data/index.txt +2 -2
- recce/diff.py +6 -12
- recce/event/__init__.py +74 -72
- recce/event/collector.py +27 -20
- recce/event/track.py +39 -27
- recce/exceptions.py +1 -1
- recce/git.py +7 -7
- recce/github.py +57 -53
- recce/models/__init__.py +1 -1
- recce/models/check.py +6 -7
- recce/models/run.py +1 -0
- recce/models/types.py +27 -27
- recce/pull_request.py +26 -24
- recce/run.py +148 -111
- recce/server.py +103 -89
- recce/state.py +209 -177
- recce/summary.py +168 -143
- recce/tasks/__init__.py +3 -3
- recce/tasks/core.py +11 -13
- recce/tasks/dataframe.py +19 -17
- recce/tasks/histogram.py +69 -34
- recce/tasks/lineage.py +2 -2
- recce/tasks/profile.py +147 -86
- recce/tasks/query.py +139 -87
- recce/tasks/rowcount.py +33 -30
- recce/tasks/schema.py +14 -14
- recce/tasks/top_k.py +35 -35
- recce/tasks/valuediff.py +216 -152
- recce/util/breaking.py +77 -84
- recce/util/cll.py +55 -51
- recce/util/io.py +19 -17
- recce/util/logger.py +1 -1
- recce/util/recce_cloud.py +70 -72
- recce/util/singleton.py +4 -4
- recce/yaml/__init__.py +7 -10
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250515.dist-info}/METADATA +5 -2
- recce_nightly-1.4.0.20250515.dist-info/RECORD +143 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250515.dist-info}/WHEEL +1 -1
- tests/adapter/dbt_adapter/conftest.py +1 -0
- tests/adapter/dbt_adapter/dbt_test_helper.py +28 -18
- tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -15
- tests/adapter/dbt_adapter/test_dbt_cll.py +39 -32
- tests/adapter/dbt_adapter/test_selector.py +22 -21
- tests/tasks/test_histogram.py +58 -66
- tests/tasks/test_lineage.py +36 -23
- tests/tasks/test_preset_checks.py +45 -31
- tests/tasks/test_profile.py +340 -15
- tests/tasks/test_query.py +40 -40
- tests/tasks/test_row_count.py +65 -46
- tests/tasks/test_schema.py +65 -42
- tests/tasks/test_top_k.py +22 -18
- tests/tasks/test_valuediff.py +43 -32
- tests/test_cli.py +71 -58
- tests/test_config.py +7 -9
- tests/test_core.py +5 -3
- tests/test_dbt.py +7 -7
- tests/test_pull_request.py +1 -1
- tests/test_server.py +19 -13
- tests/test_state.py +40 -27
- tests/test_summary.py +18 -14
- recce/data/_next/static/chunks/8d700b6a-f0b1f6b9e0d97ce2.js +0 -1
- recce/data/_next/static/chunks/app/layout-9102e22cb73f74d6.js +0 -1
- recce/data/_next/static/chunks/app/page-92f13c8fad9fae3d.js +0 -1
- recce/data/_next/static/chunks/webpack-567d72f0bc0820d5.js +0 -1
- recce_nightly-1.3.0.20250507.dist-info/RECORD +0 -142
- /recce/data/_next/static/{K5iKlCYhdcpq8Ea6ck9J_ → q0Xsc9Sd6PDuo1lshYpLu}/_buildManifest.js +0 -0
- /recce/data/_next/static/{K5iKlCYhdcpq8Ea6ck9J_ → q0Xsc9Sd6PDuo1lshYpLu}/_ssgManifest.js +0 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250515.dist-info}/entry_points.txt +0 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250515.dist-info}/licenses/LICENSE +0 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250515.dist-info}/top_level.txt +0 -0
recce/run.py
CHANGED
|
@@ -9,7 +9,11 @@ from rich import box
|
|
|
9
9
|
from rich.console import Console
|
|
10
10
|
from rich.table import Table
|
|
11
11
|
|
|
12
|
-
from recce.apis.check_func import
|
|
12
|
+
from recce.apis.check_func import (
|
|
13
|
+
create_check_from_run,
|
|
14
|
+
create_check_without_run,
|
|
15
|
+
purge_preset_checks,
|
|
16
|
+
)
|
|
13
17
|
from recce.apis.run_func import submit_run
|
|
14
18
|
from recce.config import RecceConfig
|
|
15
19
|
from recce.core import default_context
|
|
@@ -19,13 +23,13 @@ from recce.summary import generate_markdown_summary
|
|
|
19
23
|
|
|
20
24
|
def check_github_ci_env(**kwargs):
|
|
21
25
|
"""Check if the environment is GitHub CI"""
|
|
22
|
-
if
|
|
26
|
+
if "GITHUB_ACTIONS" not in os.environ:
|
|
23
27
|
return False, None
|
|
24
28
|
|
|
25
29
|
# Get the PR number
|
|
26
|
-
github_server_url = os.environ.get(
|
|
27
|
-
github_repository = os.environ.get(
|
|
28
|
-
github_ref_name = os.environ.get(
|
|
30
|
+
github_server_url = os.environ.get("GITHUB_SERVER_URL", "https://github.com")
|
|
31
|
+
github_repository = os.environ.get("GITHUB_REPOSITORY", "")
|
|
32
|
+
github_ref_name = os.environ.get("GITHUB_REF_NAME", "")
|
|
29
33
|
github_pull_request_url = f"{github_server_url}/{github_repository}/pull/{github_ref_name}"
|
|
30
34
|
|
|
31
35
|
return True, github_pull_request_url
|
|
@@ -33,21 +37,22 @@ def check_github_ci_env(**kwargs):
|
|
|
33
37
|
|
|
34
38
|
def load_preset_checks(checks: list):
|
|
35
39
|
console = Console()
|
|
36
|
-
table = Table(title=
|
|
37
|
-
table.add_column(
|
|
38
|
-
table.add_column(
|
|
39
|
-
table.add_column(
|
|
40
|
+
table = Table(title="Recce Preset Checks", box=box.HORIZONTALS, title_style="bold dark_orange3")
|
|
41
|
+
table.add_column("Name")
|
|
42
|
+
table.add_column("Type")
|
|
43
|
+
table.add_column("Description")
|
|
40
44
|
for check in checks:
|
|
41
45
|
is_check = False
|
|
42
|
-
name = check.get(
|
|
43
|
-
description = check.get(
|
|
44
|
-
check_type = check.get(
|
|
45
|
-
check_params = check.get(
|
|
46
|
-
check_options = check.get(
|
|
47
|
-
|
|
48
|
-
create_check_without_run(
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
name = check.get("name")
|
|
47
|
+
description = check.get("description", "")
|
|
48
|
+
check_type = check.get("type")
|
|
49
|
+
check_params = check.get("params", {})
|
|
50
|
+
check_options = check.get("view_options", {})
|
|
51
|
+
|
|
52
|
+
create_check_without_run(
|
|
53
|
+
name, description, check_type, check_params, check_options, is_preset=True, is_checked=is_check
|
|
54
|
+
)
|
|
55
|
+
table.add_row(name, check_type.replace("_", " ").title(), description.strip())
|
|
51
56
|
console.print(table)
|
|
52
57
|
|
|
53
58
|
|
|
@@ -55,28 +60,28 @@ def schema_diff_should_be_approved(check_params: dict) -> bool:
|
|
|
55
60
|
try:
|
|
56
61
|
context = default_context()
|
|
57
62
|
|
|
58
|
-
if
|
|
63
|
+
if "node_id" in check_params:
|
|
59
64
|
# If the node_id is provided, then use it
|
|
60
|
-
if isinstance(check_params[
|
|
61
|
-
selected_node_ids = [check_params[
|
|
65
|
+
if isinstance(check_params["node_id"], str):
|
|
66
|
+
selected_node_ids = [check_params["node_id"]]
|
|
62
67
|
else:
|
|
63
|
-
selected_node_ids = check_params.get(
|
|
68
|
+
selected_node_ids = check_params.get("node_id", [])
|
|
64
69
|
else:
|
|
65
70
|
# Otherwise, select the nodes based on the select/exclude/packages/view_mode
|
|
66
71
|
selected_node_ids = context.adapter.select_nodes(
|
|
67
|
-
select=check_params.get(
|
|
68
|
-
exclude=check_params.get(
|
|
69
|
-
packages=check_params.get(
|
|
70
|
-
view_mode=check_params.get(
|
|
72
|
+
select=check_params.get("select"),
|
|
73
|
+
exclude=check_params.get("exclude"),
|
|
74
|
+
packages=check_params.get("packages"),
|
|
75
|
+
view_mode=check_params.get("view_mode"),
|
|
71
76
|
)
|
|
72
77
|
|
|
73
|
-
selected_node_ids = [node for node in selected_node_ids if not node.startswith(
|
|
78
|
+
selected_node_ids = [node for node in selected_node_ids if not node.startswith("test.")]
|
|
74
79
|
|
|
75
80
|
def _get_selected_node_columns_from_lineage(lineage, node_ids: list[str]):
|
|
76
81
|
nodes = {}
|
|
77
|
-
for node_id, node in lineage.get(
|
|
82
|
+
for node_id, node in lineage.get("nodes", {}).items():
|
|
78
83
|
if node_id in node_ids:
|
|
79
|
-
nodes[node_id] = node.get(
|
|
84
|
+
nodes[node_id] = node.get("columns", {})
|
|
80
85
|
return nodes
|
|
81
86
|
|
|
82
87
|
base_nodes = _get_selected_node_columns_from_lineage(context.get_lineage(base=True), selected_node_ids)
|
|
@@ -100,7 +105,7 @@ def run_should_be_approved(run):
|
|
|
100
105
|
return False
|
|
101
106
|
# If the row count are exactly the same, then the check should be approved
|
|
102
107
|
for column, row_count_result in run.result.items():
|
|
103
|
-
if row_count_result[
|
|
108
|
+
if row_count_result["base"] != row_count_result["curr"]:
|
|
104
109
|
return False
|
|
105
110
|
return True
|
|
106
111
|
return False
|
|
@@ -113,12 +118,12 @@ async def execute_preset_checks(preset_checks: list) -> (int, List[dict]):
|
|
|
113
118
|
console = Console()
|
|
114
119
|
rc = 0
|
|
115
120
|
failed_checks = []
|
|
116
|
-
table = Table(title=
|
|
117
|
-
table.add_column(
|
|
118
|
-
table.add_column(
|
|
119
|
-
table.add_column(
|
|
120
|
-
table.add_column(
|
|
121
|
-
table.add_column(
|
|
121
|
+
table = Table(title="Recce Preset Checks", box=box.HORIZONTALS, title_style="bold dark_orange3")
|
|
122
|
+
table.add_column("Status")
|
|
123
|
+
table.add_column("Name")
|
|
124
|
+
table.add_column("Type")
|
|
125
|
+
table.add_column("Execution Time")
|
|
126
|
+
table.add_column("Failed Reason")
|
|
122
127
|
|
|
123
128
|
# Purge the existing preset checks before running the new ones
|
|
124
129
|
purge_preset_checks()
|
|
@@ -126,11 +131,11 @@ async def execute_preset_checks(preset_checks: list) -> (int, List[dict]):
|
|
|
126
131
|
# Execute the preset checks
|
|
127
132
|
for check in preset_checks:
|
|
128
133
|
run = None
|
|
129
|
-
check_name = check.get(
|
|
130
|
-
check_type = check.get(
|
|
131
|
-
check_description = check.get(
|
|
132
|
-
check_params = check.get(
|
|
133
|
-
check_options = check.get(
|
|
134
|
+
check_name = check.get("name")
|
|
135
|
+
check_type = check.get("type")
|
|
136
|
+
check_description = check.get("description", "")
|
|
137
|
+
check_params = check.get("params") if check.get("params") else {}
|
|
138
|
+
check_options = check.get("view_options", {})
|
|
134
139
|
|
|
135
140
|
try:
|
|
136
141
|
# verify the check
|
|
@@ -138,41 +143,58 @@ async def execute_preset_checks(preset_checks: list) -> (int, List[dict]):
|
|
|
138
143
|
raise ValueError(f"Invalid check type: {check_type}")
|
|
139
144
|
|
|
140
145
|
start = time.time()
|
|
141
|
-
if check_type in [
|
|
142
|
-
is_check = schema_diff_should_be_approved(check_params) if check_type ==
|
|
143
|
-
create_check_without_run(
|
|
144
|
-
|
|
146
|
+
if check_type in ["schema_diff", "lineage_diff"]:
|
|
147
|
+
is_check = schema_diff_should_be_approved(check_params) if check_type == "schema_diff" else False
|
|
148
|
+
create_check_without_run(
|
|
149
|
+
check_name,
|
|
150
|
+
check_description,
|
|
151
|
+
check_type,
|
|
152
|
+
check_params,
|
|
153
|
+
check_options,
|
|
154
|
+
is_preset=True,
|
|
155
|
+
is_checked=is_check,
|
|
156
|
+
)
|
|
145
157
|
else:
|
|
146
158
|
run, future = submit_run(check_type, params=check_params)
|
|
147
159
|
await future
|
|
148
160
|
is_check = run_should_be_approved(run)
|
|
149
|
-
create_check_from_run(
|
|
150
|
-
|
|
161
|
+
create_check_from_run(
|
|
162
|
+
run.run_id, check_name, check_description, check_options, is_preset=True, is_checked=is_check
|
|
163
|
+
)
|
|
151
164
|
|
|
152
165
|
end = time.time()
|
|
153
|
-
table.add_row(
|
|
154
|
-
|
|
166
|
+
table.add_row(
|
|
167
|
+
"[[green]Success[/green]]",
|
|
168
|
+
check_name,
|
|
169
|
+
check_type.replace("_", " ").title(),
|
|
170
|
+
f"{end - start:.2f} seconds",
|
|
171
|
+
"N/A",
|
|
172
|
+
)
|
|
155
173
|
except Exception as e:
|
|
156
174
|
rc = 1
|
|
157
175
|
if run is None:
|
|
158
|
-
table.add_row(
|
|
159
|
-
failed_checks.append(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
176
|
+
table.add_row("[[red]Error[/red]]", check_name, check_type.replace("_", " ").title(), "N/A", str(e))
|
|
177
|
+
failed_checks.append(
|
|
178
|
+
{
|
|
179
|
+
"check_name": check_name,
|
|
180
|
+
"check_type": check_type,
|
|
181
|
+
"check_description": check_description,
|
|
182
|
+
"failed_type": "error",
|
|
183
|
+
"failed_reason": str(e),
|
|
184
|
+
}
|
|
185
|
+
)
|
|
166
186
|
else:
|
|
167
187
|
create_check_from_run(run.run_id, check_name, check_description, check_options, is_preset=True)
|
|
168
|
-
table.add_row(
|
|
169
|
-
failed_checks.append(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
188
|
+
table.add_row("[[red]Failed[/red]]", check_name, check_type.replace("_", " ").title(), "N/A", run.error)
|
|
189
|
+
failed_checks.append(
|
|
190
|
+
{
|
|
191
|
+
"check_name": check_name,
|
|
192
|
+
"check_type": check_type,
|
|
193
|
+
"check_description": "N/A",
|
|
194
|
+
"failed_type": "failed",
|
|
195
|
+
"failed_reason": run.error,
|
|
196
|
+
}
|
|
197
|
+
)
|
|
176
198
|
|
|
177
199
|
console.print(table)
|
|
178
200
|
return rc, failed_checks
|
|
@@ -185,12 +207,12 @@ async def execute_state_checks(checks: list) -> (int, List[dict]):
|
|
|
185
207
|
console = Console()
|
|
186
208
|
rc = 0
|
|
187
209
|
failed_checks = []
|
|
188
|
-
table = Table(title=
|
|
189
|
-
table.add_column(
|
|
190
|
-
table.add_column(
|
|
191
|
-
table.add_column(
|
|
192
|
-
table.add_column(
|
|
193
|
-
table.add_column(
|
|
210
|
+
table = Table(title="Recce Checks", box=box.HORIZONTALS, title_style="bold dark_orange3")
|
|
211
|
+
table.add_column("Status")
|
|
212
|
+
table.add_column("Name")
|
|
213
|
+
table.add_column("Type")
|
|
214
|
+
table.add_column("Execution Time")
|
|
215
|
+
table.add_column("Failed Reason")
|
|
194
216
|
|
|
195
217
|
# Execute loaded checks
|
|
196
218
|
for check in checks:
|
|
@@ -210,33 +232,42 @@ async def execute_state_checks(checks: list) -> (int, List[dict]):
|
|
|
210
232
|
raise ValueError(f"Invalid check type: {check_type}")
|
|
211
233
|
|
|
212
234
|
start = time.time()
|
|
213
|
-
if check_type not in [
|
|
235
|
+
if check_type not in ["schema_diff"]:
|
|
214
236
|
run, future = submit_run(check_type, params=check_params, check_id=check_id)
|
|
215
237
|
await future
|
|
216
238
|
|
|
217
239
|
end = time.time()
|
|
218
|
-
table.add_row(
|
|
219
|
-
|
|
240
|
+
table.add_row(
|
|
241
|
+
"[[green]Success[/green]]",
|
|
242
|
+
check_name,
|
|
243
|
+
check_type.replace("_", " ").title(),
|
|
244
|
+
f"{end - start:.2f} seconds",
|
|
245
|
+
"N/A",
|
|
246
|
+
)
|
|
220
247
|
except Exception as e:
|
|
221
248
|
rc = 1
|
|
222
249
|
if run is None:
|
|
223
|
-
table.add_row(
|
|
224
|
-
failed_checks.append(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
250
|
+
table.add_row("[[red]Error[/red]]", check_name, check_type.replace("_", " ").title(), "N/A", str(e))
|
|
251
|
+
failed_checks.append(
|
|
252
|
+
{
|
|
253
|
+
"check_name": check_name,
|
|
254
|
+
"check_type": check_type,
|
|
255
|
+
"check_description": check_description,
|
|
256
|
+
"failed_type": "error",
|
|
257
|
+
"failed_reason": str(e),
|
|
258
|
+
}
|
|
259
|
+
)
|
|
231
260
|
else:
|
|
232
|
-
table.add_row(
|
|
233
|
-
failed_checks.append(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
261
|
+
table.add_row("[[red]Failed[/red]]", check_name, check_type.replace("_", " ").title(), "N/A", run.error)
|
|
262
|
+
failed_checks.append(
|
|
263
|
+
{
|
|
264
|
+
"check_name": check_name,
|
|
265
|
+
"check_type": check_type,
|
|
266
|
+
"check_description": "N/A",
|
|
267
|
+
"failed_type": "failed",
|
|
268
|
+
"failed_reason": run.error,
|
|
269
|
+
}
|
|
270
|
+
)
|
|
240
271
|
|
|
241
272
|
console.print(table)
|
|
242
273
|
return rc, failed_checks
|
|
@@ -244,24 +275,27 @@ async def execute_state_checks(checks: list) -> (int, List[dict]):
|
|
|
244
275
|
|
|
245
276
|
def process_failed_checks(failed_checks: List[dict], error_log=None):
|
|
246
277
|
from py_markdown_table.markdown_table import markdown_table
|
|
278
|
+
|
|
247
279
|
failed_check_table = []
|
|
248
280
|
for check in failed_checks:
|
|
249
|
-
name = check.get(
|
|
250
|
-
check_type = check.get(
|
|
251
|
-
failed_type = check.get(
|
|
252
|
-
failed_reason = check.get(
|
|
253
|
-
failed_check_table.append(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
281
|
+
name = check.get("check_name")
|
|
282
|
+
check_type = check.get("check_type")
|
|
283
|
+
failed_type = check.get("failed_type")
|
|
284
|
+
failed_reason = check.get("failed_reason")
|
|
285
|
+
failed_check_table.append(
|
|
286
|
+
{
|
|
287
|
+
"Name": name,
|
|
288
|
+
"Type": check_type,
|
|
289
|
+
"Kind of Failed": failed_type,
|
|
290
|
+
"Failed Reason": failed_reason.replace("\n", " "),
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
content = "# Recce Runc Failed Checks\n"
|
|
295
|
+
content += markdown_table(failed_check_table).set_params(quote=False, row_sep="markdown").get_markdown()
|
|
262
296
|
|
|
263
297
|
if error_log:
|
|
264
|
-
with open(error_log,
|
|
298
|
+
with open(error_log, "w") as f:
|
|
265
299
|
f.write(content)
|
|
266
300
|
print(f"The failed checks are stored at '{error_log}'")
|
|
267
301
|
else:
|
|
@@ -271,26 +305,28 @@ def process_failed_checks(failed_checks: List[dict], error_log=None):
|
|
|
271
305
|
async def cli_run(output_state_file: str, **kwargs):
|
|
272
306
|
"""The main function of 'recce run' command. It will execute the default runs and store the state."""
|
|
273
307
|
console = Console()
|
|
274
|
-
error_log = kwargs.get(
|
|
275
|
-
if kwargs.get(
|
|
308
|
+
error_log = kwargs.get("error_log")
|
|
309
|
+
if kwargs.get("sqlmesh", False):
|
|
276
310
|
console.print("[[red]Error[/red]] SQLMesh adapter is not supported.")
|
|
277
311
|
sys.exit(1)
|
|
278
312
|
|
|
279
313
|
from recce.core import load_context
|
|
314
|
+
|
|
280
315
|
ctx = load_context(**kwargs)
|
|
281
316
|
|
|
282
|
-
is_skip_query = kwargs.get(
|
|
317
|
+
is_skip_query = kwargs.get("skip_query", False)
|
|
283
318
|
|
|
284
319
|
# Prepare the artifact by collecting the lineage
|
|
285
320
|
console.rule("DBT Artifacts")
|
|
286
321
|
from recce.adapter.dbt_adapter import DbtAdapter
|
|
322
|
+
|
|
287
323
|
dbt_adaptor: DbtAdapter = ctx.adapter
|
|
288
324
|
dbt_adaptor.print_lineage_info()
|
|
289
325
|
|
|
290
326
|
# Execute the preset checks
|
|
291
327
|
rc = 0
|
|
292
328
|
if ctx.state_loader.state is None:
|
|
293
|
-
preset_checks = RecceConfig().get(
|
|
329
|
+
preset_checks = RecceConfig().get("checks")
|
|
294
330
|
if is_skip_query or preset_checks is None or len(preset_checks) == 0:
|
|
295
331
|
# Skip the preset checks
|
|
296
332
|
pass
|
|
@@ -313,7 +349,8 @@ async def cli_run(output_state_file: str, **kwargs):
|
|
|
313
349
|
process_failed_checks(failed_checks, error_log)
|
|
314
350
|
|
|
315
351
|
from recce.event import log_load_state
|
|
316
|
-
|
|
352
|
+
|
|
353
|
+
log_load_state(command="run")
|
|
317
354
|
|
|
318
355
|
# Export the state
|
|
319
356
|
console.rule("Export state")
|
|
@@ -321,12 +358,12 @@ async def cli_run(output_state_file: str, **kwargs):
|
|
|
321
358
|
msg = ctx.state_loader.export(ctx.export_state())
|
|
322
359
|
console.print(msg)
|
|
323
360
|
|
|
324
|
-
summary_path = kwargs.get(
|
|
361
|
+
summary_path = kwargs.get("summary")
|
|
325
362
|
if summary_path:
|
|
326
363
|
dirs = os.path.dirname(summary_path)
|
|
327
364
|
if dirs:
|
|
328
365
|
os.makedirs(dirs, exist_ok=True)
|
|
329
|
-
with open(summary_path,
|
|
366
|
+
with open(summary_path, "w") as f:
|
|
330
367
|
f.write(generate_markdown_summary(ctx))
|
|
331
368
|
console.print(f"The summary is stored at '{summary_path}'")
|
|
332
369
|
|