Skip to content

Commit 3668ff6

Browse files
committed
chore: Include OWNERS info in generated readme
Signed-off-by: Giulio Frasca <[email protected]>
1 parent 9cca62b commit 3668ff6

File tree

2 files changed

+104
-17
lines changed

2 files changed

+104
-17
lines changed

scripts/generate_readme/content_generator.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ def __init__(self, metadata: Dict[str, Any], source_dir: Path):
2222
self.source_dir = source_dir
2323
self.metadata_file = source_dir / 'metadata.yaml'
2424
self.example_file = source_dir / 'example_pipeline.py'
25-
self.yaml_metadata = self._load_yaml_metadata()
25+
self.owners_file = source_dir / 'OWNERS'
26+
self.feature_metadata = self._load_feature_metadata()
2627

2728
# Set up Jinja2 environment
2829
template_dir = Path(__file__).parent
@@ -33,11 +34,14 @@ def __init__(self, metadata: Dict[str, Any], source_dir: Path):
3334
)
3435
self.template = self.env.get_template('README.md.j2')
3536

36-
def _load_yaml_metadata(self) -> Dict[str, Any]:
37-
"""Load and parse the metadata.yaml file, excluding the 'ci' field.
37+
def _load_feature_metadata(self) -> Dict[str, Any]:
38+
"""Load and parse feature metadata from metadata.yaml and OWNERS files.
39+
40+
Loads metadata from metadata.yaml (excluding 'ci' field) and augments it
41+
with owners information from OWNERS file if it exists.
3842
3943
Returns:
40-
Dictionary containing the YAML metadata without the 'ci' field.
44+
Dictionary containing the aggregated feature metadata.
4145
"""
4246
try:
4347
with open(self.metadata_file, 'r', encoding='utf-8') as f:
@@ -47,10 +51,33 @@ def _load_yaml_metadata(self) -> Dict[str, Any]:
4751
if yaml_data and 'ci' in yaml_data:
4852
yaml_data.pop('ci')
4953

50-
return yaml_data or {}
54+
yaml_data = yaml_data or {}
5155
except Exception as e:
5256
logger.warning(f"Could not load metadata.yaml: {e}")
53-
return {}
57+
yaml_data = {}
58+
59+
# Augment with owners information from OWNERS file
60+
owners_data = self._load_owners()
61+
if owners_data:
62+
yaml_data['owners'] = owners_data
63+
64+
return yaml_data
65+
66+
def _load_owners(self) -> Dict[str, Any]:
67+
"""Load the OWNERS file if it exists.
68+
69+
Returns:
70+
Dictionary containing owners data (approvers and reviewers) if file exists, empty dict otherwise.
71+
"""
72+
if self.owners_file.exists():
73+
try:
74+
with open(self.owners_file, 'r', encoding='utf-8') as f:
75+
owners_data = yaml.safe_load(f)
76+
return owners_data or {}
77+
except Exception as e:
78+
logger.warning(f"Error reading OWNERS file ({self.owners_file}): {e}")
79+
return {}
80+
return {}
5481

5582
def _load_example_pipeline(self) -> str:
5683
"""Load the Example Pipeline file if it exists.
@@ -157,7 +184,7 @@ def _format_metadata(self) -> Dict[str, str]:
157184
"""
158185
return {
159186
self._format_key(key): self._format_value(value)
160-
for key, value in self.yaml_metadata.items()
187+
for key, value in self.feature_metadata.items()
161188
}
162189

163190
def generate_readme(self) -> str:
@@ -211,7 +238,7 @@ def _prepare_template_context(self) -> Dict[str, Any]:
211238
example_code = self._load_example_pipeline()
212239

213240
# Prepare formatted metadata for human-readable display
214-
formatted_metadata = self._format_metadata() if self.yaml_metadata else {}
241+
formatted_metadata = self._format_metadata() if self.feature_metadata else {}
215242

216243
return {
217244
'title': title,

scripts/generate_readme/tests/test_content_generator.py

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def test_init_with_component(self, component_dir, sample_extracted_metadata):
1818
)
1919

2020
assert generator.metadata == sample_extracted_metadata
21-
assert generator.yaml_metadata is not None
21+
assert generator.feature_metadata is not None
2222

2323
def test_init_with_pipeline(self, pipeline_dir, sample_extracted_metadata):
2424
"""Test initialization with pipeline metadata."""
@@ -29,18 +29,18 @@ def test_init_with_pipeline(self, pipeline_dir, sample_extracted_metadata):
2929

3030
assert generator.metadata == sample_extracted_metadata
3131

32-
def test_load_yaml_metadata(self, component_dir, sample_extracted_metadata):
32+
def test_load_feature_metadata(self, component_dir, sample_extracted_metadata):
3333
"""Test loading YAML metadata from file."""
3434
generator = ReadmeContentGenerator(
3535
sample_extracted_metadata,
3636
component_dir
3737
)
3838

39-
assert 'name' in generator.yaml_metadata
40-
assert generator.yaml_metadata['name'] == 'sample_component'
41-
assert 'tier' in generator.yaml_metadata
39+
assert 'name' in generator.feature_metadata
40+
assert generator.feature_metadata['name'] == 'sample_component'
41+
assert 'tier' in generator.feature_metadata
4242

43-
def test_load_yaml_metadata_excludes_ci(self, temp_dir, sample_extracted_metadata):
43+
def test_load_feature_metadata_excludes_ci(self, temp_dir, sample_extracted_metadata):
4444
"""Test that 'ci' field is excluded from YAML metadata."""
4545
metadata_file = temp_dir / "metadata.yaml"
4646
metadata_file.write_text("""name: test
@@ -55,9 +55,69 @@ def test_load_yaml_metadata_excludes_ci(self, temp_dir, sample_extracted_metadat
5555
temp_dir
5656
)
5757

58-
assert 'ci' not in generator.yaml_metadata
59-
assert 'name' in generator.yaml_metadata
60-
assert 'tier' in generator.yaml_metadata
58+
assert 'ci' not in generator.feature_metadata
59+
assert 'name' in generator.feature_metadata
60+
assert 'tier' in generator.feature_metadata
61+
62+
def test_load_owners_file_exists(self, component_dir, sample_extracted_metadata):
63+
"""Test loading OWNERS file when it exists."""
64+
# Create an OWNERS file
65+
owners_file = component_dir / "OWNERS"
66+
owners_file.write_text("""approvers:
67+
- user1
68+
- user2
69+
reviewers:
70+
- user3
71+
- user4
72+
""")
73+
74+
generator = ReadmeContentGenerator(
75+
sample_extracted_metadata,
76+
component_dir
77+
)
78+
79+
# Check that owners were loaded into feature_metadata
80+
assert 'owners' in generator.feature_metadata
81+
assert 'approvers' in generator.feature_metadata['owners']
82+
assert 'reviewers' in generator.feature_metadata['owners']
83+
assert generator.feature_metadata['owners']['approvers'] == ['user1', 'user2']
84+
assert generator.feature_metadata['owners']['reviewers'] == ['user3', 'user4']
85+
86+
def test_load_owners_file_not_exists(self, component_dir, sample_extracted_metadata):
87+
"""Test that missing OWNERS file doesn't cause errors."""
88+
generator = ReadmeContentGenerator(
89+
sample_extracted_metadata,
90+
component_dir
91+
)
92+
93+
# Should not have owners in feature_metadata when OWNERS doesn't exist
94+
assert 'owners' not in generator.feature_metadata
95+
96+
def test_owners_in_generated_readme(self, component_dir, sample_extracted_metadata):
97+
"""Test that OWNERS data appears in generated README."""
98+
# Create an OWNERS file
99+
owners_file = component_dir / "OWNERS"
100+
owners_file.write_text("""approvers:
101+
- alice
102+
- bob
103+
reviewers:
104+
- charlie
105+
""")
106+
107+
generator = ReadmeContentGenerator(
108+
sample_extracted_metadata,
109+
component_dir
110+
)
111+
112+
readme = generator.generate_readme()
113+
114+
# Check that owners appear in the README
115+
assert 'Owners' in readme
116+
assert 'alice' in readme
117+
assert 'bob' in readme
118+
assert 'charlie' in readme
119+
assert 'Approvers' in readme or 'approvers' in readme.lower()
120+
assert 'Reviewers' in readme or 'reviewers' in readme.lower()
61121

62122
def test_prepare_template_context(self, component_dir, sample_extracted_metadata):
63123
"""Test template context preparation."""

0 commit comments

Comments
 (0)