minor change for where the bootloader is

This commit is contained in:
Lukas Greve
2026-03-26 11:19:09 +01:00
parent 5c9a2535df
commit 8c0c3907d4
+38 -36
View File
@@ -6,11 +6,13 @@ Generates .cfg recipe files from templates and YAML manifest.
""" """
import argparse import argparse
import re
import sys import sys
import yaml
from pathlib import Path
from typing import Dict, List, Optional, Any
from itertools import product from itertools import product
from pathlib import Path
from typing import Dict, List, Optional
import yaml
# Deprecated/removed command mappings for Fedora 43 (F42) and rawhide # Deprecated/removed command mappings for Fedora 43 (F42) and rawhide
@@ -48,13 +50,13 @@ DEPRECATED_COMMANDS: Dict[str, Dict[str, str]] = {
} }
def _import_pykickstart(): def _import_pykickstart(): # noqa: PLC0415 - Import for optional dependency
"""Import pykickstart modules, returns None if not available.""" """Import pykickstart modules, returns None if not available."""
try: try:
from pykickstart.parser import KickstartParser from pykickstart.parser import KickstartParser # noqa: PLC0415
from pykickstart.version import makeVersion from pykickstart.version import makeVersion # noqa: PLC0415
from pykickstart.version import DEVEL from pykickstart.version import DEVEL # noqa: PLC0415
from pykickstart.errors import KickstartParseError, KickstartError from pykickstart.errors import KickstartParseError, KickstartError # noqa: PLC0415
return { return {
'parser': KickstartParser, 'parser': KickstartParser,
'makeVersion': makeVersion, 'makeVersion': makeVersion,
@@ -91,7 +93,7 @@ class RecipeGenerator:
template_path = path template_path = path
else: else:
template_path = self.project_root / path template_path = self.project_root / path
with open(template_path) as f: with open(template_path, encoding='utf-8') as f:
data = yaml.safe_load(f) data = yaml.safe_load(f)
return data['templates'] return data['templates']
except FileNotFoundError: except FileNotFoundError:
@@ -150,7 +152,8 @@ class RecipeGenerator:
else: else:
full_path = self.ingredients_dir / f"{fp}.cfg" full_path = self.ingredients_dir / f"{fp}.cfg"
if not full_path.exists(): if not full_path.exists():
errors.append(f"Optional fragment not found: {fp} (in list for {opt_key}={value})") errors.append(f"Optional fragment not found: {fp} "
f"(in list for {opt_key}={value})")
else: else:
if fragment_path.startswith('fragments/'): if fragment_path.startswith('fragments/'):
full_path = self.project_root / fragment_path full_path = self.project_root / fragment_path
@@ -158,7 +161,8 @@ class RecipeGenerator:
full_path = self.ingredients_dir / f"{fragment_path}.cfg" full_path = self.ingredients_dir / f"{fragment_path}.cfg"
if not full_path.exists(): if not full_path.exists():
errors.append(f"Optional fragment not found: {fragment_path} (for {opt_key}={value})") errors.append(f"Optional fragment not found: {fragment_path} "
f"(for {opt_key}={value})")
elif isinstance(opt_config, list): elif isinstance(opt_config, list):
for fragment_path in opt_config: for fragment_path in opt_config:
if fragment_path is None: if fragment_path is None:
@@ -184,18 +188,13 @@ class RecipeGenerator:
if 'name' not in recipe_config: if 'name' not in recipe_config:
errors.append("Recipe config missing 'name' key") errors.append("Recipe config missing 'name' key")
if 'variants' not in recipe_config: if 'variants' not in recipe_config:
errors.append(f"Recipe '{recipe_config.get('name', 'unnamed')}' missing 'variants' key") errors.append(f"Recipe '{recipe_config.get('name', 'unnamed')}' "
"missing 'variants' key")
continue continue
for variant in recipe_config['variants']: for variant in recipe_config['variants']:
if 'version' not in variant: if 'version' not in variant:
errors.append(f"Recipe '{recipe_config['name']}' variant missing 'version'") errors.append(f"Recipe '{recipe_config['name']}' variant missing 'version'")
# Support explicit variant name for install variants
if 'name' in variant:
variant_subname = variant['name']
else:
variant_subname = ''
return errors return errors
def generate_recipe(self, recipe_type: str, version: str, **modifiers) -> str: def generate_recipe(self, recipe_type: str, version: str, **modifiers) -> str:
@@ -219,8 +218,8 @@ class RecipeGenerator:
return '\n'.join(lines) return '\n'.join(lines)
def build_header(self, description: str, recipe_type: str, def build_header(self, description: str, _recipe_type: str,
version: str, modifiers: Dict) -> List[str]: _version: str, _modifiers: Dict) -> List[str]:
"""Build the ASCII art header and description.""" """Build the ASCII art header and description."""
header = [ header = [
"# __ ____ ____ _____", "# __ ____ ____ _____",
@@ -391,10 +390,10 @@ class RecipeGenerator:
issues.append("Warning: pykickstart not installed, skipping semantic validation") issues.append("Warning: pykickstart not installed, skipping semantic validation")
return issues return issues
KickstartParser = modules['parser'] KickstartParser = modules['parser'] # noqa: N806 - External library class name
makeVersion = modules['makeVersion'] makeVersion = modules['makeVersion'] # noqa: N806 - External library function
KickstartParseError = modules['KickstartParseError'] KickstartParseError = modules['KickstartParseError'] # noqa: N806
KickstartError = modules['KickstartError'] KickstartError = modules['KickstartError'] # noqa: N806
ks_version_str = self.get_ksversion(version) ks_version_str = self.get_ksversion(version)
if ks_version_str: if ks_version_str:
@@ -409,7 +408,7 @@ class RecipeGenerator:
issues.append(f"Syntax error line {e.lineno}: {e.message}") issues.append(f"Syntax error line {e.lineno}: {e.message}")
except KickstartError as e: except KickstartError as e:
issues.append(f"Validation error: {str(e)}") issues.append(f"Validation error: {str(e)}")
except Exception as e: except Exception as e: # noqa: BLE001 - Catch all for unexpected parser errors
issues.append(f"Unexpected error during parsing: {str(e)}") issues.append(f"Unexpected error during parsing: {str(e)}")
# Check for deprecated commands in the content # Check for deprecated commands in the content
@@ -451,7 +450,6 @@ class RecipeGenerator:
def extract_version(self, content: str, filename: str) -> Optional[str]: def extract_version(self, content: str, filename: str) -> Optional[str]:
"""Extract Fedora version from recipe content or filename.""" """Extract Fedora version from recipe content or filename."""
import re
filename_match = re.search(r'(?:_|-)(43|rawhide)(?:_|-|.cfg|.yaml|$)', filename) filename_match = re.search(r'(?:_|-)(43|rawhide)(?:_|-|.cfg|.yaml|$)', filename)
if filename_match: if filename_match:
return filename_match.group(1) return filename_match.group(1)
@@ -480,7 +478,7 @@ class RecipeGenerator:
# Build base parts # Build base parts
parts = [recipe_type.replace('_', '-')] parts = [recipe_type.replace('_', '-')]
# Add variant subname for install variants (desktop, server, hypervisor, hypervisor-desktop) # Add variant_subname for install variants
if variant_subname and variant_subname in ['desktop', 'server', 'hypervisor', 'hypervisor-desktop']: if variant_subname and variant_subname in ['desktop', 'server', 'hypervisor', 'hypervisor-desktop']:
parts.append(variant_subname) parts.append(variant_subname)
@@ -551,14 +549,15 @@ class RecipeGenerator:
def main(): def main():
"""Main entry point for recipe generator CLI."""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Generate Phyllome OS kickstart recipes from templates', description='Generate Phyllome OS kickstart recipes from templates',
formatter_class=argparse.RawDescriptionHelpFormatter formatter_class=argparse.RawDescriptionHelpFormatter
) )
# Global options # Global options
SCRIPTS_DIR = Path(__file__).resolve().parent SCRIPTS_DIR = Path(__file__).resolve().parent # noqa: N806 - Constant
PROJECT_ROOT = SCRIPTS_DIR.parent PROJECT_ROOT = SCRIPTS_DIR.parent # noqa: N806 - Constant
parser.add_argument('--ingredients', '-i', parser.add_argument('--ingredients', '-i',
type=Path, default=PROJECT_ROOT / 'ingredients', type=Path, default=PROJECT_ROOT / 'ingredients',
@@ -626,7 +625,7 @@ def main():
all_issues = [] all_issues = []
for recipe_path in args.validate: for recipe_path in args.validate:
try: try:
with open(recipe_path) as f: with open(recipe_path, encoding='utf-8') as f:
content = f.read() content = f.read()
issues = generator.validate_recipe(content) issues = generator.validate_recipe(content)
@@ -637,7 +636,8 @@ def main():
semantic_issues = generator.validate_recipe_semantic(content, version) semantic_issues = generator.validate_recipe_semantic(content, version)
issues.extend(semantic_issues) issues.extend(semantic_issues)
else: else:
issues.append("Warning: Could not determine version, skipping semantic validation") issues.append("Warning: Could not determine version, "
"skipping semantic validation")
if issues: if issues:
all_issues.append((recipe_path, issues)) all_issues.append((recipe_path, issues))
@@ -668,8 +668,10 @@ def main():
print(f"\nSummary:", file=sys.stderr) print(f"\nSummary:", file=sys.stderr)
print(f" - {len(all_issues)} recipe(s) checked", file=sys.stderr) print(f" - {len(all_issues)} recipe(s) checked", file=sys.stderr)
total_errors = sum(len([i for i in issues if 'ERROR' in i]) for _, issues in all_issues) total_errors = sum(len([i for i in issues if 'ERROR' in i])
total_warnings = sum(len([i for i in issues if 'Warning:' in i]) for _, issues in all_issues) for _, issues in all_issues)
total_warnings = sum(len([i for i in issues if 'Warning:' in i])
for _, issues in all_issues)
print(f" - {total_errors} error(s), {total_warnings} warning(s)", file=sys.stderr) print(f" - {total_errors} error(s), {total_warnings} warning(s)", file=sys.stderr)
# Strict mode: treat warnings as errors # Strict mode: treat warnings as errors
@@ -686,7 +688,7 @@ def main():
# Batch generation mode # Batch generation mode
if args.manifest: if args.manifest:
try: try:
with open(args.manifest) as f: with open(args.manifest, encoding='utf-8') as f:
manifest = yaml.safe_load(f) manifest = yaml.safe_load(f)
except FileNotFoundError: except FileNotFoundError:
print(f"Error: Manifest file not found: {args.manifest}", file=sys.stderr) print(f"Error: Manifest file not found: {args.manifest}", file=sys.stderr)
@@ -744,7 +746,7 @@ def main():
print(f"Would generate: {output_path}") print(f"Would generate: {output_path}")
else: else:
print(f"Generating: {output_path}") print(f"Generating: {output_path}")
with open(output_path, 'w') as f: with open(output_path, 'w', encoding='utf-8') as f:
f.write(content) f.write(content)
sys.exit(0) sys.exit(0)
@@ -780,7 +782,7 @@ def main():
if args.dry_run: if args.dry_run:
print(f"Would write to: {args.output}") print(f"Would write to: {args.output}")
else: else:
with open(args.output, 'w') as f: with open(args.output, 'w', encoding='utf-8') as f:
f.write(content) f.write(content)
print(f"Generated: {args.output}") print(f"Generated: {args.output}")
else: else: