diff --git a/dbt_meshify/cli.py b/dbt_meshify/cli.py index 2e024b2..102cce6 100644 --- a/dbt_meshify/cli.py +++ b/dbt_meshify/cli.py @@ -107,7 +107,14 @@ "--latest", "-l", is_flag=True, - help="Makes the newest version the latest version when incrementing model versions", + help="Makes the newest version the latest version when creating model versions", +) + +increment = click.option( + "--increment", + "--i", + is_flag=True, + help="Increments the latest_version setting by 1 when creating model versions", ) diff --git a/dbt_meshify/main.py b/dbt_meshify/main.py index a9d79f9..0be5cce 100644 --- a/dbt_meshify/main.py +++ b/dbt_meshify/main.py @@ -18,7 +18,7 @@ from dbt_meshify.storage.dbt_project_editors import DbtSubprojectCreator from dbt_meshify.utilities.contractor import Contractor from dbt_meshify.utilities.linker import Linker -from dbt_meshify.utilities.versioner import ModelVersioner +from dbt_meshify.utilities.versioner import LatestVersionBehavior, ModelVersioner from .cli import ( TupleCompatibleCommand, @@ -27,6 +27,7 @@ exclude_projects, get_version, group_yml_path, + increment, latest, owner, owner_email, @@ -373,6 +374,7 @@ def add_version( @select @selector @latest +@increment @click.option("--defined-in", default=None) def bump_version( select, @@ -380,12 +382,25 @@ def bump_version( project_path, selector, latest: bool, + increment: bool, defined_in: Optional[Path], read_catalog, ) -> List[ChangeSet]: """ Create new model versions for all selected models. """ + + if latest and increment: + raise FatalMeshifyException( + "Cannot specify both --latest and --increment. Please choose one or the other." + ) + + latest_version_behavior = LatestVersionBehavior.Prerelease + if latest: + latest_version_behavior = LatestVersionBehavior.Latest + elif increment: + latest_version_behavior = LatestVersionBehavior.Increment + path = Path(project_path).expanduser().resolve() logger.info(f"Reading dbt project at {path}") @@ -412,7 +427,9 @@ def bump_version( continue changes: ChangeSet = versioner.bump_version( - model=model_node, prerelease=not (latest), defined_in=defined_in + model=model_node, + latest_version_behavior=latest_version_behavior, + defined_in=defined_in, ) change_set.extend(changes) @@ -429,6 +446,7 @@ def bump_version( @select @selector @latest +@increment @click.option("--defined-in", default=None) def version( select, @@ -436,12 +454,24 @@ def version( project_path, selector, latest: bool, + increment: bool, defined_in: Optional[Path], read_catalog, ) -> List[ChangeSet]: """ Increment the models to the next version, and create in the initial version if it has not yet been defined. """ + if latest and increment: + raise FatalMeshifyException( + "Cannot specify both --latest and --increment. Please choose one or the other." + ) + + latest_version_behavior = LatestVersionBehavior.Prerelease + if latest: + latest_version_behavior = LatestVersionBehavior.Latest + elif increment: + latest_version_behavior = LatestVersionBehavior.Increment + path = Path(project_path).expanduser().resolve() logger.info(f"Reading dbt project at {path}") @@ -474,7 +504,7 @@ def version( versioner.bump_version( model=model_node, defined_in=defined_in, - prerelease=not (latest), + latest_version_behavior=latest_version_behavior, ) ) @@ -498,7 +528,7 @@ def version( bump_change: ChangeSet = versioner.bump_version( model=model_node, defined_in=defined_in, - prerelease=not (latest), + latest_version_behavior=latest_version_behavior, model_override=model_add_change.data, ) diff --git a/dbt_meshify/utilities/versioner.py b/dbt_meshify/utilities/versioner.py index 86d74d4..fdc331e 100644 --- a/dbt_meshify/utilities/versioner.py +++ b/dbt_meshify/utilities/versioner.py @@ -1,3 +1,4 @@ +from enum import Enum from pathlib import Path from typing import Any, Dict, Optional, Union @@ -16,6 +17,14 @@ from dbt_meshify.storage.file_manager import FileManager, YAMLFileManager +class LatestVersionBehavior(str, Enum): + """The type of behavior applied to `latest_version` when updating model versions""" + + Prerelease = "prerelease" + Increment = "increment" + Latest = "latest" + + class ModelVersionerException(Exception): """Exceptions raised during versioning of a Model.""" @@ -127,7 +136,7 @@ def add_version(self, model: ModelNode, defined_in: Optional[Path] = None) -> Ch def bump_version( self, model: ModelNode, - prerelease: bool = False, + latest_version_behavior: LatestVersionBehavior = LatestVersionBehavior.Prerelease, defined_in: Optional[Path] = None, model_override: Optional[Dict] = None, ) -> ChangeSet: @@ -149,12 +158,21 @@ def bump_version( ) # Within dbt-core, if unset `latest_version` defaults to the greatest version identifier. - latest_version = model_yml.get("latest_version", greatest_version) - - # Bump versions + current_latest_version = model_yml.get("latest_version", greatest_version) new_greatest_version_number = greatest_version + 1 - new_latest_version_number = latest_version if prerelease else latest_version + 1 + # if prerelease, the latest version is unchanged + # if increment, the latest version is incremented by 1 + # if latest, the latest version is set to the greatest version + 1 (newly created version) + + latest_version_number_map = { + LatestVersionBehavior.Prerelease: current_latest_version, + LatestVersionBehavior.Increment: current_latest_version + 1, + LatestVersionBehavior.Latest: greatest_version + 1, + } + + + new_latest_version_number = latest_version_number_map[latest_version_behavior] # Setup the new version definitions new_version_data: Dict[str, Any] = {"v": new_greatest_version_number} if defined_in: diff --git a/tests/integration/test_version_command.py b/tests/integration/test_version_command.py index 864a606..c44a46f 100644 --- a/tests/integration/test_version_command.py +++ b/tests/integration/test_version_command.py @@ -10,6 +10,7 @@ from tests.dbt_project_utils import setup_test_project, teardown_test_project from ..sql_and_yml_fixtures import ( + expected_versioned_model_yml_increment_latest_version, expected_versioned_model_yml_increment_prerelease_version, expected_versioned_model_yml_increment_prerelease_version_with_second_prerelease, expected_versioned_model_yml_increment_version_no_prerelease, @@ -239,10 +240,17 @@ def test_bump_version_fails_when_no_versions_present( expected_versioned_model_yml_increment_prerelease_version, ["shared_model_v1.sql", "shared_model_v2.sql"], ["shared_model_v1.sql", "shared_model_v2.sql", "shared_model_v3.sql"], + ["--increment"], + ), + ( + expected_versioned_model_yml_increment_version_with_prerelease, + expected_versioned_model_yml_increment_latest_version, + ["shared_model_v1.sql", "shared_model_v2.sql"], + ["shared_model_v1.sql", "shared_model_v2.sql", "shared_model_v3.sql"], ["--latest"], ), ], - ids=["1", "2", "3", "4", "5"], + ids=["1", "2", "3", "4", "5", "6"], ) def test_bump_version_in_yml( start_yml, end_yml, start_files, expected_files, command_options, project diff --git a/tests/sql_and_yml_fixtures.py b/tests/sql_and_yml_fixtures.py index 0517af4..251dbcb 100644 --- a/tests/sql_and_yml_fixtures.py +++ b/tests/sql_and_yml_fixtures.py @@ -262,6 +262,17 @@ - v: 3 """ +expected_versioned_model_yml_increment_latest_version = """ +models: + - name: shared_model + latest_version: 3 + description: "this is a test model" + versions: + - v: 1 + - v: 2 + - v: 3 +""" + expected_versioned_model_yml_prerelease_defined_in = """ models: - name: shared_model diff --git a/tests/unit/test_add_version_to_yml.py b/tests/unit/test_add_version_to_yml.py index 2313e12..4c4d925 100644 --- a/tests/unit/test_add_version_to_yml.py +++ b/tests/unit/test_add_version_to_yml.py @@ -4,7 +4,7 @@ import yaml from dbt_meshify.storage.file_content_editors import ResourceFileEditor -from dbt_meshify.utilities.versioner import ModelVersioner +from dbt_meshify.utilities.versioner import LatestVersionBehavior, ModelVersioner from ..dbt_project_fixtures import model, project # noqa: F401 from ..sql_and_yml_fixtures import ( @@ -59,7 +59,9 @@ def test_add_version_to_model_yml_increment_version_no_prerelease( self, model, project, file_manager # noqa: F811 ): versioner = ModelVersioner(project=project, file_manager=file_manager) - changes = list(versioner.bump_version(model)) + changes = list( + versioner.bump_version(model, latest_version_behavior=LatestVersionBehavior.Increment) + ) yml_dict = ResourceFileEditor.update_resource( properties=read_yml(model_yml_increment_version), change=changes[0] ) @@ -70,7 +72,9 @@ def test_add_version_to_model_yml_increment_version_with_prerelease( self, model, project, file_manager # noqa: F811 ): versioner = ModelVersioner(project=project, file_manager=file_manager) - changes = list(versioner.bump_version(model, prerelease=True)) + changes = list( + versioner.bump_version(model, latest_version_behavior=LatestVersionBehavior.Prerelease) + ) yml_dict = ResourceFileEditor.update_resource( properties=read_yml(model_yml_increment_version), change=changes[0] ) @@ -81,7 +85,13 @@ def test_add_version_to_model_yml_increment_version_defined_in( self, model, project, file_manager # noqa: F811 ): versioner = ModelVersioner(project=project, file_manager=file_manager) - changes = list(versioner.bump_version(model, defined_in="daves_model", prerelease=True)) + changes = list( + versioner.bump_version( + model, + latest_version_behavior=LatestVersionBehavior.Prerelease, + defined_in="daves_model", + ) + ) yml_dict = ResourceFileEditor.update_resource( properties=read_yml(model_yml_increment_version), change=changes[0] )