Create update-manifest.py

This commit is contained in:
overcuriousity 2025-06-23 08:49:51 +02:00 committed by GitHub
parent aba84b9ade
commit 63f3f5726f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""
Script to automatically update the Flatpak manifest with new versions
of Autopsy and Sleuth Kit.
"""
import argparse
import re
import sys
import requests
import hashlib
from pathlib import Path
from typing import Dict, Optional
class ManifestUpdater:
def __init__(self, manifest_path: str):
self.manifest_path = Path(manifest_path)
if not self.manifest_path.exists():
raise FileNotFoundError(f"Manifest file not found: {manifest_path}")
def get_github_release_info(self, repo: str, tag: str) -> Dict[str, str]:
"""Get release information from GitHub API."""
url = f"https://api.github.com/repos/{repo}/releases/tags/{tag}"
response = requests.get(url)
if response.status_code != 200:
raise ValueError(f"Failed to get release info for {repo}:{tag}")
data = response.json()
return {
'tag': data['tag_name'],
'tarball_url': data['tarball_url'],
'zipball_url': data['zipball_url'],
'published_at': data['published_at']
}
def calculate_archive_sha256(self, url: str) -> str:
"""Download and calculate SHA256 hash of an archive."""
print(f"Downloading and calculating hash for: {url}")
response = requests.get(url, stream=True)
response.raise_for_status()
sha256_hash = hashlib.sha256()
for chunk in response.iter_content(chunk_size=8192):
sha256_hash.update(chunk)
return sha256_hash.hexdigest()
def update_module_version(self, content: str, module_name: str,
new_tag: str, repo_url: str) -> str:
"""Update a specific module's version in the manifest."""
# Pattern to match the module block
module_pattern = rf'(- name: {re.escape(module_name)}.*?)((?=- name: |\Z))'
match = re.search(module_pattern, content, re.DOTALL)
if not match:
raise ValueError(f"Module '{module_name}' not found in manifest")
module_block = match.group(1)
# Update source-tag
updated_block = re.sub(
r'(\s+source-tag:\s+).*',
rf'\g<1>{new_tag}',
module_block
)
# Remove source-branch if it exists (tags take precedence)
updated_block = re.sub(
r'\s+source-branch:.*?\n',
'',
updated_block
)
# Update the URL if it's different
if repo_url:
updated_block = re.sub(
r'(\s+source:\s+).*',
rf'\g<1>{repo_url}',
updated_block
)
# Replace the module block in the content
return content.replace(module_block, updated_block)
def update_app_version(self, content: str, version: str) -> str:
"""Update the main application version."""
# Extract version number from tag (e.g., "autopsy-4.22.1" -> "4.22.1")
version_match = re.search(r'(\d+\.\d+\.\d+)', version)
if version_match:
version_number = version_match.group(1)
else:
version_number = version.replace('autopsy-', '').replace('v', '')
return re.sub(
r'^version:\s+.*',
f'version: {version_number}',
content,
flags=re.MULTILINE
)
def update_manifest(self, autopsy_version: Optional[str] = None,
sleuthkit_version: Optional[str] = None) -> bool:
"""Update the manifest file with new versions."""
# Read current manifest
content = self.manifest_path.read_text()
original_content = content
# Update Autopsy if specified
if autopsy_version:
print(f"Updating Autopsy to version: {autopsy_version}")
content = self.update_module_version(
content,
'autopsy',
autopsy_version,
'https://github.com/sleuthkit/autopsy.git'
)
content = self.update_app_version(content, autopsy_version)
# Update Sleuth Kit if specified
if sleuthkit_version:
print(f"Updating Sleuth Kit to version: {sleuthkit_version}")
content = self.update_module_version(
content,
'sleuthkit',
sleuthkit_version,
'https://github.com/sleuthkit/sleuthkit.git'
)
# Write updated manifest if changes were made
if content != original_content:
# Create backup
backup_path = self.manifest_path.with_suffix('.yml.backup')
backup_path.write_text(original_content)
print(f"Created backup: {backup_path}")
# Write updated content
self.manifest_path.write_text(content)
print(f"Updated manifest: {self.manifest_path}")
return True
else:
print("No changes needed.")
return False
def validate_manifest(self) -> bool:
"""Basic validation of the manifest file."""
content = self.manifest_path.read_text()
# Check for required fields
required_fields = ['app-id:', 'runtime:', 'sdk:', 'modules:']
for field in required_fields:
if field not in content:
print(f"Error: Required field '{field}' not found in manifest")
return False
# Check for module structure
if '- name: autopsy' not in content:
print("Error: Autopsy module not found in manifest")
return False
if '- name: sleuthkit' not in content:
print("Error: Sleuth Kit module not found in manifest")
return False
print("Manifest validation passed.")
return True
def main():
parser = argparse.ArgumentParser(
description='Update Flatpak manifest with new Autopsy/Sleuth Kit versions'
)
parser.add_argument(
'--manifest',
required=True,
help='Path to the Flatpak manifest file'
)
parser.add_argument(
'--autopsy-version',
help='New Autopsy version tag (e.g., autopsy-4.22.1)'
)
parser.add_argument(
'--sleuthkit-version',
help='New Sleuth Kit version tag (e.g., sleuthkit-4.14.0)'
)
parser.add_argument(
'--validate-only',
action='store_true',
help='Only validate the manifest without updating'
)
args = parser.parse_args()
try:
updater = ManifestUpdater(args.manifest)
if args.validate_only:
success = updater.validate_manifest()
sys.exit(0 if success else 1)
if not args.autopsy_version and not args.sleuthkit_version:
print("Error: At least one version must be specified")
sys.exit(1)
# Validate before updating
if not updater.validate_manifest():
print("Error: Manifest validation failed")
sys.exit(1)
# Perform updates
updated = updater.update_manifest(
autopsy_version=args.autopsy_version,
sleuthkit_version=args.sleuthkit_version
)
if updated:
print("Manifest updated successfully!")
# Validate after updating
if not updater.validate_manifest():
print("Warning: Updated manifest failed validation")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == '__main__':
main()