Compare commits

...
4 Commits
Author SHA1 Message Date
devx-ci-bot 5384269c83 release: v0.8.2 [skip ci] 2026-06-23 21:44:03 +02:00
emil b3d0dd8ca7 DEVX-15: fix: encode spaces in pair commands to survive shell word-splitting
Post-merge / detect-type (push) Successful in 15s
Post-merge / validate-commit-msg (push) Successful in 10s
Post-merge / vikunja (push) Successful in 31s
Post-merge / sync-wiki (push) Successful in 47s
Post-merge / badges (push) Successful in 1m3s
Post-merge / configure-repo (push) Successful in 15s
Post-merge / release (push) Successful in 47s
2026-06-23 19:42:56 +00:00
devx-ci-bot a7dcaee5c6 release: v0.8.1 [skip ci] 2026-06-23 20:45:02 +02:00
emil 02f8d3757b DEVX-14: fix: set fresh MOLECULE_HOME per pair to avoid stale config cache
Post-merge / detect-type (push) Successful in 14s
Post-merge / validate-commit-msg (push) Successful in 10s
Post-merge / configure-repo (push) Successful in 20s
Post-merge / sync-wiki (push) Successful in 58s
Post-merge / badges (push) Successful in 1m6s
Post-merge / release (push) Successful in 48s
Post-merge / vikunja (push) Successful in 21s
2026-06-23 18:43:58 +00:00
5 changed files with 30 additions and 10 deletions
+1 -1
View File
@@ -1 +1 @@
DEVX-14
DEVX-15
+12
View File
@@ -2,6 +2,18 @@
All notable changes to this project will be documented in this file.
## [0.8.2] - 2026-06-23
### Bug Fixes
- Encode spaces in pair commands to survive shell word-splitting
## [0.8.1] - 2026-06-23
### Bug Fixes
- Set fresh MOLECULE_HOME per pair to avoid stale config cache
## [0.8.0] - 2026-06-23
### Features
+1 -1
View File
@@ -1,3 +1,3 @@
"""devx — reusable development and CI/CD tools for oblachno-oss projects."""
__version__ = "0.8.0"
__version__ = "0.8.2"
+6 -6
View File
@@ -41,7 +41,8 @@ class TestPair:
def encode(self) -> str:
"""Serialize to a pipe-delimited string for CI consumption."""
return f"{self.scenario}|{self.platform['name']}|{self.platform['image']}|{self.platform['command']}"
cmd = self.platform["command"].replace(" ", "__SPACE__")
return f"{self.scenario}|{self.platform['name']}|{self.platform['image']}|{cmd}"
@staticmethod
def decode(encoded: str) -> TestPair:
@@ -49,7 +50,7 @@ class TestPair:
parts = encoded.split("|")
return TestPair(
scenario=parts[0],
platform={"name": parts[1], "image": parts[2], "command": parts[3]},
platform={"name": parts[1], "image": parts[2], "command": parts[3].replace("__SPACE__", " ")},
)
@@ -63,9 +64,8 @@ class MultiRoleTestPair:
def encode(self) -> str:
"""Serialize to a pipe-delimited string: ``role|scenario|platform_name|image|command``."""
return (
f"{self.role}|{self.scenario}|{self.platform['name']}|{self.platform['image']}|{self.platform['command']}"
)
cmd = self.platform["command"].replace(" ", "__SPACE__")
return f"{self.role}|{self.scenario}|{self.platform['name']}|{self.platform['image']}|{cmd}"
@staticmethod
def decode(encoded: str) -> MultiRoleTestPair:
@@ -74,7 +74,7 @@ class MultiRoleTestPair:
return MultiRoleTestPair(
role=parts[0],
scenario=parts[1],
platform={"name": parts[2], "image": parts[3], "command": parts[4]},
platform={"name": parts[2], "image": parts[3], "command": parts[4].replace("__SPACE__", " ")},
)
+10 -2
View File
@@ -114,12 +114,14 @@ def parse_pair(pair: str) -> tuple[str, str, str, str, str]:
Supports both 4-part (single-role) and 5-part (multi-role) formats.
For 4-part pairs, role is empty (caller uses default role dir).
Spaces in the command field are encoded as ``__SPACE__`` to survive
shell word-splitting when ``$TEST_PAIRS`` is expanded unquoted.
"""
parts = pair.split("|")
if len(parts) == 4:
return "", parts[0], parts[1], parts[2], parts[3]
return "", parts[0], parts[1], parts[2], parts[3].replace("__SPACE__", " ")
if len(parts) == 5:
return parts[0], parts[1], parts[2], parts[3], parts[4]
return parts[0], parts[1], parts[2], parts[3], parts[4].replace("__SPACE__", " ")
raise click.ClickException(f"Invalid pair format: {pair!r} (expected 4 or 5 pipe-delimited parts)")
@@ -134,6 +136,12 @@ def build_env_for_pair(pair: str, base_env: dict[str, str]) -> dict[str, str]:
elif "MOLECULE_PLATFORM_COMMAND" in env:
del env["MOLECULE_PLATFORM_COMMAND"]
env["ANSIBLE_ALLOW_BROKEN_CONDITIONALS"] = "true"
# Use a fresh MOLECULE_HOME per pair to avoid stale config cache
# from previous CI runs (causes "Instances missing" errors).
if "MOLECULE_HOME" not in env:
import tempfile
env["MOLECULE_HOME"] = tempfile.mkdtemp(prefix="molecule-ci-")
return env