Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2.8.0 cherry picks #1467

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ repos:
rev: v0.990
hooks:
- id: mypy
additional_dependencies: [types-all]
additional_dependencies: [types-pkg-resources==0.1.3, types-all==1.0.0]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.4
hooks:
Expand Down
6 changes: 6 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
## Backward incompatibility

## Deprecations
* Added deprecation warning for `native_app.package.scripts` in project definition file.

## New additions
* Added support for project definition file defaults in templates
* Added support for `native_app.package.post_deploy` scripts in project definition file.
* These scripts will execute whenever a Native App Package is created or updated.
* Currently only supports SQL scripts: `post_deploy: [{sql_script: script.sql}]`
* Added support for project definition file defaults in templates
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line can be removed - it's duplicate.


## Fixes and improvements

Expand Down
39 changes: 3 additions & 36 deletions src/snowflake/cli/api/project/definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@
from snowflake.cli.api.cli_global_context import cli_context
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
from snowflake.cli.api.project.schemas.project_definition import (
ProjectDefinition,
ProjectProperties,
)
from snowflake.cli.api.project.util import (
append_to_identifier,
clean_identifier,
get_env_username,
sanitize_identifier,
to_identifier,
)
from snowflake.cli.api.secure_path import SecurePath
Expand Down Expand Up @@ -70,40 +69,8 @@ def load_project(
return render_definition_template(merged_definitions, context_overrides or {})


def generate_local_override_yml(
project: ProjectDefinition,
) -> ProjectDefinition:
"""
Generates defaults for optional keys in the same YAML structure as the project
schema. The returned YAML object can be saved directly to a file, if desired.
A connection is made using global context to resolve current role and warehouse.
"""
conn = cli_context.connection
user = clean_identifier(get_env_username() or DEFAULT_USERNAME)
role = conn.role
warehouse = conn.warehouse

local: dict = {}
if project.native_app:
name = clean_identifier(project.native_app.name)
app_identifier = to_identifier(name)
user_app_identifier = append_to_identifier(app_identifier, f"_{user}")
package_identifier = append_to_identifier(app_identifier, f"_pkg_{user}")
local["native_app"] = {
"application": {
"name": user_app_identifier,
"role": role,
"debug": True,
"warehouse": warehouse,
},
"package": {"name": package_identifier, "role": role},
}

return project.update_from_dict(local)


def default_app_package(project_name: str):
user = clean_identifier(get_env_username() or DEFAULT_USERNAME)
user = sanitize_identifier(get_env_username() or DEFAULT_USERNAME).lower()
return append_to_identifier(to_identifier(project_name), f"_pkg_{user}")


Expand All @@ -113,5 +80,5 @@ def default_role():


def default_application(project_name: str):
user = clean_identifier(get_env_username() or DEFAULT_USERNAME)
user = sanitize_identifier(get_env_username() or DEFAULT_USERNAME).lower()
return append_to_identifier(to_identifier(project_name), f"_{user}")
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from typing import Literal, Optional

from pydantic import AliasChoices, Field
from pydantic import Field
from snowflake.cli.api.project.schemas.entities.application_package_entity import (
ApplicationPackageEntity,
)
Expand All @@ -25,26 +25,20 @@
TargetField,
)
from snowflake.cli.api.project.schemas.updatable_model import (
UpdatableModel,
DiscriminatorField,
)


class ApplicationEntity(EntityBase):
type: Literal["application"] # noqa: A003
type: Literal["application"] = DiscriminatorField() # noqa A003
name: str = Field(
title="Name of the application created when this entity is deployed"
)
from_: ApplicationFromField = Field(
validation_alias=AliasChoices("from"),
from_: TargetField[ApplicationPackageEntity] = Field(
alias="from",
title="An application package this entity should be created from",
)
debug: Optional[bool] = Field(
title="Whether to enable debug mode when using a named stage to create an application object",
default=None,
)


class ApplicationFromField(UpdatableModel):
target: TargetField[ApplicationPackageEntity] = Field(
title="Reference to an application package entity",
)
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
)
from snowflake.cli.api.project.schemas.native_app.package import DistributionOptions
from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
from snowflake.cli.api.project.schemas.updatable_model import IdentifierField
from snowflake.cli.api.project.schemas.updatable_model import (
DiscriminatorField,
IdentifierField,
)


class ApplicationPackageEntity(EntityBase):
type: Literal["application package"] # noqa: A003
type: Literal["application package"] = DiscriminatorField() # noqa: A003
name: str = Field(
title="Name of the application package created when this entity is deployed"
)
Expand Down
37 changes: 15 additions & 22 deletions src/snowflake/cli/api/project/schemas/entities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
from abc import ABC
from typing import Generic, List, Optional, TypeVar

from pydantic import AliasChoices, Field, GetCoreSchemaHandler, ValidationInfo
from pydantic_core import core_schema
from pydantic import Field
from snowflake.cli.api.project.schemas.native_app.application import (
ApplicationPostDeployHook,
PostDeployHook,
)
from snowflake.cli.api.project.schemas.updatable_model import (
IdentifierField,
Expand All @@ -36,7 +35,7 @@ class MetaField(UpdatableModel):
title="Role to use when creating the entity object",
default=None,
)
post_deploy: Optional[List[ApplicationPostDeployHook]] = Field(
post_deploy: Optional[List[PostDeployHook]] = Field(
title="Actions that will be executed after the application object is created/upgraded",
default=None,
)
Expand All @@ -45,7 +44,7 @@ class MetaField(UpdatableModel):
class DefaultsField(UpdatableModel):
schema_: Optional[str] = Field(
title="Schema.",
validation_alias=AliasChoices("schema"),
alias="schema",
default=None,
)
stage: Optional[str] = Field(
Expand All @@ -65,21 +64,15 @@ def get_type(cls) -> str:
TargetType = TypeVar("TargetType")


class TargetField(Generic[TargetType]):
def __init__(self, entity_target_key: str):
self.value = entity_target_key

def __repr__(self):
return self.value

@classmethod
def validate(cls, value: str, info: ValidationInfo) -> TargetField:
return cls(value)
class TargetField(UpdatableModel, Generic[TargetType]):
target: str = Field(
title="Reference to a target entity",
)

@classmethod
def __get_pydantic_core_schema__(
cls, source_type, handler: GetCoreSchemaHandler
) -> core_schema.CoreSchema:
return core_schema.with_info_after_validator_function(
cls.validate, handler(str), field_name=handler.field_name
)
def get_type(self) -> type:
"""
Returns the generic type of this class, indicating the entity type.
Pydantic extracts Generic annotations, and populates
them in __pydantic_generic_metadata__
"""
return self.__pydantic_generic_metadata__["args"][0]
12 changes: 10 additions & 2 deletions src/snowflake/cli/api/project/schemas/native_app/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SqlScriptHookType(UpdatableModel):


# Currently sql_script is the only supported hook type. Change to a Union once other hook types are added
ApplicationPostDeployHook = SqlScriptHookType
PostDeployHook = SqlScriptHookType


class Application(UpdatableModel):
Expand All @@ -48,7 +48,15 @@ class Application(UpdatableModel):
title="When set, forces debug_mode on/off for the deployed application object",
default=None,
)
post_deploy: Optional[List[ApplicationPostDeployHook]] = Field(
post_deploy: Optional[List[PostDeployHook]] = Field(
title="Actions that will be executed after the application object is created/upgraded",
default=None,
)


class ApplicationV11(Application):
# Templated defaults only supported in v1.1+
name: Optional[str] = Field(
title="Name of the application object created when you run the snow app run command",
default="<% fn.concat_ids(ctx.native_app.name, '_', fn.sanitize_id(fn.get_username('unknown_user')) | lower) %>",
)
15 changes: 13 additions & 2 deletions src/snowflake/cli/api/project/schemas/native_app/native_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
from typing import List, Optional, Union

from pydantic import Field, field_validator
from snowflake.cli.api.project.schemas.native_app.application import Application
from snowflake.cli.api.project.schemas.native_app.package import Package
from snowflake.cli.api.project.schemas.native_app.application import (
Application,
ApplicationV11,
)
from snowflake.cli.api.project.schemas.native_app.package import Package, PackageV11
from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
from snowflake.cli.api.project.util import (
Expand Down Expand Up @@ -80,3 +83,11 @@ def transform_artifacts(
transformed_artifacts.append(PathMapping(src=artifact))

return transformed_artifacts


class NativeAppV11(NativeApp):
# templated defaults are only supported with version 1.1+
package: Optional[PackageV11] = Field(title="PackageSchema", default=PackageV11())
application: Optional[ApplicationV11] = Field(
title="Application info", default=ApplicationV11()
)
25 changes: 24 additions & 1 deletion src/snowflake/cli/api/project/schemas/native_app/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

from typing import List, Literal, Optional

from pydantic import Field, field_validator
from pydantic import Field, field_validator, model_validator
from snowflake.cli.api.project.schemas.native_app.application import PostDeployHook
from snowflake.cli.api.project.schemas.updatable_model import (
IdentifierField,
UpdatableModel,
Expand Down Expand Up @@ -44,6 +45,10 @@ class Package(UpdatableModel):
title="Distribution of the application package created by the Snowflake CLI",
default="internal",
)
post_deploy: Optional[List[PostDeployHook]] = Field(
title="Actions that will be executed after the application package object is created/updated",
default=None,
)

@field_validator("scripts")
@classmethod
Expand All @@ -53,3 +58,21 @@ def validate_scripts(cls, input_list):
"package.scripts field should contain unique values. Check the list for duplicates and try again"
)
return input_list

@model_validator(mode="after")
@classmethod
def validate_no_scripts_and_post_deploy(cls, value: Package):
if value.scripts and value.post_deploy:
raise ValueError(
"package.scripts and package.post_deploy fields cannot be used together. "
"We recommend using package.post_deploy for all post package deploy scripts"
)
return value


class PackageV11(Package):
# Templated defaults only supported in v1.1+
name: Optional[str] = IdentifierField(
title="Name of the application package created when you run the snow app run command",
default="<% fn.concat_ids(ctx.native_app.name, '_pkg_', fn.sanitize_id(fn.get_username('unknown_user')) | lower) %>",
)
Loading
Loading