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
717 changes: 357 additions & 360 deletions poetry.lock

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ packages = [{include = "gardenlinux", from="src"}]

[tool.poetry.dependencies]
python = "^3.13"
networkx = "^3.3"
PyYAML = "^6.0.2"
pytest = "^8.3.2"
gitpython = "^3.1.44"
apt-repo = "^0.5"
jsonschema = "^4.23.0"
oras = "^0.2.33"
python-dotenv = "^1.0.1"
cryptography = "^45.0.4"
boto3 = "*"
click = "^8.2.0"
pygments = "^2.19.1"
boto3 = "^1.40.10"
click = "^8.2.1"
cryptography = "^45.0.6"
gitpython = "^3.1.45"
jsonschema = "^4.25.0"
networkx = "^3.5"
oras = "^0.2.37"
pygments = "^2.19.2"
PyYAML = "^6.0.2"

[tool.poetry.group.dev.dependencies]
bandit = "^1.8.3"
bandit = "^1.8.6"
black = "^25.1.0"
moto = "^5.1.9"
moto = "^5.1.10"
python-dotenv = "^1.1.1"
pytest = "^8.4.1"
pytest-cov = "^6.2.1"

Expand Down
26 changes: 18 additions & 8 deletions src/gardenlinux/features/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
_ARGS_TYPE_ALLOWED = [
"cname",
"cname_base",
"commit_id",
"features",
"platforms",
"flags",
"elements",
"arch",
"version",
"version_and_commit_id",
"graph",
]

Expand All @@ -41,10 +43,11 @@ def main() -> None:
parser = argparse.ArgumentParser()

parser.add_argument("--arch", dest="arch")
parser.add_argument("--cname", dest="cname")
parser.add_argument("--commit", dest="commit")
parser.add_argument("--feature-dir", default="features")
parser.add_argument("--cname")
parser.add_argument("--default-arch")
parser.add_argument("--default-version")
parser.add_argument("--default-arch", dest="default_arch")
parser.add_argument("--default-version", dest="default_version")
parser.add_argument("--version", dest="version")

parser.add_argument(
Expand All @@ -68,7 +71,7 @@ def main() -> None:

arch = args.arch
flavor = None
commit_id = None
commit_id = args.commit
gardenlinux_root = path.dirname(args.feature_dir)
version = args.version

Expand All @@ -80,8 +83,7 @@ def main() -> None:

if version is None or version == "":
try:
version_data = get_version_and_commit_id_from_files(gardenlinux_root)
version = f"{version_data[0]}-{version_data[1]}"
version, commit_id = get_version_and_commit_id_from_files(gardenlinux_root)
except RuntimeError as exc:
logging.debug(
"Failed to parse version information for GL root '{0}': {1}".format(
Expand All @@ -92,7 +94,7 @@ def main() -> None:
version = args.default_version

if args.cname:
cname = CName(args.cname, arch=arch, version=version)
cname = CName(args.cname, arch=arch, commit_id=commit_id, version=version)

arch = cname.arch
flavor = cname.flavor
Expand All @@ -108,7 +110,11 @@ def main() -> None:
"Architecture could not be determined and no default architecture set"
)

if version is None or version == "" and (args.type in ("cname", "version")):
if (
version is None
or version == ""
and (args.type in ("cname", "commit_id", "version", "version_and_commit_id"))
):
raise RuntimeError("Version not specified and no default version set")

feature_dir_name = path.basename(args.feature_dir)
Expand Down Expand Up @@ -160,7 +166,11 @@ def main() -> None:
print(",".join(features_by_type["element"]))
elif args.type == "flags":
print(",".join(features_by_type["flag"]))
elif args.type == "commit_id":
print(commit_id)
elif args.type == "version":
print(version)
elif args.type == "version_and_commit_id":
print(f"{version}-{commit_id}")


Expand Down
22 changes: 14 additions & 8 deletions src/gardenlinux/features/cname.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ class CName(object):
Apache License, Version 2.0
"""

def __init__(self, cname, arch=None, version=None):
def __init__(self, cname, arch=None, commit_id=None, version=None):
"""
Constructor __init__(CName)

:param cname: Canonical name to represent
:param arch: Architecture if not part of cname
:param version: Version if not part of cname
:param cname: Canonical name to represent
:param arch: Architecture if not part of cname
:param commit_id: Commit ID if not part of cname
:param version: Version if not part of cname

:since: 0.7.0
"""
Expand Down Expand Up @@ -64,11 +65,16 @@ def __init__(self, cname, arch=None, version=None):
self._arch = arch

if self._version is None and version is not None:
re_match = re.match("([a-z0-9.]+)(-([a-z0-9]+))?$", version)
assert re_match, f"Not a valid version {version}"
# Support version values formatted as <version>-<commit_id>
if commit_id is None:
re_match = re.match("([a-z0-9.]+)(-([a-z0-9]+))?$", version)
assert re_match, f"Not a valid version {version}"

self._commit_id = re_match[3]
self._version = re_match[1]
self._commit_id = re_match[3]
self._version = re_match[1]
else:
self._commit_id = commit_id
self._version = version

@property
def arch(self) -> Optional[str]:
Expand Down
7 changes: 4 additions & 3 deletions src/gardenlinux/features/cname_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def main():
parser = argparse.ArgumentParser()

parser.add_argument("--arch", dest="arch")
parser.add_argument("--commit", dest="commit")
parser.add_argument("--feature-dir", default="features")
parser.add_argument("--version", dest="version")
parser.add_argument("cname")
Expand All @@ -46,6 +47,7 @@ def main():
assert re_match, f"Not a valid GardenLinux canonical name {args.cname}"

arch = args.arch
commit_id = args.commit
gardenlinux_root = dirname(args.feature_dir)
version = args.version

Expand All @@ -54,16 +56,15 @@ def main():

if not version:
try:
version_data = get_version_and_commit_id_from_files(gardenlinux_root)
version = f"{version_data[0]}-{version_data[1]}"
version, commit_id = get_version_and_commit_id_from_files(gardenlinux_root)
except RuntimeError as exc:
logging.warning(
"Failed to parse version information for GL root '{0}': {1}".format(
gardenlinux_root, exc
)
)

cname = CName(args.cname, arch=arch, version=version)
cname = CName(args.cname, arch=arch, commit_id=commit_id, version=version)

assert cname.arch, "Architecture could not be determined"

Expand Down
38 changes: 3 additions & 35 deletions tests/features/test_cname_main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import sys
import types
import logging
import pytest
import sys
import types

import gardenlinux.features.cname_main as cname_main
from gardenlinux.features import CName


def test_main_happy(monkeypatch, capsys):
Expand All @@ -14,14 +15,6 @@ def test_main_happy(monkeypatch, capsys):
argv = ["prog", "--arch", "amd64", "--version", "1.0-abc123", "flav-amd64"]
monkeypatch.setattr(sys, "argv", argv)

class FakeCName:
def __init__(self, cname, arch=None, version=None):
self.arch = arch
self.flavor = "flav"
self.version_and_commit_id = "1.0-abc123"

monkeypatch.setattr(cname_main, "CName", FakeCName)

class FakeGraph:
in_degree = lambda self: [("f1", 0)]
edges = [("f1", "f2")]
Expand Down Expand Up @@ -62,14 +55,6 @@ def test_main_version_from_file(monkeypatch, capsys):
lambda root: ("2.0", "abcdef12"),
)

class FakeCName:
def __init__(self, cname, arch=None, version=None):
self.arch = arch
self.flavor = "flav"
self.version_and_commit_id = version

monkeypatch.setattr(cname_main, "CName", FakeCName)

class FakeParser:
def __init__(self, *a, **k):
pass
Expand Down Expand Up @@ -110,15 +95,6 @@ def raise_runtime(_):
cname_main, "get_version_and_commit_id_from_files", raise_runtime
)

# Patch CName to control attributes
class FakeCName:
def __init__(self, cname, arch=None, version=None):
self.arch = arch
self.flavor = "flav"
self.version_and_commit_id = version

monkeypatch.setattr(cname_main, "CName", FakeCName)

# Patch Parser for minimal valid graph
class FakeParser:
def __init__(self, *a, **k):
Expand Down Expand Up @@ -165,14 +141,6 @@ def test_cname_main_missing_arch_in_cname_raises(monkeypatch):
argv = ["prog", "--version", "1.0", "flav"]
monkeypatch.setattr(sys, "argv", argv)

class FakeCName:
def __init__(self, cname, arch=None, version=None):
self.arch = None # Force missing arch
self.flavor = "flav"
self.version_and_commit_id = "1.0-abc"

monkeypatch.setattr(cname_main, "CName", FakeCName)

# Act / Assert
with pytest.raises(AssertionError):
cname_main.main()
53 changes: 43 additions & 10 deletions tests/features/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,27 @@ def test_main_prints_arch(monkeypatch, capsys):
assert "amd64" in out


def test_main_prints_commit_id(monkeypatch, capsys):
# Arrange
argv = ["prog", "--arch", "amd64", "--features", "f1", "commit_id"]
monkeypatch.setattr(sys, "argv", argv)
monkeypatch.setattr(
fema,
"Parser",
lambda *a, **kw: types.SimpleNamespace(filter=lambda *a, **k: None),
)
# Patch get_version_and_commit_id_from_files
monkeypatch.setattr(
fema, "get_version_and_commit_id_from_files", lambda root: ("1.2.3", "abcdef12")
)

# Act
fema.main()

captured = capsys.readouterr()
assert "abcdef12" == captured.out.strip()


def test_main_prints_flags_elements_platforms(monkeypatch, capsys):
# Arrange
argv = [
Expand Down Expand Up @@ -186,7 +207,28 @@ def test_main_prints_version(monkeypatch, capsys):
fema.main()

captured = capsys.readouterr()
assert "1.2.3-abcdef12" in captured.out
assert "1.2.3" == captured.out.strip()


def test_main_prints_version_and_commit_id(monkeypatch, capsys):
# Arrange
argv = ["prog", "--arch", "amd64", "--features", "f1", "version_and_commit_id"]
monkeypatch.setattr(sys, "argv", argv)
monkeypatch.setattr(
fema,
"Parser",
lambda *a, **kw: types.SimpleNamespace(filter=lambda *a, **k: None),
)
# Patch get_version_and_commit_id_from_files
monkeypatch.setattr(
fema, "get_version_and_commit_id_from_files", lambda root: ("1.2.3", "abcdef12")
)

# Act
fema.main()

captured = capsys.readouterr()
assert "1.2.3-abcdef12" == captured.out.strip()


def test_main_arch_raises_missing_verison(monkeypatch, capsys):
Expand All @@ -202,15 +244,6 @@ def test_main_arch_raises_missing_verison(monkeypatch, capsys):

def test_main_with_cname_print_cname(monkeypatch, capsys):
# Arrange
class FakeCName:
def __init__(self, cname, arch=None, version=None):
self.arch = arch
self.flavor = "flav"
self.commit_id = "abc123"
self.version = version

monkeypatch.setattr(fema, "CName", FakeCName)

class FakeGraph:
def in_degree(self):
# Simulate a graph where one feature has no dependencies
Expand Down