snowflake-cli 3.10.0__py3-none-any.whl → 3.11.0__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.
Files changed (41) hide show
  1. snowflake/cli/__about__.py +1 -1
  2. snowflake/cli/_app/auth/__init__.py +13 -0
  3. snowflake/cli/_app/auth/errors.py +28 -0
  4. snowflake/cli/_app/auth/oidc_providers.py +393 -0
  5. snowflake/cli/_app/commands_registration/builtin_plugins.py +2 -2
  6. snowflake/cli/_app/constants.py +10 -0
  7. snowflake/cli/_app/snow_connector.py +35 -0
  8. snowflake/cli/_plugins/auth/__init__.py +4 -2
  9. snowflake/cli/_plugins/auth/keypair/commands.py +2 -0
  10. snowflake/cli/_plugins/auth/oidc/__init__.py +13 -0
  11. snowflake/cli/_plugins/auth/oidc/commands.py +47 -0
  12. snowflake/cli/_plugins/auth/oidc/manager.py +66 -0
  13. snowflake/cli/_plugins/auth/oidc/plugin_spec.py +30 -0
  14. snowflake/cli/_plugins/connection/commands.py +37 -3
  15. snowflake/cli/_plugins/dbt/manager.py +7 -7
  16. snowflake/cli/_plugins/{project → dcm}/commands.py +113 -122
  17. snowflake/cli/_plugins/{project/project_entity_model.py → dcm/dcm_project_entity_model.py} +5 -5
  18. snowflake/cli/_plugins/dcm/manager.py +96 -0
  19. snowflake/cli/_plugins/{project → dcm}/plugin_spec.py +1 -1
  20. snowflake/cli/_plugins/notebook/notebook_entity.py +2 -0
  21. snowflake/cli/_plugins/notebook/notebook_entity_model.py +8 -1
  22. snowflake/cli/_plugins/object/command_aliases.py +16 -1
  23. snowflake/cli/_plugins/object/commands.py +27 -1
  24. snowflake/cli/_plugins/object/manager.py +12 -1
  25. snowflake/cli/_plugins/snowpark/commands.py +8 -1
  26. snowflake/cli/api/commands/decorators.py +7 -0
  27. snowflake/cli/api/commands/flags.py +26 -0
  28. snowflake/cli/api/config.py +24 -0
  29. snowflake/cli/api/connections.py +1 -0
  30. snowflake/cli/api/constants.py +2 -2
  31. snowflake/cli/api/project/schemas/entities/entities.py +6 -6
  32. snowflake/cli/api/rest_api.py +1 -0
  33. snowflake/cli/api/stage_path.py +4 -0
  34. snowflake/cli/api/utils/dict_utils.py +42 -1
  35. {snowflake_cli-3.10.0.dist-info → snowflake_cli-3.11.0.dist-info}/METADATA +13 -39
  36. {snowflake_cli-3.10.0.dist-info → snowflake_cli-3.11.0.dist-info}/RECORD +40 -33
  37. snowflake/cli/_plugins/project/manager.py +0 -134
  38. /snowflake/cli/_plugins/{project → dcm}/__init__.py +0 -0
  39. {snowflake_cli-3.10.0.dist-info → snowflake_cli-3.11.0.dist-info}/WHEEL +0 -0
  40. {snowflake_cli-3.10.0.dist-info → snowflake_cli-3.11.0.dist-info}/entry_points.txt +0 -0
  41. {snowflake_cli-3.10.0.dist-info → snowflake_cli-3.11.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2024 Snowflake Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import logging
16
+ from typing import TypeAlias
17
+
18
+ from snowflake.cli._app.auth.errors import OidcProviderError
19
+ from snowflake.cli._app.auth.oidc_providers import (
20
+ OidcProviderType,
21
+ OidcProviderTypeWithAuto,
22
+ auto_detect_oidc_provider,
23
+ get_active_oidc_provider,
24
+ )
25
+ from snowflake.cli.api.exceptions import CliError
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ Providers: TypeAlias = OidcProviderType | OidcProviderTypeWithAuto
31
+
32
+
33
+ class OidcManager:
34
+ """
35
+ Manages OIDC authentication.
36
+
37
+ This class provides methods to read OIDC configurations for authentication.
38
+ """
39
+
40
+ def read_token(
41
+ self,
42
+ provider_type: Providers = OidcProviderTypeWithAuto.AUTO,
43
+ ) -> str:
44
+ """
45
+ Reads OIDC token based on the specified provider type.
46
+
47
+ Args:
48
+ provider_type: Type of provider to read token from ("auto" for auto-detection)
49
+
50
+ Returns:
51
+ Token string or provider information
52
+
53
+ Raises:
54
+ CliError: If token reading fails
55
+ """
56
+ logger.info("Reading OIDC token with provider type: %s", provider_type)
57
+
58
+ try:
59
+ if provider_type == OidcProviderTypeWithAuto.AUTO:
60
+ provider = auto_detect_oidc_provider()
61
+ else:
62
+ provider = get_active_oidc_provider(provider_type.value)
63
+ return provider.get_token()
64
+ except OidcProviderError as e:
65
+ logger.error("OIDC provider error: %s", str(e))
66
+ raise CliError(str(e))
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2024 Snowflake Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from snowflake.cli._plugins.auth import app
16
+ from snowflake.cli.api.plugins.command import (
17
+ SNOWCLI_ROOT_COMMAND_PATH,
18
+ CommandSpec,
19
+ CommandType,
20
+ plugin_hook_impl,
21
+ )
22
+
23
+
24
+ @plugin_hook_impl
25
+ def command_spec():
26
+ return CommandSpec(
27
+ parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
28
+ command_type=CommandType.COMMAND_GROUP,
29
+ typer_instance=app.create_instance(),
30
+ )
@@ -53,6 +53,7 @@ from snowflake.cli.api.commands.flags import (
53
53
  TokenFilePathOption,
54
54
  UserOption,
55
55
  WarehouseOption,
56
+ WorkloadIdentityProviderOption,
56
57
  )
57
58
  from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
58
59
  from snowflake.cli.api.config import (
@@ -62,7 +63,9 @@ from snowflake.cli.api.config import (
62
63
  get_all_connections,
63
64
  get_connection_dict,
64
65
  get_default_connection_name,
66
+ remove_connection_from_proper_file,
65
67
  set_config_value,
68
+ unset_config_value,
66
69
  )
67
70
  from snowflake.cli.api.console import cli_console
68
71
  from snowflake.cli.api.constants import ObjectType
@@ -220,6 +223,12 @@ def add(
220
223
  *AuthenticatorOption.param_decls,
221
224
  help="Chosen authenticator, if other than password-based",
222
225
  ),
226
+ workload_identity_provider: Optional[str] = typer.Option(
227
+ None,
228
+ "-W",
229
+ *WorkloadIdentityProviderOption.param_decls,
230
+ help="Workload identity provider type",
231
+ ),
223
232
  private_key_file: Optional[str] = typer.Option(
224
233
  None,
225
234
  "--private-key",
@@ -256,6 +265,7 @@ def add(
256
265
  "port": port,
257
266
  "region": region,
258
267
  "authenticator": authenticator,
268
+ "workload_identity_provider": workload_identity_provider,
259
269
  "private_key_file": private_key_file,
260
270
  "token_file_path": token_file_path,
261
271
  }
@@ -317,6 +327,30 @@ def add(
317
327
  )
318
328
 
319
329
 
330
+ @app.command(requires_connection=False)
331
+ def remove(
332
+ connection_name: str = typer.Argument(
333
+ help="Name of the connection to remove.",
334
+ show_default=False,
335
+ ),
336
+ **options,
337
+ ):
338
+ """Removes a connection from configuration file."""
339
+ if not connection_exists(connection_name):
340
+ raise UsageError(f"Connection {connection_name} does not exist.")
341
+
342
+ is_default = get_default_connection_name() == connection_name
343
+ if is_default:
344
+ unset_config_value(path=["default_connection_name"])
345
+
346
+ connections_file = remove_connection_from_proper_file(connection_name)
347
+
348
+ return MessageResult(
349
+ f"Removed connection {connection_name} from {connections_file}."
350
+ f"{' It was the default connection, so default connection is now unset.' if is_default else ''}"
351
+ )
352
+
353
+
320
354
  @app.command(requires_connection=True)
321
355
  def test(
322
356
  **options,
@@ -355,9 +389,9 @@ def test(
355
389
  "Host": conn.host,
356
390
  "Account": conn.account,
357
391
  "User": conn.user,
358
- "Role": f'{conn.role or "not set"}',
359
- "Database": f'{conn.database or "not set"}',
360
- "Warehouse": f'{conn.warehouse or "not set"}',
392
+ "Role": f"{conn.role or 'not set'}",
393
+ "Database": f"{conn.database or 'not set'}",
394
+ "Warehouse": f"{conn.warehouse or 'not set'}",
361
395
  }
362
396
 
363
397
  if conn_ctx.enable_diag:
@@ -44,7 +44,7 @@ class DBTManager(SqlExecutionMixin):
44
44
 
45
45
  def deploy(
46
46
  self,
47
- name: FQN,
47
+ fqn: FQN,
48
48
  path: SecurePath,
49
49
  profiles_path: SecurePath,
50
50
  force: bool,
@@ -66,7 +66,7 @@ class DBTManager(SqlExecutionMixin):
66
66
 
67
67
  with cli_console.phase("Creating temporary stage"):
68
68
  stage_manager = StageManager()
69
- stage_fqn = FQN.from_string(f"dbt_{name}_stage").using_context()
69
+ stage_fqn = FQN.from_string(f"dbt_{fqn.name}_stage").using_context()
70
70
  stage_name = stage_manager.get_standard_stage_prefix(stage_fqn)
71
71
  stage_manager.create(stage_fqn, temporary=True)
72
72
 
@@ -86,11 +86,11 @@ class DBTManager(SqlExecutionMixin):
86
86
 
87
87
  with cli_console.phase("Creating DBT project"):
88
88
  if force is True:
89
- query = f"CREATE OR REPLACE DBT PROJECT {name}"
90
- elif self.exists(name=name):
91
- query = f"ALTER DBT PROJECT {name} ADD VERSION"
89
+ query = f"CREATE OR REPLACE DBT PROJECT {fqn}"
90
+ elif self.exists(name=fqn):
91
+ query = f"ALTER DBT PROJECT {fqn} ADD VERSION"
92
92
  else:
93
- query = f"CREATE DBT PROJECT {name}"
93
+ query = f"CREATE DBT PROJECT {fqn}"
94
94
  query += f"\nFROM {stage_name}"
95
95
  return self.execute_query(query)
96
96
 
@@ -174,7 +174,7 @@ class DBTManager(SqlExecutionMixin):
174
174
  yaml.safe_dump(yaml.safe_load(sfd), tfd)
175
175
 
176
176
  def execute(
177
- self, dbt_command: str, name: str, run_async: bool, *dbt_cli_args
177
+ self, dbt_command: str, name: FQN, run_async: bool, *dbt_cli_args
178
178
  ) -> SnowflakeCursor:
179
179
  if dbt_cli_args:
180
180
  dbt_command = " ".join([dbt_command, *dbt_cli_args]).strip()
@@ -11,24 +11,23 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
14
  from typing import List, Optional
16
15
 
17
16
  import typer
17
+ from snowflake.cli._plugins.dcm.dcm_project_entity_model import (
18
+ DCMProjectEntityModel,
19
+ )
20
+ from snowflake.cli._plugins.dcm.manager import DCMProjectManager
18
21
  from snowflake.cli._plugins.object.command_aliases import add_object_command_aliases
19
22
  from snowflake.cli._plugins.object.commands import scope_option
20
23
  from snowflake.cli._plugins.object.manager import ObjectManager
21
- from snowflake.cli._plugins.project.manager import ProjectManager
22
- from snowflake.cli._plugins.project.project_entity_model import (
23
- ProjectEntityModel,
24
- )
24
+ from snowflake.cli.api.artifacts.upload import sync_artifacts_with_stage
25
25
  from snowflake.cli.api.cli_global_context import get_cli_context
26
26
  from snowflake.cli.api.commands.decorators import with_project_definition
27
27
  from snowflake.cli.api.commands.flags import (
28
28
  IfExistsOption,
29
29
  IfNotExistsOption,
30
30
  OverrideableOption,
31
- PruneOption,
32
31
  entity_argument,
33
32
  identifier_argument,
34
33
  like_option,
@@ -46,99 +45,130 @@ from snowflake.cli.api.output.types import (
46
45
  QueryJsonValueResult,
47
46
  QueryResult,
48
47
  )
48
+ from snowflake.cli.api.project.project_paths import ProjectPaths
49
49
 
50
50
  app = SnowTyperFactory(
51
- name="project",
52
- help="Manages projects in Snowflake.",
51
+ name="dcm",
52
+ help="Manages DCM Projects in Snowflake.",
53
53
  is_hidden=FeatureFlag.ENABLE_SNOWFLAKE_PROJECTS.is_disabled,
54
54
  )
55
55
 
56
- project_identifier = identifier_argument(sf_object="project", example="MY_PROJECT")
57
- version_flag = typer.Option(
58
- None,
59
- "--version",
60
- help="Version of the project to use. If not specified default version is used. For names containing '$', use single quotes to prevent shell expansion (e.g., 'VERSION$1').",
61
- show_default=False,
62
- )
56
+ dcm_identifier = identifier_argument(sf_object="DCM Project", example="MY_PROJECT")
63
57
  variables_flag = variables_option(
64
58
  'Variables for the execution context; for example: `-D "<key>=<value>"`.'
65
59
  )
66
60
  configuration_flag = typer.Option(
67
61
  None,
68
62
  "--configuration",
69
- help="Configuration of the project to use. If not specified default configuration is used.",
63
+ help="Configuration of the DCM Project to use. If not specified default configuration is used.",
70
64
  show_default=False,
71
65
  )
72
66
  from_option = OverrideableOption(
73
67
  None,
74
68
  "--from",
69
+ mutually_exclusive=["prune"],
70
+ show_default=False,
71
+ )
72
+
73
+ prune_option = OverrideableOption(
74
+ False,
75
+ "--prune",
76
+ help="Remove unused artifacts from the stage during sync. Mutually exclusive with --from.",
77
+ mutually_exclusive=["from_stage"],
78
+ show_default=False,
79
+ )
80
+
81
+ alias_option = typer.Option(
82
+ None,
83
+ "--alias",
84
+ help="Alias for the deployment.",
85
+ show_default=False,
86
+ )
87
+ output_path_option = OverrideableOption(
88
+ None,
89
+ "--output-path",
90
+ show_default=False,
91
+ )
92
+
93
+ terse_option = typer.Option(
94
+ False,
95
+ "--terse",
96
+ help="Returns only a subset of output columns.",
97
+ show_default=False,
98
+ )
99
+
100
+ limit_option = typer.Option(
101
+ None,
102
+ "--limit",
103
+ help="Limits the maximum number of rows returned.",
75
104
  show_default=False,
76
105
  )
77
106
 
78
107
 
79
108
  add_object_command_aliases(
80
109
  app=app,
81
- object_type=ObjectType.PROJECT,
82
- name_argument=project_identifier,
110
+ object_type=ObjectType.DCM_PROJECT,
111
+ name_argument=dcm_identifier,
83
112
  like_option=like_option(
84
- help_example='`list --like "my%"` lists all projects that begin with "my"'
113
+ help_example='`list --like "my%"` lists all DCM Projects that begin with "my"'
85
114
  ),
86
115
  scope_option=scope_option(help_example="`list --in database my_db`"),
87
- ommit_commands=["create", "describe"],
116
+ ommit_commands=["create"],
117
+ terse_option=terse_option,
118
+ limit_option=limit_option,
88
119
  )
89
120
 
90
121
 
91
122
  @app.command(requires_connection=True)
92
- def execute(
93
- identifier: FQN = project_identifier,
94
- version: Optional[str] = version_flag,
123
+ def deploy(
124
+ identifier: FQN = dcm_identifier,
95
125
  from_stage: Optional[str] = from_option(
96
- help="Execute project from given stage instead of using a specific version."
126
+ help="Deploy DCM Project deployment from a given stage."
97
127
  ),
98
128
  variables: Optional[List[str]] = variables_flag,
99
129
  configuration: Optional[str] = configuration_flag,
130
+ alias: Optional[str] = alias_option,
131
+ prune: bool = prune_option(),
100
132
  **options,
101
133
  ):
102
134
  """
103
- Executes a project.
135
+ Applies changes defined in DCM Project to Snowflake.
104
136
  """
105
- if version and from_stage:
106
- raise CliError("--version and --from are mutually exclusive.")
107
-
108
- result = ProjectManager().execute(
137
+ result = DCMProjectManager().execute(
109
138
  project_name=identifier,
110
139
  configuration=configuration,
111
- version=version,
112
- from_stage=from_stage,
140
+ from_stage=from_stage if from_stage else _sync_local_files(prune=prune),
113
141
  variables=variables,
142
+ alias=alias,
143
+ output_path=None,
114
144
  )
115
145
  return QueryJsonValueResult(result)
116
146
 
117
147
 
118
148
  @app.command(requires_connection=True)
119
- def dry_run(
120
- identifier: FQN = project_identifier,
121
- version: Optional[str] = version_flag,
149
+ def plan(
150
+ identifier: FQN = dcm_identifier,
122
151
  from_stage: Optional[str] = from_option(
123
- help="Execute project from given stage instead of using a specific version."
152
+ help="Plan DCM Project deployment from a given stage."
124
153
  ),
125
154
  variables: Optional[List[str]] = variables_flag,
126
155
  configuration: Optional[str] = configuration_flag,
156
+ prune: bool = prune_option(),
157
+ output_path: Optional[str] = output_path_option(
158
+ help="Stage path where the deployment plan output will be stored."
159
+ ),
127
160
  **options,
128
161
  ):
129
162
  """
130
- Validates a project.
163
+ Plans a DCM Project deployment (validates without executing).
131
164
  """
132
- if version and from_stage:
133
- raise CliError("--version and --from are mutually exclusive.")
134
-
135
- result = ProjectManager().execute(
165
+ result = DCMProjectManager().execute(
136
166
  project_name=identifier,
137
167
  configuration=configuration,
138
- version=version,
139
- from_stage=from_stage,
168
+ from_stage=from_stage if from_stage else _sync_local_files(prune=prune),
140
169
  dry_run=True,
141
170
  variables=variables,
171
+ output_path=output_path,
142
172
  )
143
173
  return QueryJsonValueResult(result)
144
174
 
@@ -146,114 +176,55 @@ def dry_run(
146
176
  @app.command(requires_connection=True)
147
177
  @with_project_definition()
148
178
  def create(
149
- entity_id: str = entity_argument("project"),
150
- no_version: bool = typer.Option(
151
- False,
152
- "--no-version",
153
- help="Do not initialize project with a new version, only create the snowflake object.",
154
- ),
179
+ entity_id: str = entity_argument("dcm"),
155
180
  if_not_exists: bool = IfNotExistsOption(
156
181
  help="Do nothing if the project already exists."
157
182
  ),
158
183
  **options,
159
184
  ):
160
185
  """
161
- Creates a project in Snowflake.
162
- By default, the project is initialized with a new version created from local files.
186
+ Creates a DCM Project in Snowflake.
163
187
  """
164
188
  cli_context = get_cli_context()
165
- project: ProjectEntityModel = get_entity_for_operation(
189
+ project: DCMProjectEntityModel = get_entity_for_operation(
166
190
  cli_context=cli_context,
167
191
  entity_id=entity_id,
168
192
  project_definition=cli_context.project_definition,
169
- entity_type="project",
193
+ entity_type="dcm",
170
194
  )
171
195
  om = ObjectManager()
172
- if om.object_exists(object_type="project", fqn=project.fqn):
173
- message = f"Project '{project.fqn}' already exists."
196
+ if om.object_exists(object_type="dcm", fqn=project.fqn):
197
+ message = f"DCM Project '{project.fqn}' already exists."
174
198
  if if_not_exists:
175
199
  return MessageResult(message)
176
200
  raise CliError(message)
177
201
 
178
- if not no_version and om.object_exists(
179
- object_type="stage", fqn=FQN.from_stage(project.stage)
180
- ):
202
+ if om.object_exists(object_type="stage", fqn=FQN.from_stage(project.stage)):
181
203
  raise CliError(f"Stage '{project.stage}' already exists.")
182
204
 
183
- pm = ProjectManager()
184
- with cli_console.phase(f"Creating project '{project.fqn}'"):
185
- pm.create(project=project, initialize_version_from_local_files=not no_version)
205
+ dpm = DCMProjectManager()
206
+ with cli_console.phase(f"Creating DCM Project '{project.fqn}'"):
207
+ dpm.create(project=project)
186
208
 
187
- if no_version:
188
- return MessageResult(f"Project '{project.fqn}' successfully created.")
189
- return MessageResult(
190
- f"Project '{project.fqn}' successfully created and initial version is added."
191
- )
209
+ return MessageResult(f"DCM Project '{project.fqn}' successfully created.")
192
210
 
193
211
 
194
212
  @app.command(requires_connection=True)
195
- @with_project_definition()
196
- def add_version(
197
- entity_id: str = entity_argument("project"),
198
- _from: Optional[str] = from_option(
199
- help="Create a new version using given stage instead of uploading local files."
200
- ),
201
- _alias: Optional[str] = typer.Option(
202
- None, "--alias", help="Alias for the version.", show_default=False
203
- ),
204
- comment: Optional[str] = typer.Option(
205
- None, "--comment", help="Version comment.", show_default=False
206
- ),
207
- prune: bool = PruneOption(default=True),
208
- **options,
209
- ):
210
- """Uploads local files to Snowflake and cerates a new project version."""
211
- if _from is not None and prune:
212
- cli_console.warning(
213
- "When `--from` option is used, `--prune` option will be ignored and files from stage will be used as they are."
214
- )
215
- prune = False
216
- cli_context = get_cli_context()
217
- project: ProjectEntityModel = get_entity_for_operation(
218
- cli_context=cli_context,
219
- entity_id=entity_id,
220
- project_definition=cli_context.project_definition,
221
- entity_type="project",
222
- )
223
- om = ObjectManager()
224
- if not om.object_exists(object_type="project", fqn=project.fqn):
225
- raise CliError(
226
- f"Project '{project.fqn}' does not exist. Use `project create` command first."
227
- )
228
- ProjectManager().add_version(
229
- project=project,
230
- prune=prune,
231
- from_stage=_from,
232
- alias=_alias,
233
- comment=comment,
234
- )
235
- alias_str = "" if _alias is None else f"'{_alias}' "
236
- return MessageResult(
237
- f"New project version {alias_str}added to project '{project.fqn}'."
238
- )
239
-
240
-
241
- @app.command(requires_connection=True)
242
- def list_versions(
243
- identifier: FQN = project_identifier,
213
+ def list_deployments(
214
+ identifier: FQN = dcm_identifier,
244
215
  **options,
245
216
  ):
246
217
  """
247
- Lists versions of given project.
218
+ Lists deployments of given DCM Project.
248
219
  """
249
- pm = ProjectManager()
220
+ pm = DCMProjectManager()
250
221
  results = pm.list_versions(project_name=identifier)
251
222
  return QueryResult(results)
252
223
 
253
224
 
254
225
  @app.command(requires_connection=True)
255
- def drop_version(
256
- identifier: FQN = project_identifier,
226
+ def drop_deployment(
227
+ identifier: FQN = dcm_identifier,
257
228
  version_name: str = typer.Argument(
258
229
  help="Name or alias of the version to drop. For names containing '$', use single quotes to prevent shell expansion (e.g., 'VERSION$1').",
259
230
  show_default=False,
@@ -262,7 +233,7 @@ def drop_version(
262
233
  **options,
263
234
  ):
264
235
  """
265
- Drops a version from the project.
236
+ Drops a version from the DCM Project.
266
237
  """
267
238
  # Detect potential shell expansion issues
268
239
  if version_name and version_name.upper() == "VERSION":
@@ -271,12 +242,32 @@ def drop_version(
271
242
  f"If you meant to use a version like 'VERSION$1', try using single quotes: 'VERSION$1'."
272
243
  )
273
244
 
274
- pm = ProjectManager()
275
- pm.drop_version(
245
+ dpm = DCMProjectManager()
246
+ dpm.drop_deployment(
276
247
  project_name=identifier,
277
248
  version_name=version_name,
278
249
  if_exists=if_exists,
279
250
  )
280
251
  return MessageResult(
281
- f"Version '{version_name}' dropped from project '{identifier}'."
252
+ f"Version '{version_name}' dropped from DCM Project '{identifier}'."
253
+ )
254
+
255
+
256
+ def _sync_local_files(prune: bool = False) -> str:
257
+ cli_context = get_cli_context()
258
+ project_entity = get_entity_for_operation(
259
+ cli_context=cli_context,
260
+ entity_id=None,
261
+ project_definition=cli_context.project_definition,
262
+ entity_type="dcm",
282
263
  )
264
+
265
+ with cli_console.phase("Syncing local files to stage"):
266
+ sync_artifacts_with_stage(
267
+ project_paths=ProjectPaths(project_root=cli_context.project_root),
268
+ stage_root=project_entity.stage,
269
+ artifacts=project_entity.artifacts,
270
+ prune=prune,
271
+ )
272
+
273
+ return project_entity.stage
@@ -35,10 +35,10 @@ T = TypeVar("T")
35
35
  MANIFEST_FILE_NAME = "manifest.yml"
36
36
 
37
37
 
38
- class ProjectEntityModel(EntityModelBaseWithArtifacts):
39
- type: Literal["project"] = DiscriminatorField() # noqa: A003
38
+ class DCMProjectEntityModel(EntityModelBaseWithArtifacts):
39
+ type: Literal["dcm"] = DiscriminatorField() # noqa: A003
40
40
  stage: Optional[str] = Field(
41
- title="Stage in which the project artifacts will be stored", default=None
41
+ title="Stage in which the DCM Project artifacts will be stored", default=None
42
42
  )
43
43
 
44
44
  @field_validator("artifacts")
@@ -54,6 +54,6 @@ class ProjectEntityModel(EntityModelBaseWithArtifacts):
54
54
  return super().transform_artifacts(orig_artifacts)
55
55
 
56
56
 
57
- @attach_spans_to_entity_actions(entity_name="project")
58
- class ProjectEntity(EntityBase[ProjectEntityModel]):
57
+ @attach_spans_to_entity_actions(entity_name="dcm")
58
+ class DCMProjectEntity(EntityBase[DCMProjectEntityModel]):
59
59
  """Placeholder for project entity"""