dbt-platform-helper 13.4.0__py3-none-any.whl → 14.0.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.

Potentially problematic release.


This version of dbt-platform-helper might be problematic. Click here for more details.

Files changed (46) hide show
  1. dbt_platform_helper/COMMANDS.md +26 -57
  2. dbt_platform_helper/commands/config.py +9 -0
  3. dbt_platform_helper/commands/environment.py +3 -7
  4. dbt_platform_helper/commands/notify.py +24 -77
  5. dbt_platform_helper/commands/pipeline.py +6 -12
  6. dbt_platform_helper/commands/secrets.py +1 -1
  7. dbt_platform_helper/constants.py +7 -5
  8. dbt_platform_helper/domain/codebase.py +0 -5
  9. dbt_platform_helper/domain/config.py +16 -9
  10. dbt_platform_helper/domain/copilot_environment.py +3 -3
  11. dbt_platform_helper/domain/database_copy.py +1 -1
  12. dbt_platform_helper/domain/maintenance_page.py +42 -38
  13. dbt_platform_helper/domain/notify.py +64 -0
  14. dbt_platform_helper/domain/pipelines.py +20 -16
  15. dbt_platform_helper/domain/terraform_environment.py +18 -11
  16. dbt_platform_helper/domain/versioning.py +18 -78
  17. dbt_platform_helper/providers/aws/exceptions.py +1 -1
  18. dbt_platform_helper/providers/cloudformation.py +1 -1
  19. dbt_platform_helper/providers/config.py +119 -17
  20. dbt_platform_helper/providers/config_validator.py +4 -31
  21. dbt_platform_helper/providers/copilot.py +3 -3
  22. dbt_platform_helper/providers/io.py +1 -1
  23. dbt_platform_helper/providers/load_balancers.py +6 -6
  24. dbt_platform_helper/providers/platform_config_schema.py +24 -29
  25. dbt_platform_helper/providers/schema_migrations/__init__.py +0 -0
  26. dbt_platform_helper/providers/schema_migrations/schema_v0_to_v1_migration.py +43 -0
  27. dbt_platform_helper/providers/schema_migrator.py +77 -0
  28. dbt_platform_helper/providers/secrets.py +5 -5
  29. dbt_platform_helper/providers/semantic_version.py +6 -1
  30. dbt_platform_helper/providers/slack_channel_notifier.py +62 -0
  31. dbt_platform_helper/providers/terraform_manifest.py +8 -10
  32. dbt_platform_helper/providers/version.py +1 -18
  33. dbt_platform_helper/providers/version_status.py +8 -61
  34. dbt_platform_helper/providers/yaml_file.py +23 -1
  35. dbt_platform_helper/templates/environment-pipelines/main.tf +1 -1
  36. dbt_platform_helper/utils/application.py +1 -1
  37. dbt_platform_helper/utils/aws.py +3 -3
  38. dbt_platform_helper/utils/git.py +0 -15
  39. {dbt_platform_helper-13.4.0.dist-info → dbt_platform_helper-14.0.0.dist-info}/METADATA +4 -4
  40. {dbt_platform_helper-13.4.0.dist-info → dbt_platform_helper-14.0.0.dist-info}/RECORD +44 -41
  41. platform_helper.py +0 -2
  42. dbt_platform_helper/commands/version.py +0 -37
  43. dbt_platform_helper/utils/tool_versioning.py +0 -12
  44. {dbt_platform_helper-13.4.0.dist-info → dbt_platform_helper-14.0.0.dist-info}/LICENSE +0 -0
  45. {dbt_platform_helper-13.4.0.dist-info → dbt_platform_helper-14.0.0.dist-info}/WHEEL +0 -0
  46. {dbt_platform_helper-13.4.0.dist-info → dbt_platform_helper-14.0.0.dist-info}/entry_points.txt +0 -0
@@ -48,7 +48,7 @@ class FailedToActivateMaintenancePageException(MaintenancePageException):
48
48
  return f"{super().__str__()}\n" f"Original exception: {self.orginal_exception}"
49
49
 
50
50
 
51
- # TODO should this be in its own provider, inside the VPC one, what logic is this sepcific too?
51
+ # TODO: DBTP-1958: should this be in its own provider, inside the VPC one, what logic is this sepcific too?
52
52
  def get_env_ips(vpc: str, application_environment: Environment) -> List[str]:
53
53
  account_name = f"{application_environment.session.profile_name}-vpc"
54
54
  vpc_name = vpc if vpc else account_name
@@ -73,7 +73,7 @@ class MaintenancePage:
73
73
  ):
74
74
  self.application = application
75
75
  self.io = io
76
- self.load_balancer_provider = load_balancer_provider # TODO requires session from environment in application object which is only known during method execution
76
+ self.load_balancer_provider = load_balancer_provider # TODO: DBTP-1962: requires session from environment in application object which is only known during method execution
77
77
  self.load_balancer: LoadBalancerProvider = None
78
78
  self.get_env_ips = get_env_ips
79
79
 
@@ -87,7 +87,7 @@ class MaintenancePage:
87
87
  raise LoadBalancedWebServiceNotFoundException(app.name)
88
88
  return services
89
89
 
90
- # TODO: inject load balancer provider in activate method to avoid passing load balancer provider in init?
90
+ # TODO: DBTP-1962: inject load balancer provider in activate method to avoid passing load balancer provider in init?
91
91
  def activate(self, env: str, services: List[str], template: str, vpc: Union[str, None]):
92
92
 
93
93
  services = self._get_deployed_load_balanced_web_services(self.application, services)
@@ -229,44 +229,48 @@ class MaintenancePage:
229
229
  f"\nUse a browser plugin to add `Bypass-Key` header with value {bypass_value} to your requests. For more detail, visit https://platform.readme.trade.gov.uk/next-steps/put-a-service-under-maintenance/",
230
230
  )
231
231
 
232
- self.load_balancer.create_rule(
233
- listener_arn=listener_arn,
234
- priority=next(rule_priority),
235
- conditions=[
232
+ unique_sorted_host_headers = sorted(
233
+ list(
236
234
  {
237
- "Field": "path-pattern",
238
- "PathPatternConfig": {"Values": ["/*"]},
239
- },
240
- {
241
- "Field": "host-header",
242
- "HostHeaderConfig": {
243
- "Values": sorted(
244
- list(
245
- {
246
- value
247
- for condition in maintenance_page_host_header_conditions
248
- for value in condition["HostHeaderConfig"]["Values"]
249
- }
250
- )
251
- )
252
- },
253
- },
254
- ],
255
- actions=[
256
- {
257
- "Type": "fixed-response",
258
- "FixedResponseConfig": {
259
- "StatusCode": "503",
260
- "ContentType": "text/html",
261
- "MessageBody": maintenance_page_content,
262
- },
235
+ value
236
+ for condition in maintenance_page_host_header_conditions
237
+ for value in condition["HostHeaderConfig"]["Values"]
263
238
  }
264
- ],
265
- tags=[
266
- {"Key": "name", "Value": "MaintenancePage"},
267
- {"Key": "type", "Value": template},
268
- ],
239
+ )
269
240
  )
241
+
242
+ # Can only set 4 host headers per rule as listener rules have a max conditions of 5
243
+ for i in range(0, len(unique_sorted_host_headers), 4):
244
+ self.load_balancer.create_rule(
245
+ listener_arn=listener_arn,
246
+ priority=next(rule_priority),
247
+ conditions=[
248
+ {
249
+ "Field": "path-pattern",
250
+ "PathPatternConfig": {"Values": ["/*"]},
251
+ },
252
+ {
253
+ "Field": "host-header",
254
+ "HostHeaderConfig": {
255
+ "Values": unique_sorted_host_headers[i : i + 4],
256
+ },
257
+ },
258
+ ],
259
+ actions=[
260
+ {
261
+ "Type": "fixed-response",
262
+ "FixedResponseConfig": {
263
+ "StatusCode": "503",
264
+ "ContentType": "text/html",
265
+ "MessageBody": maintenance_page_content,
266
+ },
267
+ }
268
+ ],
269
+ tags=[
270
+ {"Key": "name", "Value": "MaintenancePage"},
271
+ {"Key": "type", "Value": template},
272
+ ],
273
+ )
270
274
  except Exception as e:
271
275
  self.__clean_up_maintenance_page_rules(listener_arn)
272
276
  raise FailedToActivateMaintenancePageException(
@@ -0,0 +1,64 @@
1
+ from dbt_platform_helper.providers.slack_channel_notifier import SlackChannelNotifier
2
+ from dbt_platform_helper.utils.arn_parser import ARN
3
+
4
+
5
+ class Notify:
6
+ def __init__(self, notifier: SlackChannelNotifier):
7
+ self.notifier = notifier
8
+
9
+ def environment_progress(
10
+ self,
11
+ message: str,
12
+ build_arn: str = None,
13
+ repository: str = None,
14
+ commit_sha: str = None,
15
+ original_message_ref: str = None,
16
+ ):
17
+ context = []
18
+
19
+ if repository:
20
+ context.append(f"*Repository*: <https://github.com/{repository}|{repository}>")
21
+ if commit_sha:
22
+ context.append(
23
+ f"*Revision*: <https://github.com/{repository}/commit/{commit_sha}|{commit_sha}>"
24
+ )
25
+
26
+ if build_arn:
27
+ context.append(f"<{get_build_url(build_arn)}|Build Logs>")
28
+
29
+ if original_message_ref:
30
+ return self.notifier.post_update(original_message_ref, message, context)
31
+ else:
32
+ return self.notifier.post_new(message, context)
33
+
34
+ def add_comment(
35
+ self,
36
+ original_message_ref: str,
37
+ message: str,
38
+ title: str,
39
+ reply_broadcast: bool,
40
+ ):
41
+ self.notifier.post_new(
42
+ message=message,
43
+ title=title,
44
+ context=[],
45
+ reply_broadcast=reply_broadcast,
46
+ thread_ref=original_message_ref,
47
+ )
48
+
49
+
50
+ def get_build_url(build_arn: str):
51
+ try:
52
+ arn = ARN(build_arn)
53
+ url = (
54
+ "https://{region}.console.aws.amazon.com/codesuite/codebuild/{account}/projects/{"
55
+ "project}/build/{project}%3A{build_id}"
56
+ )
57
+ return url.format(
58
+ region=arn.region,
59
+ account=arn.account_id,
60
+ project=arn.project.replace("build/", ""),
61
+ build_id=arn.build_id,
62
+ )
63
+ except ValueError:
64
+ return ""
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from collections.abc import Callable
2
3
  from os import makedirs
3
4
  from pathlib import Path
@@ -5,6 +6,7 @@ from shutil import rmtree
5
6
 
6
7
  from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY
7
8
  from dbt_platform_helper.constants import ENVIRONMENT_PIPELINES_KEY
9
+ from dbt_platform_helper.constants import PLATFORM_HELPER_VERSION_OVERRIDE_KEY
8
10
  from dbt_platform_helper.constants import SUPPORTED_AWS_PROVIDER_VERSION
9
11
  from dbt_platform_helper.constants import SUPPORTED_TERRAFORM_VERSION
10
12
  from dbt_platform_helper.providers.config import ConfigProvider
@@ -14,9 +16,6 @@ from dbt_platform_helper.providers.io import ClickIOProvider
14
16
  from dbt_platform_helper.providers.terraform_manifest import TerraformManifestProvider
15
17
  from dbt_platform_helper.utils.application import get_application_name
16
18
  from dbt_platform_helper.utils.template import setup_templates
17
- from dbt_platform_helper.utils.tool_versioning import (
18
- get_required_terraform_platform_modules_version,
19
- )
20
19
 
21
20
 
22
21
  class Pipelines:
@@ -29,6 +28,7 @@ class Pipelines:
29
28
  get_codestar_arn: Callable[[str], str],
30
29
  io: ClickIOProvider = ClickIOProvider(),
31
30
  file_provider: FileProvider = FileProvider(),
31
+ platform_helper_version_override: str = None,
32
32
  ):
33
33
  self.config_provider = config_provider
34
34
  self.get_git_remote = get_git_remote
@@ -37,8 +37,14 @@ class Pipelines:
37
37
  self.ecr_provider = ecr_provider
38
38
  self.io = io
39
39
  self.file_provider = file_provider
40
+ self.platform_helper_version_override = platform_helper_version_override or os.environ.get(
41
+ PLATFORM_HELPER_VERSION_OVERRIDE_KEY
42
+ )
40
43
 
41
- def generate(self, cli_terraform_platform_modules_version: str, deploy_branch: str):
44
+ def generate(
45
+ self,
46
+ deploy_branch: str,
47
+ ):
42
48
  platform_config = self.config_provider.load_and_validate_platform_config()
43
49
 
44
50
  has_codebase_pipelines = CODEBASE_PIPELINES_KEY in platform_config
@@ -48,10 +54,6 @@ class Pipelines:
48
54
  self.io.warn("No pipelines defined: nothing to do.")
49
55
  return
50
56
 
51
- platform_config_terraform_modules_default_version = platform_config.get(
52
- "default_versions", {}
53
- ).get("terraform-platform-modules", "")
54
-
55
57
  app_name = get_application_name()
56
58
 
57
59
  git_repo = self.get_git_remote()
@@ -67,12 +69,14 @@ class Pipelines:
67
69
 
68
70
  self._clean_pipeline_config(copilot_pipelines_dir)
69
71
 
70
- terraform_platform_modules_version = get_required_terraform_platform_modules_version(
71
- cli_terraform_platform_modules_version,
72
- platform_config_terraform_modules_default_version,
72
+ platform_helper_version_for_template: str = platform_config.get("default_versions", {}).get(
73
+ "platform-helper"
73
74
  )
74
75
 
75
- # TODO - this whole code block/if-statement can fall away once the deploy_repository is a required key.
76
+ if self.platform_helper_version_override:
77
+ platform_helper_version_for_template = self.platform_helper_version_override
78
+
79
+ # TODO: DBTP-1965: - this whole code block/if-statement can fall away once the deploy_repository is a required key.
76
80
  deploy_repository = ""
77
81
  if "deploy_repository" in platform_config.keys():
78
82
  deploy_repository = f"{platform_config['deploy_repository']}"
@@ -95,7 +99,7 @@ class Pipelines:
95
99
  platform_config["application"],
96
100
  deploy_repository,
97
101
  account,
98
- terraform_platform_modules_version,
102
+ platform_helper_version_for_template,
99
103
  deploy_branch,
100
104
  )
101
105
 
@@ -114,7 +118,7 @@ class Pipelines:
114
118
 
115
119
  self.terraform_manifest_provider.generate_codebase_pipeline_config(
116
120
  platform_config,
117
- terraform_platform_modules_version,
121
+ platform_helper_version_for_template,
118
122
  ecrs_that_need_importing,
119
123
  deploy_repository,
120
124
  )
@@ -129,7 +133,7 @@ class Pipelines:
129
133
  application: str,
130
134
  deploy_repository: str,
131
135
  aws_account: str,
132
- terraform_platform_modules_version: str,
136
+ platform_helper_version: str,
133
137
  deploy_branch: str,
134
138
  ):
135
139
  env_pipeline_template = setup_templates().get_template("environment-pipelines/main.tf")
@@ -139,7 +143,7 @@ class Pipelines:
139
143
  "application": application,
140
144
  "deploy_repository": deploy_repository,
141
145
  "aws_account": aws_account,
142
- "terraform_platform_modules_version": terraform_platform_modules_version,
146
+ "platform_helper_version": platform_helper_version,
143
147
  "deploy_branch": deploy_branch,
144
148
  "terraform_version": SUPPORTED_TERRAFORM_VERSION,
145
149
  "aws_provider_version": SUPPORTED_AWS_PROVIDER_VERSION,
@@ -1,9 +1,9 @@
1
+ import os
2
+
3
+ from dbt_platform_helper.constants import PLATFORM_HELPER_VERSION_OVERRIDE_KEY
1
4
  from dbt_platform_helper.platform_exception import PlatformException
2
5
  from dbt_platform_helper.providers.io import ClickIOProvider
3
6
  from dbt_platform_helper.providers.terraform_manifest import TerraformManifestProvider
4
- from dbt_platform_helper.utils.tool_versioning import (
5
- get_required_terraform_platform_modules_version,
6
- )
7
7
 
8
8
 
9
9
  class TerraformEnvironmentException(PlatformException):
@@ -20,12 +20,20 @@ class TerraformEnvironment:
20
20
  config_provider,
21
21
  manifest_provider: TerraformManifestProvider = None,
22
22
  io: ClickIOProvider = ClickIOProvider(),
23
+ platform_helper_version_override: str = None,
23
24
  ):
24
25
  self.io = io
25
26
  self.config_provider = config_provider
26
27
  self.manifest_provider = manifest_provider or TerraformManifestProvider()
28
+ self.platform_helper_version_override = platform_helper_version_override or os.environ.get(
29
+ PLATFORM_HELPER_VERSION_OVERRIDE_KEY
30
+ )
31
+
32
+ def generate(
33
+ self,
34
+ environment_name: str,
35
+ ):
27
36
 
28
- def generate(self, environment_name, terraform_platform_modules_version_override=None):
29
37
  config = self.config_provider.get_enriched_config()
30
38
 
31
39
  if environment_name not in config.get("environments").keys():
@@ -33,14 +41,13 @@ class TerraformEnvironment:
33
41
  f"cannot generate terraform for environment {environment_name}. It does not exist in your configuration"
34
42
  )
35
43
 
36
- platform_config_terraform_modules_default_version = config.get("default_versions", {}).get(
37
- "terraform-platform-modules", ""
38
- )
39
- terraform_platform_modules_version = get_required_terraform_platform_modules_version(
40
- terraform_platform_modules_version_override,
41
- platform_config_terraform_modules_default_version,
44
+ platform_helper_version_for_template: str = config.get("default_versions", {}).get(
45
+ "platform-helper"
42
46
  )
43
47
 
48
+ if self.platform_helper_version_override:
49
+ platform_helper_version_for_template = self.platform_helper_version_override
50
+
44
51
  self.manifest_provider.generate_environment_config(
45
- config, environment_name, terraform_platform_modules_version
52
+ config, environment_name, platform_helper_version_for_template
46
53
  )
@@ -12,14 +12,11 @@ from dbt_platform_helper.providers.semantic_version import (
12
12
  from dbt_platform_helper.providers.semantic_version import SemanticVersion
13
13
  from dbt_platform_helper.providers.version import AWSCLIInstalledVersionProvider
14
14
  from dbt_platform_helper.providers.version import CopilotInstalledVersionProvider
15
- from dbt_platform_helper.providers.version import DeprecatedVersionFileVersionProvider
16
15
  from dbt_platform_helper.providers.version import GithubLatestVersionProvider
17
16
  from dbt_platform_helper.providers.version import InstalledVersionProvider
18
17
  from dbt_platform_helper.providers.version import PyPiLatestVersionProvider
19
18
  from dbt_platform_helper.providers.version import VersionProvider
20
- from dbt_platform_helper.providers.version_status import PlatformHelperVersionStatus
21
19
  from dbt_platform_helper.providers.version_status import VersionStatus
22
- from dbt_platform_helper.providers.yaml_file import YamlFileProvider
23
20
 
24
21
 
25
22
  def running_as_installed_package():
@@ -31,24 +28,20 @@ def skip_version_checks():
31
28
 
32
29
 
33
30
  class PlatformHelperVersionNotFoundException(PlatformException):
34
- def __init__(self):
35
- super().__init__(f"""Platform helper version could not be resolved.""")
31
+ def __init__(self, message=None):
32
+ super().__init__(message or "Platform helper version could not be resolved.")
36
33
 
37
34
 
38
35
  class PlatformHelperVersioning:
39
36
  def __init__(
40
37
  self,
41
38
  io: ClickIOProvider = ClickIOProvider(),
42
- version_file_version_provider: DeprecatedVersionFileVersionProvider = DeprecatedVersionFileVersionProvider(
43
- YamlFileProvider
44
- ),
45
39
  config_provider: ConfigProvider = ConfigProvider(),
46
40
  latest_version_provider: VersionProvider = PyPiLatestVersionProvider,
47
41
  installed_version_provider: InstalledVersionProvider = InstalledVersionProvider(),
48
42
  skip_versioning_checks: bool = None,
49
43
  ):
50
44
  self.io = io
51
- self.version_file_version_provider = version_file_version_provider
52
45
  self.config_provider = config_provider
53
46
  self.latest_version_provider = latest_version_provider
54
47
  self.installed_version_provider = installed_version_provider
@@ -56,10 +49,9 @@ class PlatformHelperVersioning:
56
49
  skip_versioning_checks if skip_versioning_checks is not None else skip_version_checks()
57
50
  )
58
51
 
59
- def get_required_version(self, pipeline=None):
60
- version_status = self._get_version_status()
61
- self.io.process_messages(version_status.validate())
62
- required_version = self._resolve_required_version(pipeline, version_status)
52
+ def get_required_version(self):
53
+ platform_config = self.config_provider.load_and_validate_platform_config()
54
+ required_version = platform_config.get("default_versions", {}).get("platform-helper")
63
55
  self.io.info(required_version)
64
56
  return required_version
65
57
 
@@ -68,25 +60,24 @@ class PlatformHelperVersioning:
68
60
  if self.skip_versioning_checks:
69
61
  return
70
62
 
71
- version_status = self._get_version_status()
72
- self.io.process_messages(version_status.validate())
63
+ version_status = self.get_version_status()
64
+ required_version = self.get_required_version()
73
65
 
74
- required_version = SemanticVersion.from_string(
75
- self._resolve_required_version(version_status=version_status)
76
- )
66
+ if SemanticVersion.is_semantic_version(required_version):
67
+ required_version_semver = SemanticVersion.from_string(required_version)
77
68
 
78
- if not version_status.installed == required_version:
79
- message = (
80
- f"WARNING: You are running platform-helper v{version_status.installed} against "
81
- f"v{required_version} specified for the project."
82
- )
83
- self.io.warn(message)
69
+ if not version_status.installed == required_version_semver:
70
+ message = (
71
+ f"WARNING: You are running platform-helper v{version_status.installed} against "
72
+ f"v{required_version_semver} specified for the project."
73
+ )
74
+ self.io.warn(message)
84
75
 
85
76
  def check_if_needs_update(self):
86
77
  if self.skip_versioning_checks:
87
78
  return
88
79
 
89
- version_status = self._get_version_status(include_project_versions=False)
80
+ version_status = self.get_version_status()
90
81
 
91
82
  message = (
92
83
  f"You are running platform-helper v{version_status.installed}, upgrade to "
@@ -101,65 +92,14 @@ class PlatformHelperVersioning:
101
92
  except IncompatibleMinorVersionException:
102
93
  self.io.warn(message)
103
94
 
104
- def _get_version_status(
105
- self,
106
- include_project_versions: bool = True,
107
- ) -> PlatformHelperVersionStatus:
95
+ def get_version_status(self) -> VersionStatus:
108
96
  locally_installed_version = self.installed_version_provider.get_semantic_version(
109
97
  "dbt-platform-helper"
110
98
  )
111
99
 
112
100
  latest_release = self.latest_version_provider.get_semantic_version("dbt-platform-helper")
113
101
 
114
- if not include_project_versions:
115
- return PlatformHelperVersionStatus(
116
- installed=locally_installed_version,
117
- latest=latest_release,
118
- )
119
-
120
- platform_config_default, pipeline_overrides = None, {}
121
-
122
- platform_config = self.config_provider.load_unvalidated_config_file()
123
-
124
- if platform_config:
125
- platform_config_default = SemanticVersion.from_string(
126
- platform_config.get("default_versions", {}).get("platform-helper")
127
- )
128
-
129
- pipeline_overrides = {
130
- name: pipeline.get("versions", {}).get("platform-helper")
131
- for name, pipeline in platform_config.get("environment_pipelines", {}).items()
132
- if pipeline.get("versions", {}).get("platform-helper")
133
- }
134
- out = PlatformHelperVersionStatus(
135
- installed=locally_installed_version,
136
- latest=latest_release,
137
- deprecated_version_file=self.version_file_version_provider.get_semantic_version(),
138
- platform_config_default=platform_config_default,
139
- pipeline_overrides=pipeline_overrides,
140
- )
141
-
142
- return out
143
-
144
- def _resolve_required_version(
145
- self, pipeline: str = None, version_status: PlatformHelperVersionStatus = None
146
- ) -> str:
147
- pipeline_version = version_status.pipeline_overrides.get(pipeline)
148
- version_precedence = [
149
- pipeline_version,
150
- version_status.platform_config_default,
151
- version_status.deprecated_version_file,
152
- ]
153
- non_null_version_precedence = [
154
- f"{v}" if isinstance(v, SemanticVersion) else v for v in version_precedence if v
155
- ]
156
-
157
- out = non_null_version_precedence[0] if non_null_version_precedence else None
158
-
159
- if not out:
160
- raise PlatformHelperVersionNotFoundException
161
-
162
- return out
102
+ return VersionStatus(installed=locally_installed_version, latest=latest_release)
163
103
 
164
104
 
165
105
  class AWSVersioning:
@@ -29,7 +29,7 @@ class LogGroupNotFoundException(AWSException):
29
29
  super().__init__(f"""No log group called "{log_group_name}".""")
30
30
 
31
31
 
32
- # Todo: This should probably be in the AWS Copilot provider, but was causing circular import when we tried it pre refactoring the utils/aws.py
32
+ # TODO: DBTP-1976: This should probably be in the AWS Copilot provider, but was causing circular import when we tried it pre refactoring the utils/aws.py
33
33
  class CopilotCodebaseNotFoundException(PlatformException):
34
34
  def __init__(self, codebase: str):
35
35
  super().__init__(
@@ -8,7 +8,7 @@ from dbt_platform_helper.platform_exception import PlatformException
8
8
 
9
9
 
10
10
  class CloudFormation:
11
- # TODO add handling for optional client parameters to handle case of calling boto API with None
11
+ # TODO: DBTP-1966: add handling for optional client parameters to handle case of calling boto API with None
12
12
  def __init__(self, cloudformation_client, iam_client=None, ssm_client=None):
13
13
  self.cloudformation_client = cloudformation_client
14
14
  self.iam_client = iam_client