Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "1.0"
description: Minimal shell-only module with a single shell application

applications:
- app_type: shell

name: test-shell-echo
script:
- echo hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions:
example-module-shell: "2.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "1.0"
description: Minimal shell-only module with a single shell application

applications:
- app_type: shell

name: test-shell-echo
script:
- echo hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "2.0"
description: Minimal shell-only module with a single shell application

applications:
- app_type: shell

name: test-shell-echo
script:
- echo hello

deprecated: true
3 changes: 3 additions & 0 deletions tests/configs/invalid/deprecated-on-creation/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "1.0"
description: Module whose shell script is not valid bash

applications:
- app_type: shell

name: test-shell-echo
# 'fi' with no matching 'if' is invalid bash, so `validate --test-build` must
# reject the generated entrypoint when it runs `bash -n` over it.
script:
- fi
3 changes: 3 additions & 0 deletions tests/configs/invalid/invalid-shell-script/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "1.0"
description: Minimal shell-only module with a single shell application

applications:
- app_type: shell

name: test-shell-echo
# Differs from the valid/minimal baseline (echo hello) so that deploying this over
# it is an in-place modification, rejected without allow_updates / a version bump.
script:
- echo modified
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "1.0"
description: Shell module excluded from defaults with no eligible fallback

applications:
- app_type: shell

name: test-shell-echo
script:
- echo hello

exclude_from_defaults: true
3 changes: 3 additions & 0 deletions tests/configs/invalid/no-eligible-default/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-base
version: "1.0"
description: Base module that the dependent module references

applications: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-dependent
version: "1.0"
description: References a version of example-module-base that does not exist

dependencies:
- name: example-module-base
version: "9.9"

applications: []
3 changes: 3 additions & 0 deletions tests/configs/invalid/unknown-dependency/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
13 changes: 13 additions & 0 deletions tests/configs/valid/minimal/example-module-shell/1.0.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/release.json

module:
name: example-module-shell
version: "1.0"
description: Minimal shell-only module with a single shell application

applications:
- app_type: shell

name: test-shell-echo
script:
- echo hello
3 changes: 3 additions & 0 deletions tests/configs/valid/minimal/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# yaml-language-server: $schema=/workspaces/deploy-tools/src/deploy_tools/models/schemas/deployment-settings.json

default_versions: {}
127 changes: 127 additions & 0 deletions tests/test_default_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Unit tests for default-version selection.

These call the function directly rather than through the CLI. Here that is to isolate
pure, non-trivial logic (e.g. natsort ordering of non-SemVer versions).
"""

from collections import defaultdict

import pytest

from deploy_tools.models.deployment import (
Deployment,
DeploymentSettings,
ReleasesByNameAndVersion,
)
from deploy_tools.models.module import Module, Release
from deploy_tools.validate import ValidationError, validate_default_versions


def _release(
name: str, version: str, *, deprecated: bool = False, excluded: bool = False
) -> Release:
"""Build a minimal Release with no applications, for selection tests."""
return Release(
module=Module(
name=name,
version=version,
applications=[],
exclude_from_defaults=excluded,
),
deprecated=deprecated,
)


def _deployment(
*releases: Release, default_versions: dict[str, str] | None = None
) -> Deployment:
"""Assemble a Deployment from loose Releases and optional explicit defaults."""
by_name: ReleasesByNameAndVersion = defaultdict(dict)
for release in releases:
by_name[release.module.name][release.module.version] = release

return Deployment(
settings=DeploymentSettings(default_versions=default_versions or {}),
releases=by_name,
)


def test_auto_selects_latest_version_by_natsort() -> None:
# natsort, not string ordering: "10.0" must beat "2.0" (which sorts last lexically).
deployment = _deployment(
_release("mod", "1.0"),
_release("mod", "2.0"),
_release("mod", "10.0"),
)
assert validate_default_versions(deployment) == {"mod": "10.0"}


def test_prerelease_sorts_before_final_release() -> None:
# The documented non-SemVer case: "1.2rc1" must come before "1.2", so the final
# release is chosen as default over its own release candidate.
deployment = _deployment(
_release("mod", "1.2rc1"),
_release("mod", "1.2"),
)
Comment thread
ptsOSL marked this conversation as resolved.
assert validate_default_versions(deployment) == {"mod": "1.2"}


def test_excluded_versions_are_not_auto_selected() -> None:
# The highest version opts out of defaults, so the next-highest is chosen instead.
deployment = _deployment(
_release("mod", "1.0"),
_release("mod", "2.0", excluded=True),
)
assert validate_default_versions(deployment) == {"mod": "1.0"}


def test_deprecated_versions_are_not_auto_selected() -> None:
# Deprecated releases are excluded from the deployed set, so a higher deprecated
# version must not become the default over a lower active one.
deployment = _deployment(
_release("mod", "1.0"),
_release("mod", "2.0", deprecated=True),
)
assert validate_default_versions(deployment) == {"mod": "1.0"}


def test_explicit_default_is_preserved_over_auto_selection() -> None:
# An explicit default wins even when a higher version exists.
deployment = _deployment(
_release("mod", "1.0"),
_release("mod", "2.0"),
default_versions={"mod": "1.0"},
)
assert validate_default_versions(deployment) == {"mod": "1.0"}


def test_explicit_default_for_nonexistent_version_raises() -> None:
# Pointing the default at a version that will not be deployed is rejected.
deployment = _deployment(
_release("mod", "1.0"),
default_versions={"mod": "9.9"},
)
with pytest.raises(ValidationError, match="Unable to configure mod/9.9 as default"):
validate_default_versions(deployment)


def test_explicit_default_for_deprecated_version_raises() -> None:
# A deprecated version is not in the deployed set, so it cannot be an explicit
# default either.
deployment = _deployment(
_release("mod", "1.0", deprecated=True),
default_versions={"mod": "1.0"},
)
with pytest.raises(ValidationError, match="Unable to configure mod/1.0 as default"):
validate_default_versions(deployment)


def test_all_versions_excluded_raises() -> None:
# With every version opting out and no explicit default, there is no eligible
# version to make default.
deployment = _deployment(_release("mod", "1.0", excluded=True))
with pytest.raises(
ValidationError,
match="every version for name: mod has set exclude_from_defaults",
):
validate_default_versions(deployment)
Loading
Loading