datasecops-cli 0.2.5__tar.gz → 0.2.7__tar.gz
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.
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/CHANGELOG.md +16 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/PKG-INFO +1 -1
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/pyproject.toml +1 -1
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/menus/development.py +64 -23
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/bootstrap_service.py +10 -6
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/dbt_runner.py +3 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/download_service.py +39 -19
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/linting_service.py +12 -6
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/.github/workflows/publish-cli.yml +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/.gitignore +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/DEVELOPMENT.md +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/LICENSE +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/README.md +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/docs/getting-started.md +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/docs/legacy.md +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/docs/legacy_plan_of_action.md +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/docs/mcp-server.md +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/mcp-servers.json +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/setup.ps1 +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/setup.sh +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/config.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/main.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/menus/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/menus/downloads.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/menus/git_operations.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/models/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/models/git_helpers.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/models/project_config.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/git_service.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/skill_service.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/snowflake_service.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/utilities/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/utilities/display.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/utilities/file_utils.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/utilities/yaml_utils.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_mcp/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_mcp/__main__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_mcp/connection.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_mcp/server.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/tests/__init__.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/tests/test_config.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/tests/test_file_utils.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/tests/test_models.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/tests/test_version.py +0 -0
- {datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/tests/test_yaml_utils.py +0 -0
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the DataSecOps CLI are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.7] - 2026-05-12
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **Separate SQLFluff and dbt installs** — `get_sqlfluff_requirements()` now returns only `sqlfluff` and `sqlfluff-templater-dbt`; new `get_dbt_requirements()` returns only `dbt-core` and `dbt-snowflake`. The lint menu install option and the new development menu install option each handle their own packages independently
|
|
10
|
+
- **Reorganised development menu** — added `[7] parse` for `dbt parse`, added `[14] install dbt` for explicit dbt-core/dbt-snowflake installation, removed standalone retry (available in run and test submenus)
|
|
11
|
+
- **Expanded test submenu** — added unit tests (`test_type:unit`), data tests (`test_type:data`), and failed test retry options alongside all tests and specific selector
|
|
12
|
+
- **Clearer input prompts** — run, test, and lint specific-file prompts now include examples of valid input (e.g. `my_model+`, `tag:nightly`, `models/staging/stg_orders.sql`)
|
|
13
|
+
- **Bootstrap shows separate install hints** — step 7 now lists SQLFluff and dbt requirements separately with individual `uv pip install` commands
|
|
14
|
+
|
|
15
|
+
## [0.2.6] - 2026-05-11
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Include `dbt-core` and `dbt-snowflake` in framework requirements** — `get_sqlfluff_requirements()` now fetches all four active versions from the native app (`sqlfluff`, `sqlfluff-templater-dbt`, `dbt-core`, `dbt-snowflake`) and the lint menu ensures they are all installed at the correct pinned versions before linting, resolving the "Could not find adapter type snowflake!" error
|
|
20
|
+
|
|
5
21
|
## [0.2.5] - 2026-05-11
|
|
6
22
|
|
|
7
23
|
### Fixed
|
|
@@ -48,33 +48,35 @@ class DevelopmentMenu:
|
|
|
48
48
|
self.dbt.deps()
|
|
49
49
|
complete_action()
|
|
50
50
|
elif option == 7:
|
|
51
|
+
display_action_header("dbt parse")
|
|
52
|
+
self.dbt.parse()
|
|
53
|
+
complete_action()
|
|
54
|
+
elif option == 8:
|
|
51
55
|
display_action_header("dbt compile")
|
|
52
56
|
self.dbt.compile()
|
|
53
57
|
complete_action()
|
|
54
|
-
elif option ==
|
|
58
|
+
elif option == 9:
|
|
55
59
|
display_action_header("dbt snapshot")
|
|
56
60
|
self.dbt.snapshot()
|
|
57
61
|
complete_action()
|
|
58
|
-
elif option ==
|
|
62
|
+
elif option == 10:
|
|
59
63
|
display_action_header("dbt source freshness")
|
|
60
64
|
self.dbt.source_freshness()
|
|
61
65
|
complete_action()
|
|
62
|
-
elif option ==
|
|
66
|
+
elif option == 11:
|
|
63
67
|
display_action_header("dbt clean")
|
|
64
68
|
self.dbt.clean()
|
|
65
69
|
complete_action()
|
|
66
|
-
elif option ==
|
|
70
|
+
elif option == 12:
|
|
67
71
|
display_action_header("dbt debug")
|
|
68
72
|
self.dbt.debug()
|
|
69
73
|
complete_action()
|
|
70
|
-
elif option ==
|
|
74
|
+
elif option == 13:
|
|
71
75
|
display_action_header("dbt list")
|
|
72
76
|
self.dbt.list_models()
|
|
73
77
|
complete_action()
|
|
74
|
-
elif option ==
|
|
75
|
-
|
|
76
|
-
self.dbt.retry()
|
|
77
|
-
complete_action()
|
|
78
|
+
elif option == 14:
|
|
79
|
+
self._install_dbt_requirements()
|
|
78
80
|
self._menu()
|
|
79
81
|
option = get_input_number("Choose an option: ")
|
|
80
82
|
|
|
@@ -87,13 +89,14 @@ class DevelopmentMenu:
|
|
|
87
89
|
menu_option(4, "docs - Generate & serve dbt docs")
|
|
88
90
|
menu_option(5, "seed - Load seed data")
|
|
89
91
|
menu_option(6, "deps - Install dbt packages")
|
|
90
|
-
menu_option(7, "
|
|
91
|
-
menu_option(8, "
|
|
92
|
-
menu_option(9, "
|
|
93
|
-
menu_option(10, "
|
|
94
|
-
menu_option(11, "
|
|
95
|
-
menu_option(12, "
|
|
96
|
-
menu_option(13, "
|
|
92
|
+
menu_option(7, "parse - Parse dbt project")
|
|
93
|
+
menu_option(8, "compile - Compile dbt models")
|
|
94
|
+
menu_option(9, "snapshot - Run dbt snapshots")
|
|
95
|
+
menu_option(10, "freshness - Check source freshness")
|
|
96
|
+
menu_option(11, "clean - Clean dbt target")
|
|
97
|
+
menu_option(12, "debug - Debug dbt connection")
|
|
98
|
+
menu_option(13, "list - List dbt resources")
|
|
99
|
+
menu_option(14, "install dbt - Install dbt-core & dbt-snowflake from framework")
|
|
97
100
|
menu_option(0, "back - Return to main menu")
|
|
98
101
|
|
|
99
102
|
def _run_menu(self) -> None:
|
|
@@ -113,7 +116,7 @@ class DevelopmentMenu:
|
|
|
113
116
|
full_refresh = get_input_true_false("Full refresh?", "n")
|
|
114
117
|
self.dbt.run(modified_only=True, full_refresh=full_refresh)
|
|
115
118
|
elif option == 3:
|
|
116
|
-
select = get_input_string("Enter model selector: ")
|
|
119
|
+
select = get_input_string("Enter model selector (e.g. my_model, my_model+, tag:nightly, path:models/...): ")
|
|
117
120
|
if select != "0":
|
|
118
121
|
self.dbt.run(select=select)
|
|
119
122
|
elif option == 4:
|
|
@@ -129,13 +132,22 @@ class DevelopmentMenu:
|
|
|
129
132
|
clear()
|
|
130
133
|
display_action_header("dbt Test Options")
|
|
131
134
|
menu_option(1, "all tests - Run all tests")
|
|
132
|
-
menu_option(2, "
|
|
135
|
+
menu_option(2, "unit tests - Run unit tests only")
|
|
136
|
+
menu_option(3, "data tests - Run data tests only")
|
|
137
|
+
menu_option(4, "failed - Retry failed tests")
|
|
138
|
+
menu_option(5, "specific - Run specific test(s)")
|
|
133
139
|
menu_option(0, "back - Return to development menu")
|
|
134
140
|
option = get_input_number("Choose an option: ")
|
|
135
141
|
if option == 1:
|
|
136
142
|
self.dbt.test()
|
|
137
143
|
elif option == 2:
|
|
138
|
-
select
|
|
144
|
+
self.dbt.test(select="test_type:unit")
|
|
145
|
+
elif option == 3:
|
|
146
|
+
self.dbt.test(select="test_type:data")
|
|
147
|
+
elif option == 4:
|
|
148
|
+
self.dbt.retry()
|
|
149
|
+
elif option == 5:
|
|
150
|
+
select = get_input_string("Enter test selector (e.g. test_name, model_name, tag:nightly): ")
|
|
139
151
|
if select != "0":
|
|
140
152
|
self.dbt.test(select=select)
|
|
141
153
|
complete_action()
|
|
@@ -179,7 +191,7 @@ class DevelopmentMenu:
|
|
|
179
191
|
elif option == 4:
|
|
180
192
|
self.linting.lint_file(fix=True)
|
|
181
193
|
elif option == 5:
|
|
182
|
-
path = get_input_string("Enter file path: ")
|
|
194
|
+
path = get_input_string("Enter SQL file path (e.g. models/staging/stg_orders.sql): ")
|
|
183
195
|
if path != "0":
|
|
184
196
|
self.linting.lint_file(file_path=path, fix=False)
|
|
185
197
|
elif option == 6:
|
|
@@ -192,11 +204,11 @@ class DevelopmentMenu:
|
|
|
192
204
|
error_line("Download service not available")
|
|
193
205
|
return
|
|
194
206
|
|
|
195
|
-
# Show current versions
|
|
207
|
+
# Show current sqlfluff versions
|
|
196
208
|
installed = self.linting.get_installed_versions()
|
|
197
209
|
info_line("Currently installed:")
|
|
198
|
-
for pkg
|
|
199
|
-
info_line(f" {pkg}: {
|
|
210
|
+
for pkg in ("sqlfluff", "sqlfluff-templater-dbt"):
|
|
211
|
+
info_line(f" {pkg}: {installed.get(pkg) or 'not installed'}")
|
|
200
212
|
|
|
201
213
|
# Fetch required versions from framework
|
|
202
214
|
packages = self.downloads.get_sqlfluff_requirements()
|
|
@@ -210,3 +222,32 @@ class DevelopmentMenu:
|
|
|
210
222
|
|
|
211
223
|
info_line("")
|
|
212
224
|
self.linting.install_requirements(packages)
|
|
225
|
+
|
|
226
|
+
def _install_dbt_requirements(self) -> None:
|
|
227
|
+
"""Install dbt-core and dbt-snowflake at versions defined by the framework."""
|
|
228
|
+
display_action_header("Install dbt Requirements")
|
|
229
|
+
if not self.downloads:
|
|
230
|
+
error_line("Download service not available")
|
|
231
|
+
complete_action()
|
|
232
|
+
return
|
|
233
|
+
|
|
234
|
+
# Show current dbt versions
|
|
235
|
+
installed = self.linting.get_installed_versions()
|
|
236
|
+
info_line("Currently installed:")
|
|
237
|
+
for pkg in ("dbt-core", "dbt-snowflake"):
|
|
238
|
+
info_line(f" {pkg}: {installed.get(pkg) or 'not installed'}")
|
|
239
|
+
|
|
240
|
+
# Fetch required dbt versions from framework
|
|
241
|
+
packages = self.downloads.get_dbt_requirements()
|
|
242
|
+
if not packages:
|
|
243
|
+
complete_action()
|
|
244
|
+
return
|
|
245
|
+
|
|
246
|
+
info_line("")
|
|
247
|
+
info_line("Framework requires:")
|
|
248
|
+
for pkg in packages:
|
|
249
|
+
info_line(f" {pkg}")
|
|
250
|
+
|
|
251
|
+
info_line("")
|
|
252
|
+
self.linting.install_requirements(packages)
|
|
253
|
+
complete_action()
|
{datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/bootstrap_service.py
RENAMED
|
@@ -109,14 +109,18 @@ class BootstrapService:
|
|
|
109
109
|
info_line(" (dbt deps failed - run manually after fixing packages.yml)")
|
|
110
110
|
steps_passed += 1
|
|
111
111
|
|
|
112
|
-
# Step 7:
|
|
112
|
+
# Step 7: Check SQLFluff & dbt version requirements
|
|
113
113
|
info_line("")
|
|
114
114
|
step_num = 7 if run_deps else 6
|
|
115
|
-
info_line(f"[{step_num}] Checking SQLFluff version requirements...")
|
|
116
|
-
|
|
117
|
-
if
|
|
118
|
-
info_line(f"
|
|
119
|
-
info_line(" (install with: uv pip install " + " ".join(
|
|
115
|
+
info_line(f"[{step_num}] Checking SQLFluff & dbt version requirements...")
|
|
116
|
+
sqlfluff_requirements = self.download_service.get_sqlfluff_requirements()
|
|
117
|
+
if sqlfluff_requirements:
|
|
118
|
+
info_line(f" SQLFluff: {', '.join(sqlfluff_requirements)}")
|
|
119
|
+
info_line(" (install with: uv pip install " + " ".join(sqlfluff_requirements) + ")")
|
|
120
|
+
dbt_requirements = self.download_service.get_dbt_requirements()
|
|
121
|
+
if dbt_requirements:
|
|
122
|
+
info_line(f" dbt: {', '.join(dbt_requirements)}")
|
|
123
|
+
info_line(" (install with: uv pip install " + " ".join(dbt_requirements) + ")")
|
|
120
124
|
steps_passed += 1
|
|
121
125
|
|
|
122
126
|
# Step 8: Install Cortex Code skills
|
|
@@ -117,6 +117,9 @@ class DbtRunner:
|
|
|
117
117
|
self._copy_manifest()
|
|
118
118
|
return result
|
|
119
119
|
|
|
120
|
+
def parse(self) -> subprocess.CompletedProcess:
|
|
121
|
+
return self._run_command("parse")
|
|
122
|
+
|
|
120
123
|
def run_operation(self, macro: str, args_str: str = None) -> subprocess.CompletedProcess:
|
|
121
124
|
cmd_args = [f"--target={self.target}"]
|
|
122
125
|
if args_str:
|
{datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/download_service.py
RENAMED
|
@@ -168,32 +168,52 @@ class DownloadService:
|
|
|
168
168
|
success_line(f"SQLFluff config written to {dest}")
|
|
169
169
|
return True
|
|
170
170
|
|
|
171
|
-
def
|
|
172
|
-
"""Fetch active
|
|
173
|
-
|
|
171
|
+
def _fetch_framework_versions(self) -> dict[str, str]:
|
|
172
|
+
"""Fetch all active package versions from the framework's DBT_VERSIONS config.
|
|
173
|
+
|
|
174
|
+
Returns a dict mapping pip package name to pinned spec, e.g. {"dbt-core": "dbt-core==1.9.0", ...}.
|
|
175
|
+
"""
|
|
174
176
|
raw = self.sf.get_framework_config("DBT_VERSIONS")
|
|
175
177
|
if not raw:
|
|
176
178
|
error_line("No DBT_VERSIONS configuration found in native app")
|
|
177
|
-
return
|
|
179
|
+
return {}
|
|
178
180
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
break
|
|
181
|
+
version_keys = {
|
|
182
|
+
"sqlfluff_versions": "sqlfluff",
|
|
183
|
+
"sqlfluff_templater_versions": "sqlfluff-templater-dbt",
|
|
184
|
+
"dbt_core_versions": "dbt-core",
|
|
185
|
+
"dbt_snowflake_versions": "dbt-snowflake",
|
|
186
|
+
}
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
for
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
result: dict[str, str] = {}
|
|
189
|
+
for config_key, pkg_name in version_keys.items():
|
|
190
|
+
for entry in raw.get(config_key, []):
|
|
191
|
+
if entry.get("active"):
|
|
192
|
+
result[pkg_name] = f"{pkg_name}=={entry['version']}"
|
|
193
|
+
break
|
|
192
194
|
|
|
193
|
-
if not
|
|
194
|
-
error_line("No active
|
|
195
|
+
if not result:
|
|
196
|
+
error_line("No active versions found in framework configuration")
|
|
195
197
|
|
|
196
|
-
return
|
|
198
|
+
return result
|
|
199
|
+
|
|
200
|
+
def get_sqlfluff_requirements(self) -> list[str]:
|
|
201
|
+
"""Fetch active sqlfluff and sqlfluff-templater-dbt versions from the framework."""
|
|
202
|
+
info_line("Fetching SQLFluff requirements from framework...")
|
|
203
|
+
versions = self._fetch_framework_versions()
|
|
204
|
+
sqlfluff_packages = [versions[k] for k in ("sqlfluff", "sqlfluff-templater-dbt") if k in versions]
|
|
205
|
+
if not sqlfluff_packages:
|
|
206
|
+
error_line("No active SQLFluff versions found in framework configuration")
|
|
207
|
+
return sqlfluff_packages
|
|
208
|
+
|
|
209
|
+
def get_dbt_requirements(self) -> list[str]:
|
|
210
|
+
"""Fetch active dbt-core and dbt-snowflake versions from the framework."""
|
|
211
|
+
info_line("Fetching dbt requirements from framework...")
|
|
212
|
+
versions = self._fetch_framework_versions()
|
|
213
|
+
dbt_packages = [versions[k] for k in ("dbt-core", "dbt-snowflake") if k in versions]
|
|
214
|
+
if not dbt_packages:
|
|
215
|
+
error_line("No active dbt versions found in framework configuration")
|
|
216
|
+
return dbt_packages
|
|
197
217
|
|
|
198
218
|
def download_pipelines(self, platform: str = "github") -> bool:
|
|
199
219
|
info_line(f"Downloading {platform} pipeline configurations...")
|
{datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/linting_service.py
RENAMED
|
@@ -10,10 +10,16 @@ class LintingService:
|
|
|
10
10
|
def __init__(self, project_dir: Path):
|
|
11
11
|
self.project_dir = project_dir
|
|
12
12
|
|
|
13
|
-
def get_installed_versions(self) -> dict[str, str]:
|
|
14
|
-
"""Get currently installed versions of
|
|
13
|
+
def get_installed_versions(self, packages: list[str] = None) -> dict[str, str]:
|
|
14
|
+
"""Get currently installed versions of the specified packages.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
packages: Package names to check. Defaults to sqlfluff, sqlfluff-templater-dbt, dbt-core, dbt-snowflake.
|
|
18
|
+
"""
|
|
19
|
+
if packages is None:
|
|
20
|
+
packages = ["sqlfluff", "sqlfluff-templater-dbt", "dbt-core", "dbt-snowflake"]
|
|
15
21
|
versions = {}
|
|
16
|
-
for package in
|
|
22
|
+
for package in packages:
|
|
17
23
|
result = subprocess.run(
|
|
18
24
|
["uv", "pip", "show", package],
|
|
19
25
|
capture_output=True, text=True
|
|
@@ -28,7 +34,7 @@ class LintingService:
|
|
|
28
34
|
return versions
|
|
29
35
|
|
|
30
36
|
def install_requirements(self, packages: list[str]) -> bool:
|
|
31
|
-
"""Install
|
|
37
|
+
"""Install packages at specified versions via uv pip."""
|
|
32
38
|
if not packages:
|
|
33
39
|
warning_line("No packages to install")
|
|
34
40
|
return False
|
|
@@ -37,7 +43,7 @@ class LintingService:
|
|
|
37
43
|
info_line(f"Installing: {', '.join(packages)}")
|
|
38
44
|
result = subprocess.run(cmd, capture_output=False)
|
|
39
45
|
if result.returncode == 0:
|
|
40
|
-
success_line("
|
|
46
|
+
success_line("Packages installed successfully")
|
|
41
47
|
return True
|
|
42
48
|
else:
|
|
43
49
|
error_line(f"uv pip install failed with exit code {result.returncode}")
|
|
@@ -75,7 +81,7 @@ class LintingService:
|
|
|
75
81
|
return True
|
|
76
82
|
return self.install_requirements(to_install)
|
|
77
83
|
|
|
78
|
-
# No pinned versions — just ensure packages are present
|
|
84
|
+
# No pinned versions — just ensure sqlfluff packages are present
|
|
79
85
|
missing = [pkg for pkg in ["sqlfluff", "sqlfluff-templater-dbt"] if not installed.get(pkg)]
|
|
80
86
|
if not missing:
|
|
81
87
|
return True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datasecops_cli-0.2.5 → datasecops_cli-0.2.7}/src/datasecops_cli/services/snowflake_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|