Skip to content

Commit 7e2f553

Browse files
committed
Enhance handling of flavors.yaml checked out from GitHub
Signed-off-by: Tobias Wolf <[email protected]>
1 parent 563027c commit 7e2f553

File tree

5 files changed

+87
-74
lines changed

5 files changed

+87
-74
lines changed

src/gardenlinux/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
"secureboot.aws-efivars": "application/io.gardenlinux.cert.secureboot.aws-efivars",
141141
}
142142

143+
GL_REPOSITORY_URL = "https://github.com/gardenlinux/gardenlinux"
144+
143145
OCI_ANNOTATION_SIGNATURE_KEY = "io.gardenlinux.oci.signature"
144146
OCI_ANNOTATION_SIGNED_STRING_KEY = "io.gardenlinux.oci.signed-string"
145147
OCI_IMAGE_INDEX_MEDIA_TYPE = "application/vnd.oci.image.index.v1+json"

src/gardenlinux/flavors/__main__.py

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,27 @@
66
"""
77

88
from argparse import ArgumentParser
9+
from pathlib import Path
10+
from tempfile import TemporaryDirectory
911
import json
1012
import os
1113
import sys
1214

13-
from ..git import Git
14-
from ..github import GitHub
15+
from git import Repo
16+
from git.exc import GitError
1517

1618
from .parser import Parser
19+
from ..constants import GL_REPOSITORY_URL
20+
from ..git import Git
21+
22+
23+
def _get_flavors_file_data(flavors_file):
24+
if not flavors_file.exists():
25+
raise RuntimeError(f"Error: {flavors_file} does not exist.")
26+
27+
# Load and validate the flavors.yaml
28+
with flavors_file.open("r") as fp:
29+
return fp.read()
1730

1831

1932
def generate_markdown_table(combinations, no_arch):
@@ -52,7 +65,7 @@ def parse_args():
5265
parser.add_argument(
5366
"--commit",
5467
default=None,
55-
help="Commit hash to fetch flavors.yaml from GitHub (if not specified, uses local file).",
68+
help="Commit hash to fetch flavors.yaml from GitHub. An existing 'flavors.yaml' file will be preferred.",
5669
)
5770
parser.add_argument(
5871
"--no-arch",
@@ -126,44 +139,33 @@ def main():
126139

127140
args = parse_args()
128141

129-
if args.commit:
130-
# Use GitHub API to fetch flavors.yaml
131-
github = GitHub()
132-
flavors_content = github.get_flavors_yaml(commit=args.commit)
133-
134-
parser = Parser(data=flavors_content)
135-
136-
combinations = parser.filter(
137-
include_only_patterns=args.include_only,
138-
wildcard_excludes=args.exclude,
139-
only_build=args.build,
140-
only_test=args.test,
141-
only_test_platform=args.test_platform,
142-
only_publish=args.publish,
143-
filter_categories=args.category,
144-
exclude_categories=args.exclude_category,
145-
)
146-
else:
147-
# Use local file
148-
flavors_file = os.path.join(Git().root, "flavors.yaml")
149-
150-
if not os.path.isfile(flavors_file):
151-
sys.exit(f"Error: {flavors_file} does not exist.")
152-
153-
# Load and validate the flavors.yaml
154-
with open(flavors_file, "r") as file:
155-
flavors_data = file.read()
156-
157-
combinations = Parser(flavors_data).filter(
158-
include_only_patterns=args.include_only,
159-
wildcard_excludes=args.exclude,
160-
only_build=args.build,
161-
only_test=args.test,
162-
only_test_platform=args.test_platform,
163-
only_publish=args.publish,
164-
filter_categories=args.category,
165-
exclude_categories=args.exclude_category,
166-
)
142+
try:
143+
flavors_data = _get_flavors_file_data(Path(Git().root, "flavors.yaml"))
144+
except (GitError, RuntimeError):
145+
with TemporaryDirectory() as git_directory:
146+
repo = Repo.clone_from(
147+
GL_REPOSITORY_URL, git_directory, no_origin=True, sparse=True
148+
)
149+
150+
ref = repo.heads.main
151+
152+
if args.commit is not None:
153+
ref = ref.set_commit(args.commit)
154+
155+
flavors_data = _get_flavors_file_data(
156+
Path(repo.working_dir, "flavors.yaml")
157+
)
158+
159+
combinations = Parser(flavors_data).filter(
160+
include_only_patterns=args.include_only,
161+
wildcard_excludes=args.exclude,
162+
only_build=args.build,
163+
only_test=args.test,
164+
only_test_platform=args.test_platform,
165+
only_publish=args.publish,
166+
filter_categories=args.category,
167+
exclude_categories=args.exclude_category,
168+
)
167169

168170
if args.json_by_arch:
169171
grouped_combinations = Parser.group_by_arch(combinations)

src/gardenlinux/flavors/parser.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from ..constants import GL_FLAVORS_SCHEMA
1212
from ..logger import LoggerSetup
13-
from ..github import GitHub
1413

1514

1615
class Parser(object):

src/gardenlinux/git/git.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# -*- coding: utf-8 -*-
22

3+
from os import PathLike
4+
from pathlib import Path
35
import sys
6+
47
from git import Repo
58
from git import Git as _Git
6-
from os import PathLike
7-
from pathlib import Path
89

910
from ..logger import LoggerSetup
1011

tests/flavors/test_main.py

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import sys
33
import pytest
44

5-
import gardenlinux.flavors.__main__ as fm
5+
from gardenlinux.flavors import __main__ as fm
6+
from gardenlinux.git import Git
67

78

89
def test_generate_markdown_table():
@@ -98,22 +99,17 @@ def remove_arch(combinations):
9899
return DummyParser
99100

100101

101-
def test_main_exits_when_flavors_missing(tmp_path, monkeypatch):
102-
# Arrange
103-
# make Git().root point to a tmp dir that does NOT contain flavors.yaml
102+
def _make_git_class(tmp_path):
103+
"""
104+
Factory to create a fake Parser class
105+
Instances ignore the favors_data passed to __init__.
106+
"""
107+
104108
class DummyGit:
105109
def __init__(self):
106-
self.root = str(tmp_path)
110+
self.root = tmp_path
107111

108-
monkeypatch.setattr(fm, "Git", DummyGit)
109-
110-
# ensure no flavors.yaml
111-
monkeypatch.setattr(sys, "argv", ["prog"])
112-
113-
# Act / Assert
114-
with pytest.raises(SystemExit) as excinfo:
115-
fm.main()
116-
assert "does not exist" in str(excinfo.value)
112+
return DummyGit
117113

118114

119115
def test_main_json_by_arch_prints_json(tmp_path, monkeypatch, capsys):
@@ -122,14 +118,11 @@ def test_main_json_by_arch_prints_json(tmp_path, monkeypatch, capsys):
122118
flavors_file = tmp_path / "flavors.yaml"
123119
flavors_file.write_text("dummy: content")
124120

125-
class DummyGit:
126-
def __init__(self):
127-
self.root = str(tmp_path)
128-
129121
# define combinations and expected grouped mapping
130122
combinations = [("x86", "linux-x86"), ("arm", "android-arm")]
131123
grouped = {"x86": ["linux-x86"], "arm": ["android-arm"]}
132124

125+
DummyGit = _make_git_class(str(tmp_path))
133126
DummyParser = _make_parser_class(filter_result=combinations, group_result=grouped)
134127
monkeypatch.setattr(fm, "Git", DummyGit)
135128
monkeypatch.setattr(fm, "Parser", DummyParser)
@@ -151,13 +144,11 @@ def test_main_json_by_arch_with_no_arch_strips_arch_suffix(
151144
flavors_file = tmp_path / "flavors.yaml"
152145
flavors_file.write_text("dummy: content")
153146

154-
class DummyGit:
155-
def __init__(self):
156-
self.root = str(tmp_path)
157-
158147
combinations = [("x86", "linux-x86"), ("arm", "android-arm")]
159148
# group_by_arch returns items that include architecture suffixes
160149
grouped = {"x86": ["linux-x86"], "arm": ["android-arm"]}
150+
151+
DummyGit = _make_git_class(str(tmp_path))
161152
DummyParser = _make_parser_class(filter_result=combinations, group_result=grouped)
162153

163154
monkeypatch.setattr(fm, "Git", DummyGit)
@@ -179,11 +170,9 @@ def test_main_markdown_table_branch(tmp_path, monkeypatch, capsys):
179170
flavors_file = tmp_path / "flavors.yaml"
180171
flavors_file.write_text("dummy: content")
181172

182-
class DummyGit:
183-
def __init__(self):
184-
self.root = str(tmp_path)
185-
186173
combinations = [("x86_64", "linux-x86_64"), ("armv7", "android-armv7")]
174+
175+
DummyGit = _make_git_class(str(tmp_path))
187176
DummyParser = _make_parser_class(filter_result=combinations)
188177

189178
monkeypatch.setattr(fm, "Git", DummyGit)
@@ -205,12 +194,10 @@ def test_main_default_prints_flavors_list(tmp_path, monkeypatch, capsys):
205194
flavors_file = tmp_path / "flavors.yaml"
206195
flavors_file.write_text("dummy: content")
207196

208-
class DummyGit:
209-
def __init__(self):
210-
self.root = str(tmp_path)
211-
212197
# filter returns tuples; main's default branch prints comb[1] values, sorted unique
213198
combinations = [("x86", "linux-x86"), ("arm", "android-arm")]
199+
200+
DummyGit = _make_git_class(str(tmp_path))
214201
DummyParser = _make_parser_class(filter_result=combinations)
215202

216203
monkeypatch.setattr(fm, "Git", DummyGit)
@@ -224,3 +211,25 @@ def __init__(self):
224211

225212
# Assert
226213
assert sorted(lines) == sorted(["linux-x86", "android-arm"])
214+
215+
216+
def test_main_default_prints_git_flavors_list(tmp_path, monkeypatch, capsys):
217+
# Arrange
218+
flavors_file = tmp_path / "flavors.yaml"
219+
flavors_file.write_text("dummy: content")
220+
221+
# filter returns tuples; main's default branch prints comb[1] values, sorted unique
222+
combinations = [("x86", "linux-x86"), ("arm", "android-arm")]
223+
224+
DummyParser = _make_parser_class(filter_result=combinations)
225+
226+
monkeypatch.setattr(fm, "Parser", DummyParser)
227+
monkeypatch.setattr(sys, "argv", ["prog"])
228+
229+
# Act
230+
fm.main()
231+
out = capsys.readouterr().out
232+
lines = out.strip().splitlines()
233+
234+
# Assert
235+
assert sorted(lines) == sorted(["linux-x86", "android-arm"])

0 commit comments

Comments
 (0)