debian-forge/osbuild/version_detector.py
robojerk f93e3a447c
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
Add dynamic Debian version detection system (Fedora-style)
2025-08-26 16:08:44 -07:00

253 lines
9.6 KiB
Python

#!/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()