Skip to content

Commit

Permalink
Merge branch 'main' into v3.2.2-release-notes-update
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-pczajka authored Dec 16, 2024
2 parents 94bdfc7 + dae4e10 commit 5aeedf1
Show file tree
Hide file tree
Showing 38 changed files with 1,610 additions and 64 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
## Backward incompatibility

## Deprecations
* Added deprecation message for default Streamlit warehouse

## New additions
* Add Release Directives support by introducing the following commands:
Expand All @@ -25,10 +26,12 @@
* `snow app release-directive unset`
* Add support for release channels feature in native app version creation/drop.
* `snow app version create` now returns version, patch, and label in JSON format.
* Add ability to specify release channel when creating application instance from release directive: `snow app run --from-release-directive --channel=<channel>`

## Fixes and improvements
* Fixed inability to add patches to lowercase quoted versions
* Fixes label being set to blank instead of None when not provided.
* Added a feature flag `ENABLE_SPCS_LOG_STREAMING` to control the rollout of the log streaming feature


# v3.2.2
Expand Down
12 changes: 11 additions & 1 deletion src/snowflake/cli/_plugins/nativeapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ def app_run(
The command fails if no release directive exists for your Snowflake account for a given application package, which is determined from the project definition file. Default: unset.""",
is_flag=True,
),
channel: str = typer.Option(
None,
show_default=False,
help=f"""The name of the release channel to use when creating or upgrading an application instance from a release directive.
Requires the `--from-release-directive` flag to be set. If unset, the default channel will be used.""",
),
interactive: bool = InteractiveOption,
force: Optional[bool] = ForceOption,
validate: bool = ValidateOption,
Expand Down Expand Up @@ -179,6 +185,7 @@ def app_run(
paths=[],
interactive=interactive,
force=force,
release_channel=channel,
)
app = ws.get_entity(app_id)
return MessageResult(
Expand Down Expand Up @@ -362,7 +369,10 @@ def app_validate(
if cli_context.output_format == OutputFormat.JSON:
return ObjectResult(
package.get_validation_result(
use_scratch_stage=True, interactive=False, force=True
action_ctx=ws.action_ctx,
use_scratch_stage=True,
interactive=False,
force=True,
)
)

Expand Down
46 changes: 46 additions & 0 deletions src/snowflake/cli/_plugins/nativeapp/entities/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from snowflake.cli._plugins.nativeapp.constants import (
ALLOWED_SPECIAL_COMMENTS,
COMMENT_COL,
DEFAULT_CHANNEL,
OWNER_COL,
)
from snowflake.cli._plugins.nativeapp.entities.application_package import (
Expand Down Expand Up @@ -85,6 +86,8 @@
append_test_resource_suffix,
extract_schema,
identifier_for_url,
identifier_in_list,
same_identifiers,
to_identifier,
unquote_identifier,
)
Expand Down Expand Up @@ -329,6 +332,7 @@ def action_deploy(
prune: bool,
recursive: bool,
paths: List[Path],
release_channel: Optional[str] = None,
validate: bool = ValidateOption,
stage_fqn: Optional[str] = None,
interactive: bool = InteractiveOption,
Expand Down Expand Up @@ -356,15 +360,25 @@ def action_deploy(

# same-account release directive
if from_release_directive:
release_channel = _get_verified_release_channel(
package_entity, release_channel
)

self.create_or_upgrade_app(
package=package_entity,
stage_fqn=stage_fqn,
install_method=SameAccountInstallMethod.release_directive(),
release_channel=release_channel,
policy=policy,
interactive=interactive,
)
return

if release_channel:
raise UsageError(
f"Release channel is only supported when --from-release-directive is used."
)

# versioned dev
if version:
try:
Expand Down Expand Up @@ -603,6 +617,7 @@ def _upgrade_app(
event_sharing: EventSharingHandler,
policy: PolicyBase,
interactive: bool,
release_channel: Optional[str] = None,
) -> list[tuple[str]] | None:
self.console.step(f"Upgrading existing application object {self.name}.")

Expand All @@ -613,6 +628,7 @@ def _upgrade_app(
stage_fqn=stage_fqn,
debug_mode=self.debug,
should_authorize_event_sharing=event_sharing.should_authorize_event_sharing(),
release_channel=release_channel,
role=self.role,
warehouse=self.warehouse,
)
Expand All @@ -627,6 +643,7 @@ def _create_app(
install_method: SameAccountInstallMethod,
event_sharing: EventSharingHandler,
package: ApplicationPackageEntity,
release_channel: Optional[str] = None,
) -> list[tuple[str]]:
self.console.step(f"Creating new application object {self.name} in account.")

Expand Down Expand Up @@ -665,6 +682,7 @@ def _create_app(
should_authorize_event_sharing=event_sharing.should_authorize_event_sharing(),
role=self.role,
warehouse=self.warehouse,
release_channel=release_channel,
)

@span("update_app_object")
Expand All @@ -675,6 +693,7 @@ def create_or_upgrade_app(
install_method: SameAccountInstallMethod,
policy: PolicyBase,
interactive: bool,
release_channel: Optional[str] = None,
):
event_sharing = EventSharingHandler(
telemetry_definition=self.telemetry,
Expand All @@ -699,6 +718,7 @@ def create_or_upgrade_app(
event_sharing=event_sharing,
policy=policy,
interactive=interactive,
release_channel=release_channel,
)

# 3. If no existing application found, or we performed a drop before the upgrade, we proceed to create
Expand All @@ -708,6 +728,7 @@ def create_or_upgrade_app(
install_method=install_method,
event_sharing=event_sharing,
package=package,
release_channel=release_channel,
)

print_messages(self.console, create_or_upgrade_result)
Expand Down Expand Up @@ -1004,3 +1025,28 @@ def _application_objects_to_str(

def _application_object_to_str(obj: ApplicationOwnedObject) -> str:
return f"({obj['type']}) {obj['name']}"


def _get_verified_release_channel(
package_entity: ApplicationPackageEntity,
release_channel: Optional[str],
) -> Optional[str]:
release_channel = release_channel or DEFAULT_CHANNEL
available_release_channels = get_snowflake_facade().show_release_channels(
package_entity.name, role=package_entity.role
)
if available_release_channels:
release_channel_names = [c["name"] for c in available_release_channels]
if not identifier_in_list(release_channel, release_channel_names):
raise UsageError(
f"Release channel '{release_channel}' is not available for application package {package_entity.name}. Available release channels: ({', '.join(release_channel_names)})."
)
else:
if same_identifiers(release_channel, DEFAULT_CHANNEL):
return None
else:
raise UsageError(
f"Release channels are not enabled for application package {package_entity.name}."
)

return release_channel
Loading

0 comments on commit 5aeedf1

Please sign in to comment.