Add dynamic Debian version detection system (Fedora-style)
Some checks are pending
Checks / Spelling (push) Waiting to run
Checks / Python Linters (push) Waiting to run
Checks / Shell Linters (push) Waiting to run
Checks / 📦 Packit config lint (push) Waiting to run
Checks / 🔍 Check for valid snapshot urls (push) Waiting to run
Checks / 🔍 Check JSON files for formatting consistency (push) Waiting to run
Generate / Documentation (push) Waiting to run
Generate / Test Data (push) Waiting to run
Tests / Unittest (push) Waiting to run
Tests / Assembler test (legacy) (push) Waiting to run
Tests / Smoke run: unittest as normal user on default runner (push) Waiting to run

This commit is contained in:
robojerk 2025-08-26 16:08:44 -07:00
parent 0e9754eec1
commit f93e3a447c
4 changed files with 420 additions and 1 deletions

View file

@ -10,7 +10,7 @@
# url = http://localhost:3142
# url = http://192.168.1.100:3142
# url = http://apt-cache.company.local:3142
url =
# url =
# Alternative: use environment variable
# Set DEBIAN_FORGE_APT_PROXY environment variable to override this setting

View file

@ -9,6 +9,28 @@ import configparser
from pathlib import Path
from typing import Optional, Dict, Any
# Import version detector
try:
from .version_detector import (
get_recommended_suite as _get_recommended_suite,
get_mirror_url as _get_mirror_url,
is_version_supported as _is_version_supported,
print_version_info as _print_version_info
)
except ImportError:
# Fallback if version detector is not available
def _get_recommended_suite():
return "trixie"
def _get_mirror_url():
return "http://deb.debian.org/debian"
def _is_version_supported():
return True
def _print_version_info():
print("Version detector not available")
class DebianForgeConfig:
"""Configuration manager for Debian Forge settings"""
@ -17,6 +39,7 @@ class DebianForgeConfig:
self.config_dir = Path(config_dir)
self.config = configparser.ConfigParser()
self._load_config()
self._apply_version_detection()
def _load_config(self):
"""Load configuration from multiple sources with priority order"""
@ -60,6 +83,26 @@ class DebianForgeConfig:
self.config.add_section("build")
self.config["build"]["default_arch"] = env_arch
def _apply_version_detection(self):
"""Apply automatic version detection like Fedora does"""
# Check if version detection is available
if not _is_version_supported():
print("⚠️ Warning: Current Debian version is not officially supported")
print(" Debian Forge supports Debian 13+ (Trixie and newer)")
print(" Consider upgrading or using a supported version")
# Auto-detect recommended suite if not explicitly set
try:
current_suite = self.get_build_setting("default_suite")
if not current_suite or current_suite == "bookworm": # Legacy default
recommended_suite = _get_recommended_suite()
if "build" not in self.config:
self.config.add_section("build")
self.config["build"]["default_suite"] = recommended_suite
print(f"🔄 Auto-detected recommended suite: {recommended_suite}")
except Exception:
pass
def get_apt_proxy(self) -> Optional[str]:
"""Get apt-cacher-ng proxy URL if configured"""
try:
@ -93,6 +136,18 @@ class DebianForgeConfig:
"""Check if apt-cacher-ng proxy is enabled"""
return self.get_apt_proxy() is not None
def get_recommended_suite(self) -> str:
"""Get the recommended Debian suite for this system"""
return _get_recommended_suite()
def get_mirror_url(self) -> str:
"""Get appropriate Debian mirror URL"""
return _get_mirror_url()
def is_version_supported(self) -> bool:
"""Check if current Debian version is supported"""
return _is_version_supported()
def get_all_settings(self) -> Dict[str, Dict[str, Any]]:
"""Get all configuration settings as a dictionary"""
result = {}
@ -104,6 +159,12 @@ class DebianForgeConfig:
"""Print current configuration for debugging"""
print("Debian Forge Configuration:")
print("=" * 40)
# Show version detection info
_print_version_info()
print()
# Show configuration settings
for section, settings in self.get_all_settings().items():
print(f"\n[{section}]")
for key, value in settings.items():
@ -114,6 +175,12 @@ class DebianForgeConfig:
if env_proxy:
print(f"\nEnvironment Override:")
print(f" DEBIAN_FORGE_APT_PROXY = {env_proxy}")
# Show auto-detected values
print(f"\nAuto-detected:")
print(f" Recommended suite = {self.get_recommended_suite()}")
print(f" Mirror URL = {self.get_mirror_url()}")
print(f" Version supported = {self.is_version_supported()}")
# Global configuration instance
@ -138,3 +205,18 @@ def get_build_setting(key: str, default: Any = None) -> Any:
def get_stage_setting(key: str, default: Any = None) -> Any:
"""Get a stage setting (convenience function)"""
return config.get_stage_setting(key, default)
def get_recommended_suite() -> str:
"""Get recommended Debian suite (convenience function)"""
return config.get_recommended_suite()
def get_mirror_url() -> str:
"""Get appropriate Debian mirror URL (convenience function)"""
return config.get_mirror_url()
def is_version_supported() -> bool:
"""Check if current Debian version is supported (convenience function)"""
return config.is_version_supported()

253
osbuild/version_detector.py Normal file
View file

@ -0,0 +1,253 @@
#!/usr/bin/env python3
"""
Debian Version Detector
Automatically detects Debian version and provides appropriate configuration
Similar to how Fedora/RHEL handle version detection in OSBuild
"""
import os
import subprocess
import re
from pathlib import Path
from typing import Optional, Dict, Any, Tuple
class DebianVersionDetector:
"""Detects Debian version and provides appropriate configuration"""
def __init__(self):
self.version_info = self._detect_debian_version()
def _detect_debian_version(self) -> Dict[str, Any]:
"""Detect Debian version from multiple sources"""
version_info = {
'codename': None,
'version': None,
'release': None,
'is_debian': False,
'is_supported': False,
'support_status': 'unknown'
}
# Method 1: Check /etc/os-release
if os.path.exists('/etc/os-release'):
with open('/etc/os-release', 'r') as f:
content = f.read()
# Check if this is actually Debian
if 'debian' in content.lower():
version_info['is_debian'] = True
# Extract version info
version_match = re.search(r'VERSION_ID="?([^"\n]+)"?', content)
codename_match = re.search(r'VERSION_CODENAME="?([^"\n]+)"?', content)
if version_match:
version_info['version'] = version_match.group(1)
if codename_match:
version_info['codename'] = codename_match.group(1)
# Method 2: Check /etc/debian_version
if os.path.exists('/etc/debian_version'):
version_info['is_debian'] = True
with open('/etc/debian_version', 'r') as f:
version_info['release'] = f.read().strip()
# Method 3: Check lsb_release command
try:
result = subprocess.run(['lsb_release', '-a'],
capture_output=True, text=True, check=True)
for line in result.stdout.split('\n'):
if 'Distributor ID:' in line and 'debian' in line.lower():
version_info['is_debian'] = True
elif 'Codename:' in line and version_info['is_debian']:
version_info['codename'] = line.split(':', 1)[1].strip()
elif 'Release:' in line and version_info['is_debian']:
version_info['version'] = line.split(':', 1)[1].strip()
except (subprocess.CalledProcessError, FileNotFoundError):
pass
# If not Debian, return early
if not version_info['is_debian']:
return {
'codename': None,
'version': None,
'release': None,
'is_debian': False,
'is_supported': False,
'support_status': 'not_debian',
'support_level': 'none',
'debian_version': 'unknown'
}
# Determine support status for Debian systems
version_info.update(self._determine_support_status(version_info))
return version_info
def _determine_support_status(self, version_info: Dict[str, Any]) -> Dict[str, Any]:
"""Determine if the detected version is supported"""
codename = version_info.get('codename', '').lower()
version = version_info.get('version', '')
# Debian 13+ support policy
supported_codenames = {
'trixie': {'version': '13', 'status': 'stable', 'support': 'full'},
'forky': {'version': '14', 'status': 'testing', 'support': 'development'},
'sid': {'version': 'unstable', 'status': 'unstable', 'support': 'experimental'}
}
# Check if codename is supported
if codename in supported_codenames:
return {
'is_supported': True,
'support_status': supported_codenames[codename]['status'],
'support_level': supported_codenames[codename]['support'],
'debian_version': supported_codenames[codename]['version']
}
# Check version number if codename not found
try:
version_num = int(version.split('.')[0])
if version_num >= 13:
return {
'is_supported': True,
'support_status': 'stable',
'support_level': 'full',
'debian_version': str(version_num)
}
except (ValueError, IndexError):
pass
# Not supported
return {
'is_supported': False,
'support_status': 'unsupported',
'support_level': 'none',
'debian_version': 'unknown'
}
def get_recommended_suite(self) -> str:
"""Get the recommended Debian suite for this system"""
if not self.version_info['is_debian']:
return 'trixie' # Default for non-Debian systems
if self.version_info['is_supported']:
return self.version_info['codename'] or 'trixie'
return 'trixie' # Default to supported version
def get_mirror_url(self) -> str:
"""Get appropriate Debian mirror URL"""
if not self.version_info['is_debian']:
return 'http://deb.debian.org/debian' # Default for non-Debian systems
codename = self.version_info.get('codename', 'trixie')
# Use official Debian mirrors
mirrors = {
'trixie': 'http://deb.debian.org/debian',
'forky': 'http://deb.debian.org/debian',
'sid': 'http://deb.debian.org/debian'
}
return mirrors.get(codename, 'http://deb.debian.org/debian')
def get_apt_sources(self) -> str:
"""Generate appropriate apt sources.list content"""
if not self.version_info['is_debian']:
# Return default sources for non-Debian systems
return """deb http://deb.debian.org/debian trixie main
deb http://deb.debian.org/debian trixie-updates main
deb http://deb.debian.org/debian trixie-security main
deb http://deb.debian.org/debian trixie-backports main
"""
codename = self.version_info.get('codename', 'trixie')
mirror = self.get_mirror_url()
sources = f"""deb {mirror} {codename} main
deb {mirror} {codename}-updates main
deb {mirror} {codename}-security main
"""
# Add backports for stable releases
if codename == 'trixie':
sources += f"deb {mirror} {codename}-backports main\n"
return sources
def get_support_warning(self) -> Optional[str]:
"""Get warning message if version is not fully supported"""
if not self.version_info['is_debian']:
return "Note: This is not a Debian system. Debian Forge will use default Debian settings."
if not self.version_info['is_supported']:
return f"Warning: Debian {self.version_info.get('version', 'unknown')} ({self.version_info.get('codename', 'unknown')}) is not officially supported. Debian Forge supports Debian 13+ (Trixie and newer)."
if self.version_info['support_level'] == 'experimental':
return f"Warning: {self.version_info['codename']} is unstable. Use with caution for production builds."
return None
def print_version_info(self):
"""Print detailed version information"""
print("Debian Version Detection:")
print("=" * 40)
if not self.version_info['is_debian']:
print("System: Non-Debian system detected")
print("Status: Using default Debian Forge settings")
print(f"Recommended suite: {self.get_recommended_suite()}")
print(f"Mirror URL: {self.get_mirror_url()}")
return
print(f"System: Debian")
print(f"Codename: {self.version_info.get('codename', 'unknown')}")
print(f"Version: {self.version_info.get('version', 'unknown')}")
print(f"Release: {self.version_info.get('release', 'unknown')}")
print(f"Supported: {self.version_info['is_supported']}")
print(f"Status: {self.version_info['support_status']}")
print(f"Support Level: {self.version_info['support_level']}")
warning = self.get_support_warning()
if warning:
print(f"\n⚠️ {warning}")
print(f"\nRecommended suite: {self.get_recommended_suite()}")
print(f"Mirror URL: {self.get_mirror_url()}")
# Global instance
version_detector = DebianVersionDetector()
def get_recommended_suite() -> str:
"""Get recommended Debian suite (convenience function)"""
return version_detector.get_recommended_suite()
def get_mirror_url() -> str:
"""Get appropriate Debian mirror URL (convenience function)"""
return version_detector.get_mirror_url()
def get_apt_sources() -> str:
"""Get appropriate apt sources (convenience function)"""
return version_detector.get_apt_sources()
def is_version_supported() -> bool:
"""Check if current Debian version is supported (convenience function)"""
return version_detector.version_info['is_supported']
def is_debian_system() -> bool:
"""Check if this is a Debian system (convenience function)"""
return version_detector.version_info['is_debian']
def print_version_info():
"""Print version information (convenience function)"""
version_detector.print_version_info()
if __name__ == '__main__':
print_version_info()

84
tools/debian-version-info Executable file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""
Debian Version Info Tool
Shows current Debian version information and compatibility status
"""
import sys
import os
# Add the project root to the Python path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
try:
from osbuild.version_detector import print_version_info, is_debian_system, get_recommended_suite
from osbuild.config_manager import config
except ImportError as e:
print(f"Error importing modules: {e}")
print("Make sure you're running this from the project root directory")
sys.exit(1)
def main():
"""Main function"""
print("🔍 Debian Forge Version Information")
print("=" * 50)
# Show version detection
print_version_info()
print()
# Show configuration status
print("📋 Configuration Status:")
print("=" * 30)
if is_debian_system():
print("✅ Running on Debian system")
suite = get_recommended_suite()
print(f"📦 Recommended suite: {suite}")
# Check if suite is supported
if suite in ['trixie', 'forky', 'sid']:
print("✅ Suite is officially supported")
else:
print("⚠️ Suite may have limited support")
else:
print(" Running on non-Debian system")
print("📦 Using default Debian Forge settings")
print(f"📦 Default suite: {get_recommended_suite()}")
print()
# Show current configuration
print("⚙️ Current Configuration:")
print("=" * 30)
print(f"Default suite: {config.get_build_setting('default_suite', 'not set')}")
print(f"Default arch: {config.get_build_setting('default_arch', 'not set')}")
print(f"APT proxy: {config.get_apt_proxy() or 'not set'}")
print()
# Show recommendations
print("💡 Recommendations:")
print("=" * 30)
if not is_debian_system():
print("• Consider using a Debian system for best compatibility")
print("• Current system will use default Debian Forge settings")
else:
suite = get_recommended_suite()
if suite == 'trixie':
print("• ✅ Using stable Debian 13 (Trixie) - recommended for production")
elif suite == 'forky':
print("• 🔄 Using testing Debian 14 (Forky) - good for development")
elif suite == 'sid':
print("• ⚠️ Using unstable (Sid) - use with caution")
else:
print(f"• ⚠️ Using {suite} - may have limited support")
print()
print("For more information, see config/README.md")
if __name__ == '__main__':
main()