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
49 changes: 29 additions & 20 deletions src/deploy_tools/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
from .models.changes import DeploymentChanges
from .models.module import Release
from .modulefile import (
DEFAULT_VERSION_FILENAME,
apply_default_versions,
deprecate_modulefile,
restore_modulefile,
deprecate_modulefile_link,
restore_modulefile_link,
)

MODULE_VERSIONS_GLOB = f"[!{Layout.DEFAULT_VERSION_FILENAME}]*"


def deploy_changes(changes: DeploymentChanges, layout: Layout) -> None:
"""Perform the Deploy step for the specified changes."""
Expand Down Expand Up @@ -46,20 +47,19 @@
def _deploy_new_releases(to_add: list[Release], layout: Layout) -> None:
"""Deploy modules from the provided list."""
_deploy_releases(to_add, layout)
build_layout = layout.build_layout

for release in to_add:
name = release.module.name
version = release.module.version
deprecated = release.deprecated

built_modulefile = build_layout.get_built_modulefile(name, version)
modulefile_link = layout.get_modulefile(
modulefile = layout.get_modulefile(name, version)
modulefile_link = layout.get_modulefile_link(

Check warning on line 57 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L56-L57

Added lines #L56 - L57 were not covered by tests
name, version, from_deprecated=deprecated
)

modulefile_link.parent.mkdir(parents=True, exist_ok=True)
os.symlink(built_modulefile, modulefile_link)
os.symlink(modulefile, modulefile_link)

Check warning on line 62 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L62

Added line #L62 was not covered by tests


def _deploy_releases(
Expand All @@ -84,18 +84,18 @@
def _deprecate_releases(to_deprecate: list[Release], layout: Layout) -> None:
"""Deprecate a list of modules.

This will move the modulefile to a 'deprecated' directory. If the modulefile path is
set up to include the 'deprecated' directory, all modulefiles should continue to
work.
For each module, this will move the modulefile link to a 'deprecated' directory. If
the user's MODULEPATH is set up to include the 'deprecated' directory, all
modules should be available as before.
"""
for release in to_deprecate:
deprecate_modulefile(release.module.name, release.module.version, layout)
deprecate_modulefile_link(release.module.name, release.module.version, layout)

Check warning on line 92 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L92

Added line #L92 was not covered by tests


def _remove_deployed_module(
name: str, version: str, layout: Layout, from_deprecated: bool = False
) -> None:
modulefile = layout.get_modulefile(name, version, from_deprecated)
modulefile = layout.get_modulefile_link(name, version, from_deprecated)

Check warning on line 98 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L98

Added line #L98 was not covered by tests
modulefile.unlink()

_remove_module(name, version, layout)
Expand All @@ -110,7 +110,7 @@
def _restore_releases(to_restore: list[Release], layout: Layout) -> None:
"""Restore a previously deprecated module."""
for release in to_restore:
restore_modulefile(release.module.name, release.module.version, layout)
restore_modulefile_link(release.module.name, release.module.version, layout)

Check warning on line 113 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L113

Added line #L113 was not covered by tests


def _remove_name_folders(
Expand All @@ -119,25 +119,34 @@
removed: list[Release],
layout: Layout,
) -> None:
"""Remove module name folders where all versions have been removed."""
"""Remove module name folders where all versions have been removed.

Several types of path are of the form <root>/name/version. When removing version
files in operations such as deprecation, if all versions are removed the parent
folder (called name folder here) will still exist. This function is designed to
remove them.

Note that the non-deprecated modulefile name folder will not be empty, as the
default version file will still exist.
"""
for release in deprecated:
_delete_modulefile_name_folder(layout, release.module.name)
_delete_modulefiles_name_folder(layout, release.module.name)

Check warning on line 133 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L133

Added line #L133 was not covered by tests

for release in restored:
_delete_modulefile_name_folder(layout, release.module.name, True)
_delete_modulefiles_name_folder(layout, release.module.name, True)

Check warning on line 136 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L136

Added line #L136 was not covered by tests

for release in removed:
_delete_modulefile_name_folder(layout, release.module.name, True)
_delete_modulefiles_name_folder(layout, release.module.name, True)

Check warning on line 139 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L139

Added line #L139 was not covered by tests
_delete_name_folder(release.module.name, layout.modules_root)


def _delete_modulefile_name_folder(
def _delete_modulefiles_name_folder(
layout: Layout, name: str, from_deprecated: bool = False
) -> None:
modulefiles_name_path = layout.get_modulefiles_root(from_deprecated) / name
module_versions_glob = f"[!{DEFAULT_VERSION_FILENAME}]*"

if next(modulefiles_name_path.glob(module_versions_glob), None) is None:
# Ignore the default version file when checking for existing modulefile links
if next(modulefiles_name_path.glob(MODULE_VERSIONS_GLOB), None) is None:

Check warning on line 149 in src/deploy_tools/deploy.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/deploy.py#L149

Added line #L149 was not covered by tests
shutil.rmtree(modulefiles_name_path)


Expand Down
12 changes: 11 additions & 1 deletion src/deploy_tools/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
MODULEFILES_ROOT_NAME = "modulefiles"
DEPRECATED_ROOT_NAME = "deprecated"
DEFAULT_BUILD_ROOT_NAME = "build"
DEFAULT_VERSION_FILENAME = ".version"

DEPLOYMENT_SNAPSHOT_FILENAME = "deployment.yaml"

Expand All @@ -75,11 +76,20 @@
else self.modulefiles_root
)

def get_modulefile(
def get_modulefile_link(
self, name: str, version: str, from_deprecated: bool = False
) -> Path:
return self.get_modulefiles_root(from_deprecated) / name / version

def get_modulefile(self, name: str, version: str) -> Path:
return (

Check warning on line 85 in src/deploy_tools/layout.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/layout.py#L85

Added line #L85 was not covered by tests
self.get_module_folder(name, version)
/ ModuleBuildLayout.BUILT_MODULEFILE_FILENAME
)

def get_default_version_file(self, name: str) -> Path:
return self.modulefiles_root / name / self.DEFAULT_VERSION_FILENAME

Check warning on line 91 in src/deploy_tools/layout.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/layout.py#L91

Added line #L91 was not covered by tests

@property
def deployment_root(self) -> Path:
return self._root
Expand Down
21 changes: 11 additions & 10 deletions src/deploy_tools/modulefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@

type ModuleVersionsByName = dict[str, list[str]]

DEFAULT_VERSION_FILENAME = ".version"
VERSION_GLOB = f"*/[!{DEFAULT_VERSION_FILENAME}]*"
VERSION_GLOB = f"*/[!{Layout.DEFAULT_VERSION_FILENAME}]*"

DEFAULT_VERSION_REGEX = "^set ModulesVersion (.*)$"


def deprecate_modulefile(name: str, version: str, layout: Layout) -> None:
def deprecate_modulefile_link(name: str, version: str, layout: Layout) -> None:
_move_modulefile_link(
name,
version,
Expand All @@ -23,7 +22,7 @@
)


def restore_modulefile(name: str, version: str, layout: Layout) -> None:
def restore_modulefile_link(name: str, version: str, layout: Layout) -> None:
_move_modulefile_link(
name,
version,
Expand Down Expand Up @@ -58,13 +57,15 @@
def is_modulefile_deployed(
name: str, version: str, layout: Layout, in_deprecated: bool = False
) -> bool:
modulefile = layout.get_modulefile(name, version, from_deprecated=in_deprecated)
return modulefile.exists()
modulefile_link = layout.get_modulefile_link(

Check warning on line 60 in src/deploy_tools/modulefile.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/modulefile.py#L60

Added line #L60 was not covered by tests
name, version, from_deprecated=in_deprecated
)
return modulefile_link.exists()

Check warning on line 63 in src/deploy_tools/modulefile.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/modulefile.py#L63

Added line #L63 was not covered by tests


def get_default_modulefile_version(name: str, layout: Layout) -> str | None:
version_regex = re.compile(DEFAULT_VERSION_REGEX)
default_version_file = layout.modulefiles_root / name / DEFAULT_VERSION_FILENAME
default_version_file = layout.get_default_version_file(name)

Check warning on line 68 in src/deploy_tools/modulefile.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/modulefile.py#L68

Added line #L68 was not covered by tests

with open(default_version_file) as f:
for line in f.readlines():
Expand All @@ -81,16 +82,16 @@
deployed_module_versions = get_deployed_modulefile_versions(layout)

for name in deployed_module_versions:
version_file = layout.modulefiles_root / name / DEFAULT_VERSION_FILENAME
default_version_file = layout.get_default_version_file(name)

Check warning on line 85 in src/deploy_tools/modulefile.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/modulefile.py#L85

Added line #L85 was not covered by tests

if name in default_versions:
params = {"version": default_versions[name]}

templater.create(
version_file,
default_version_file,
TemplateType.MODULEFILE_VERSION,
params,
overwrite=True,
)
else:
version_file.unlink(missing_ok=True)
default_version_file.unlink(missing_ok=True)

Check warning on line 97 in src/deploy_tools/modulefile.py

View check run for this annotation

Codecov / codecov/patch

src/deploy_tools/modulefile.py#L97

Added line #L97 was not covered by tests
File renamed without changes.
2 changes: 1 addition & 1 deletion src/deploy_tools/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

from .build import build
from .check_deploy import check_deploy_can_run
from .display import print_updates
from .layout import Layout
from .models.changes import DeploymentChanges, ReleaseChanges
from .models.deployment import (
Expand All @@ -18,6 +17,7 @@
from .modulefile import (
ModuleVersionsByName,
)
from .print_updates import print_updates
from .snapshot import load_snapshot


Expand Down