snakemake-software-deployment-plugin-container 0.6.3__tar.gz → 0.7.2__tar.gz
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.
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/CHANGELOG.md +21 -0
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/PKG-INFO +3 -3
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/pyproject.toml +3 -3
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/src/snakemake_software_deployment_plugin_container/__init__.py +85 -2
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/tests/test_plugin.py +10 -1
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/.github/workflows/ci.yml +0 -0
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/.github/workflows/conventional-prs.yml +0 -0
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/.github/workflows/release-please.yml +0 -0
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/.gitignore +0 -0
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/LICENSE +0 -0
- {snakemake_software_deployment_plugin_container-0.6.3 → snakemake_software_deployment_plugin_container-0.7.2}/README.md +0 -0
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.2](https://github.com/snakemake/snakemake-software-deployment-plugin-container/compare/v0.7.1...v0.7.2) (2026-09-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Performance Improvements
|
|
7
|
+
|
|
8
|
+
* explicit handling of deployment ([#25](https://github.com/snakemake/snakemake-software-deployment-plugin-container/issues/25)) ([127dff9](https://github.com/snakemake/snakemake-software-deployment-plugin-container/commit/127dff9b49f81a0fd55504676e1385b1dea977f7))
|
|
9
|
+
|
|
10
|
+
## [0.7.1](https://github.com/snakemake/snakemake-software-deployment-plugin-container/compare/v0.7.0...v0.7.1) (2026-09-07)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* bump twine ([6a5fcdf](https://github.com/snakemake/snakemake-software-deployment-plugin-container/commit/6a5fcdf33ff93101266551449e090f3a13d569b7))
|
|
16
|
+
|
|
17
|
+
## [0.7.0](https://github.com/snakemake/snakemake-software-deployment-plugin-container/compare/v0.6.3...v0.7.0) (2026-09-07)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* auto-pass workflow environment variables into container ([#21](https://github.com/snakemake/snakemake-software-deployment-plugin-container/issues/21)) ([3083669](https://github.com/snakemake/snakemake-software-deployment-plugin-container/commit/3083669e9e250053508099d26cfef93ec4fa8432))
|
|
23
|
+
|
|
3
24
|
## [0.6.3](https://github.com/snakemake/snakemake-software-deployment-plugin-container/compare/v0.6.2...v0.6.3) (2026-07-24)
|
|
4
25
|
|
|
5
26
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: snakemake-software-deployment-plugin-container
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Project-URL: repository, https://github.com/snakemake/snakemake-software-deployment-plugin-container
|
|
5
5
|
Project-URL: documentation, https://snakemake.github.io/snakemake-plugin-catalog/plugins/software-deployment/container.html
|
|
6
6
|
Author-email: Ben Carrillo <ben.uzh@pm.me>, Johannes Köster <johannes.koester@uni-due.de>
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Python: <4.0,>=3.11
|
|
9
9
|
Requires-Dist: snakemake-interface-common<2.0.0,>=1.23.0
|
|
10
|
-
Requires-Dist: snakemake-interface-software-deployment-plugins<1.0,>=0.
|
|
10
|
+
Requires-Dist: snakemake-interface-software-deployment-plugins<1.0,>=0.19.2
|
|
11
11
|
Requires-Dist: udocker<2.0.0,>=1.3.17
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "snakemake-software-deployment-plugin-container"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.2"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name = "Ben Carrillo", email = "ben.uzh@pm.me" },
|
|
6
6
|
{ name = "Johannes Köster", email = "johannes.koester@uni-due.de" }
|
|
@@ -10,7 +10,7 @@ readme = "README.md"
|
|
|
10
10
|
requires-python = ">=3.11,<4.0"
|
|
11
11
|
dependencies = [
|
|
12
12
|
"snakemake-interface-common (>=1.23.0,<2.0.0)",
|
|
13
|
-
"snakemake-interface-software-deployment-plugins (>=0.
|
|
13
|
+
"snakemake-interface-software-deployment-plugins (>=0.19.2,<1.0)",
|
|
14
14
|
"udocker (>=1.3.17,<2.0.0)",
|
|
15
15
|
]
|
|
16
16
|
|
|
@@ -63,7 +63,7 @@ exclude_lines = ["pass", "\\.\\.\\."]
|
|
|
63
63
|
fail_under = 86.0
|
|
64
64
|
|
|
65
65
|
[tool.pixi.feature.publish.pypi-dependencies]
|
|
66
|
-
twine = ">=
|
|
66
|
+
twine = ">=7.0,<8"
|
|
67
67
|
build = ">=1.2.2,<2"
|
|
68
68
|
|
|
69
69
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from snakemake_interface_software_deployment_plugins import DeployableEnvBase
|
|
1
4
|
import re
|
|
2
5
|
|
|
3
6
|
__author__ = "ben carrillo"
|
|
@@ -91,7 +94,7 @@ class EnvSpec(EnvSpecBase):
|
|
|
91
94
|
|
|
92
95
|
|
|
93
96
|
# All errors should be wrapped with snakemake-interface-common.errors.WorkflowError
|
|
94
|
-
class Env(EnvBase):
|
|
97
|
+
class Env(DeployableEnvBase, EnvBase):
|
|
95
98
|
# image_repo is the de-referenced repository from where the image was obtained
|
|
96
99
|
image_repo: str
|
|
97
100
|
settings: Settings
|
|
@@ -159,11 +162,62 @@ class Env(EnvBase):
|
|
|
159
162
|
# Return an empty tuple () if no software can be reported.
|
|
160
163
|
return [SoftwareReport(name=self.spec.image_uri)]
|
|
161
164
|
|
|
165
|
+
def is_deployment_path_portable(self) -> bool:
|
|
166
|
+
"""Return whether the deployment path matters for the environment, i.e.
|
|
167
|
+
whether the environment is portable. If this returns False, the deployment
|
|
168
|
+
path is considered for the deployment hash. For example, conda environments are not
|
|
169
|
+
portable because they hardcode the path in binaries, while containers are
|
|
170
|
+
portable.
|
|
171
|
+
"""
|
|
172
|
+
return True
|
|
173
|
+
|
|
174
|
+
async def deploy(self) -> None:
|
|
175
|
+
"""Deploy the environment to self.deployment_path.
|
|
176
|
+
|
|
177
|
+
When issuing shell commands, the environment should use
|
|
178
|
+
self.run_cmd(cmd: str) in order to ensure that it runs within eventual
|
|
179
|
+
parent environments (e.g. a container or an env module).
|
|
180
|
+
"""
|
|
181
|
+
deploy_cmd = self.runtime_manager.deploy_cmd()
|
|
182
|
+
assert deploy_cmd is not None
|
|
183
|
+
self.deployment_path.mkdir(parents=True, exist_ok=True)
|
|
184
|
+
self.run_cmd(
|
|
185
|
+
deploy_cmd,
|
|
186
|
+
check=True,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
def remove(self) -> None:
|
|
190
|
+
"""Remove the deployed environment."""
|
|
191
|
+
if (
|
|
192
|
+
self.is_deployable()
|
|
193
|
+
and self.runtime_manager.deployed_image_path() is not None
|
|
194
|
+
):
|
|
195
|
+
self.runtime_manager.deployed_image_path.unlink(missing_ok=True)
|
|
196
|
+
|
|
197
|
+
def is_deployable(self) -> bool:
|
|
198
|
+
return (
|
|
199
|
+
self.settings.runtime is Runtime.UDOCKER
|
|
200
|
+
or self.settings.runtime is Runtime.APPTAINER
|
|
201
|
+
)
|
|
202
|
+
|
|
162
203
|
|
|
163
204
|
@dataclass
|
|
164
205
|
class RuntimeManager:
|
|
165
206
|
env: Env
|
|
166
207
|
|
|
208
|
+
def deployed_image_name(self) -> str:
|
|
209
|
+
return (
|
|
210
|
+
self.env.spec.image_uri.replace("/", "_")
|
|
211
|
+
.replace(":", "_")
|
|
212
|
+
.replace("#", "_")
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@abstractmethod
|
|
216
|
+
def deployed_image_path(self) -> Path | None: ...
|
|
217
|
+
|
|
218
|
+
@abstractmethod
|
|
219
|
+
def deploy_cmd(self) -> str | None: ...
|
|
220
|
+
|
|
167
221
|
def options(self) -> str:
|
|
168
222
|
return "--rm"
|
|
169
223
|
|
|
@@ -217,7 +271,11 @@ class RuntimeManagerApptainer(RuntimeManager):
|
|
|
217
271
|
return "exec"
|
|
218
272
|
|
|
219
273
|
def options(self) -> str:
|
|
220
|
-
|
|
274
|
+
options = ""
|
|
275
|
+
envvars = [f"{env_var}={os.environ[env_var]}" for env_var in self.env.envvars]
|
|
276
|
+
if envvars:
|
|
277
|
+
options += f" --env {','.join(envvars)}"
|
|
278
|
+
return options
|
|
221
279
|
|
|
222
280
|
def workdir_option(self) -> str:
|
|
223
281
|
return "--cwd"
|
|
@@ -230,6 +288,14 @@ class RuntimeManagerApptainer(RuntimeManager):
|
|
|
230
288
|
return super().image_uri()
|
|
231
289
|
return f"docker://{super().image_uri()}"
|
|
232
290
|
|
|
291
|
+
def deployed_image_path(self) -> Path | None:
|
|
292
|
+
return (self.env.deployment_path / self.deployed_image_name()).with_suffix(
|
|
293
|
+
".sif"
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
def deploy_cmd(self) -> str | None:
|
|
297
|
+
return f"apptainer pull {self.deployed_image_path()} {self.image_uri()}"
|
|
298
|
+
|
|
233
299
|
|
|
234
300
|
class RuntimeManagerDocker(RuntimeManager):
|
|
235
301
|
def options(self) -> str:
|
|
@@ -240,11 +306,28 @@ class RuntimeManagerDocker(RuntimeManager):
|
|
|
240
306
|
uid = os.getuid()
|
|
241
307
|
gid = os.getgid()
|
|
242
308
|
options += f" --user {uid}:{gid}"
|
|
309
|
+
for env_var in self.env.envvars:
|
|
310
|
+
options += f" --env {env_var}"
|
|
243
311
|
return options
|
|
244
312
|
|
|
313
|
+
def deployed_image_path(self) -> Path | None:
|
|
314
|
+
return None
|
|
315
|
+
|
|
316
|
+
def deploy_cmd(self) -> str | None:
|
|
317
|
+
# No need to deploy anything in docker, the daemon handles that on the fly.
|
|
318
|
+
return None
|
|
319
|
+
|
|
245
320
|
|
|
246
321
|
class RuntimeManagerUdocker(RuntimeManager):
|
|
247
322
|
def options(self) -> str:
|
|
248
323
|
options = super().options()
|
|
249
324
|
options += " --nobanner --env TINI_SUBREAPER=1"
|
|
325
|
+
for env_var in self.env.envvars:
|
|
326
|
+
options += f" --env {env_var}={os.environ[env_var]}"
|
|
250
327
|
return options
|
|
328
|
+
|
|
329
|
+
def deployed_image_path(self) -> Path | None:
|
|
330
|
+
return None
|
|
331
|
+
|
|
332
|
+
def deploy_cmd(self) -> str | None:
|
|
333
|
+
return f"UDOCKER_DIR={self.env.deployment_path} udocker pull {self.image_uri()}"
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
from collections.abc import Set
|
|
1
2
|
from typing import Optional, Type
|
|
3
|
+
import shutil
|
|
4
|
+
import os
|
|
2
5
|
|
|
3
6
|
import pytest
|
|
4
|
-
import shutil
|
|
5
7
|
|
|
6
8
|
from snakemake_interface_software_deployment_plugins.tests import (
|
|
7
9
|
TestSoftwareDeploymentBase,
|
|
@@ -22,6 +24,10 @@ from snakemake_software_deployment_plugin_container import (
|
|
|
22
24
|
)
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
os.environ["TESTVAR1"] = "testvalue"
|
|
28
|
+
os.environ["TESTVAR2"] = "testvalue2"
|
|
29
|
+
|
|
30
|
+
|
|
25
31
|
class TestBase(TestSoftwareDeploymentBase):
|
|
26
32
|
test_container = "quay.io/biocontainers/samtools:1.23.1--ha83d96e_0"
|
|
27
33
|
|
|
@@ -47,6 +53,9 @@ class TestBase(TestSoftwareDeploymentBase):
|
|
|
47
53
|
# with exit code 0 (i.e. without error).
|
|
48
54
|
return "samtools --version"
|
|
49
55
|
|
|
56
|
+
def get_envvars(self) -> Set[str]:
|
|
57
|
+
return {"TESTVAR1", "TESTVAR2"}
|
|
58
|
+
|
|
50
59
|
|
|
51
60
|
class TestApptainerContainer(TestBase):
|
|
52
61
|
__test__ = True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|