Add sbuild and debian source stages for Debian package building and source management
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
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:
parent
6a17af5a62
commit
6a744c6c5b
4 changed files with 387 additions and 0 deletions
132
stages/org.osbuild.debian.source
Normal file
132
stages/org.osbuild.debian.source
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#!/usr/bin/python3
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
import osbuild.api
|
||||
|
||||
|
||||
def download_source_package(package_name, suite, mirror, output_dir):
|
||||
"""Download Debian source package"""
|
||||
|
||||
# Create temporary directory for download
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
os.chdir(temp_dir)
|
||||
|
||||
# Use apt-get source to download package
|
||||
cmd = ["apt-get", "source", package_name]
|
||||
|
||||
print(f"Downloading source package: {' '.join(cmd)}")
|
||||
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
print(f"Error downloading source package:")
|
||||
print(f"stdout: {result.stdout}")
|
||||
print(f"stderr: {result.stderr}")
|
||||
return False
|
||||
|
||||
# Copy downloaded files to output directory
|
||||
for file in os.listdir("."):
|
||||
src = os.path.join(temp_dir, file)
|
||||
dst = os.path.join(output_dir, file)
|
||||
|
||||
if os.path.isdir(file):
|
||||
shutil.copytree(src, dst)
|
||||
else:
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
print(f"Copied: {file}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def setup_apt_sources(tree, suite, mirror, components=None):
|
||||
"""Set up apt sources for the specified suite"""
|
||||
|
||||
if components is None:
|
||||
components = ["main", "contrib", "non-free"]
|
||||
|
||||
sources_content = f"""deb {mirror} {suite} {' '.join(components)}
|
||||
deb {mirror} {suite}-updates {' '.join(components)}
|
||||
deb {mirror} {suite}-security {' '.join(components)}
|
||||
"""
|
||||
|
||||
sources_path = os.path.join(tree, "etc/apt/sources.list")
|
||||
os.makedirs(os.path.dirname(sources_path), exist_ok=True)
|
||||
|
||||
with open(sources_path, "w") as f:
|
||||
f.write(sources_content)
|
||||
|
||||
print(f"Created sources.list for {suite}")
|
||||
|
||||
|
||||
def update_package_lists(tree):
|
||||
"""Update package lists"""
|
||||
|
||||
cmd = ["chroot", tree, "apt-get", "update"]
|
||||
|
||||
print("Updating package lists...")
|
||||
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
print(f"Error updating package lists:")
|
||||
print(f"stdout: {result.stdout}")
|
||||
print(f"stderr: {result.stderr}")
|
||||
return False
|
||||
|
||||
print("Package lists updated successfully")
|
||||
return True
|
||||
|
||||
|
||||
def main(tree, options):
|
||||
"""Main function for debian source stage"""
|
||||
|
||||
# Get options
|
||||
package_name = options.get("package")
|
||||
suite = options.get("suite", "bookworm")
|
||||
mirror = options.get("mirror", "http://deb.debian.org/debian")
|
||||
components = options.get("components", ["main", "contrib", "non-free"])
|
||||
output_dir = options.get("output_dir", ".")
|
||||
|
||||
if not package_name:
|
||||
print("No package name specified")
|
||||
return 1
|
||||
|
||||
# Create output directory
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Set up apt sources
|
||||
setup_apt_sources(tree, suite, mirror, components)
|
||||
|
||||
# Update package lists
|
||||
if not update_package_lists(tree):
|
||||
return 1
|
||||
|
||||
# Download source package
|
||||
if not download_source_package(package_name, suite, mirror, output_dir):
|
||||
return 1
|
||||
|
||||
# Write source info
|
||||
source_info = {
|
||||
"package": package_name,
|
||||
"suite": suite,
|
||||
"mirror": mirror,
|
||||
"components": components,
|
||||
"output_dir": output_dir
|
||||
}
|
||||
|
||||
info_file = os.path.join(output_dir, "debian-source.json")
|
||||
with open(info_file, "w") as f:
|
||||
json.dump(source_info, f, indent=2)
|
||||
|
||||
print(f"Source package {package_name} downloaded successfully")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = osbuild.api.arguments()
|
||||
r = main(args["tree"], args["options"])
|
||||
sys.exit(r)
|
||||
57
stages/org.osbuild.debian.source.meta.json
Normal file
57
stages/org.osbuild.debian.source.meta.json
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"name": "org.osbuild.debian.source",
|
||||
"version": "1",
|
||||
"description": "Download and manage Debian source packages",
|
||||
"options": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string",
|
||||
"description": "Name of the Debian source package to download"
|
||||
},
|
||||
"suite": {
|
||||
"type": "string",
|
||||
"default": "bookworm",
|
||||
"description": "Debian suite for the package"
|
||||
},
|
||||
"mirror": {
|
||||
"type": "string",
|
||||
"default": "http://deb.debian.org/debian",
|
||||
"description": "Debian mirror for package sources"
|
||||
},
|
||||
"components": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": ["main", "contrib", "non-free"],
|
||||
"description": "Debian repository components to use"
|
||||
},
|
||||
"output_dir": {
|
||||
"type": "string",
|
||||
"default": ".",
|
||||
"description": "Directory for downloaded source packages"
|
||||
}
|
||||
},
|
||||
"required": ["package"]
|
||||
},
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"devices": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"mounts": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"capabilities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": ["CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_FOWNER", "CAP_FSETID", "CAP_MKNOD", "CAP_SETGID", "CAP_SETUID"]
|
||||
}
|
||||
}
|
||||
144
stages/org.osbuild.sbuild
Normal file
144
stages/org.osbuild.sbuild
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#!/usr/bin/python3
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
import shutil
|
||||
import json
|
||||
|
||||
import osbuild.api
|
||||
|
||||
|
||||
def run_sbuild_command(cmd, cwd=None, env=None):
|
||||
"""Run sbuild command and return result"""
|
||||
if env is None:
|
||||
env = {}
|
||||
|
||||
result = subprocess.run(cmd, cwd=cwd, env=env, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"Error running sbuild command: {' '.join(cmd)}")
|
||||
print(f"stdout: {result.stdout}")
|
||||
print(f"stderr: {result.stderr}")
|
||||
return False, result.stderr
|
||||
|
||||
return True, result.stdout
|
||||
|
||||
|
||||
def create_sbuild_chroot(tree, suite, arch, mirror):
|
||||
"""Create sbuild chroot for building packages"""
|
||||
|
||||
chroot_name = f"{suite}-{arch}-sbuild"
|
||||
|
||||
# Create sbuild chroot
|
||||
cmd = ["sbuild-createchroot", "--arch", arch, suite, chroot_name, mirror]
|
||||
|
||||
print(f"Creating sbuild chroot: {' '.join(cmd)}")
|
||||
|
||||
success, output = run_sbuild_command(cmd)
|
||||
if not success:
|
||||
return False, None
|
||||
|
||||
print(f"Created sbuild chroot: {chroot_name}")
|
||||
return True, chroot_name
|
||||
|
||||
|
||||
def build_package_with_sbuild(chroot_name, source_dir, output_dir):
|
||||
"""Build package using sbuild"""
|
||||
|
||||
# Change to source directory
|
||||
os.chdir(source_dir)
|
||||
|
||||
# Run sbuild
|
||||
cmd = ["sbuild", "--arch", "amd64", "--dist", chroot_name.split("-")[0], "."]
|
||||
|
||||
print(f"Building package with sbuild: {' '.join(cmd)}")
|
||||
|
||||
success, output = run_sbuild_command(cmd)
|
||||
if not success:
|
||||
return False
|
||||
|
||||
# Copy built packages to output directory
|
||||
for file in os.listdir("."):
|
||||
if file.endswith(".deb") or file.endswith(".dsc") or file.endswith(".tar.gz"):
|
||||
src = os.path.join(source_dir, file)
|
||||
dst = os.path.join(output_dir, file)
|
||||
shutil.copy2(src, dst)
|
||||
print(f"Copied: {file}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def setup_sbuild_config(tree, chroot_name):
|
||||
"""Set up sbuild configuration for the chroot"""
|
||||
|
||||
sbuild_conf_dir = f"{tree}/etc/sbuild"
|
||||
os.makedirs(sbuild_conf_dir, exist_ok=True)
|
||||
|
||||
# Create sbuild configuration
|
||||
sbuild_conf = f"""# sbuild configuration for {chroot_name}
|
||||
$build_environment = 'chroot';
|
||||
$build_arch_all = 1;
|
||||
$build_source = 1;
|
||||
$build_binary = 1;
|
||||
$build_arch_any = 1;
|
||||
$build_indep = 1;
|
||||
$build_dep = 1;
|
||||
$build_conf = 1;
|
||||
$build_progress = 1;
|
||||
$build_verbose = 1;
|
||||
"""
|
||||
|
||||
conf_file = os.path.join(sbuild_conf_dir, "sbuild.conf")
|
||||
with open(conf_file, "w") as f:
|
||||
f.write(sbuild_conf)
|
||||
|
||||
print(f"Created sbuild configuration: {conf_file}")
|
||||
|
||||
|
||||
def main(tree, options):
|
||||
"""Main function for sbuild stage"""
|
||||
|
||||
# Get options
|
||||
suite = options.get("suite", "bookworm")
|
||||
arch = options.get("arch", "amd64")
|
||||
mirror = options.get("mirror", "http://deb.debian.org/debian")
|
||||
source_dir = options.get("source_dir", ".")
|
||||
output_dir = options.get("output_dir", ".")
|
||||
|
||||
# Create output directory
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Create sbuild chroot
|
||||
success, chroot_name = create_sbuild_chroot(tree, suite, arch, mirror)
|
||||
if not success:
|
||||
return 1
|
||||
|
||||
# Set up sbuild configuration
|
||||
setup_sbuild_config(tree, chroot_name)
|
||||
|
||||
# Build package
|
||||
if not build_package_with_sbuild(chroot_name, source_dir, output_dir):
|
||||
return 1
|
||||
|
||||
# Write build info
|
||||
build_info = {
|
||||
"chroot": chroot_name,
|
||||
"suite": suite,
|
||||
"arch": arch,
|
||||
"mirror": mirror,
|
||||
"output_dir": output_dir
|
||||
}
|
||||
|
||||
info_file = os.path.join(output_dir, "sbuild-build.json")
|
||||
with open(info_file, "w") as f:
|
||||
json.dump(build_info, f, indent=2)
|
||||
|
||||
print("sbuild package building completed successfully")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = osbuild.api.arguments()
|
||||
r = main(args["tree"], args["options"])
|
||||
sys.exit(r)
|
||||
54
stages/org.osbuild.sbuild.meta.json
Normal file
54
stages/org.osbuild.sbuild.meta.json
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "org.osbuild.sbuild",
|
||||
"version": "1",
|
||||
"description": "Build Debian packages using sbuild chroot environments",
|
||||
"options": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"suite": {
|
||||
"type": "string",
|
||||
"default": "bookworm",
|
||||
"description": "Debian suite for the build environment"
|
||||
},
|
||||
"arch": {
|
||||
"type": "string",
|
||||
"default": "amd64",
|
||||
"description": "Target architecture for building"
|
||||
},
|
||||
"mirror": {
|
||||
"type": "string",
|
||||
"default": "http://deb.debian.org/debian",
|
||||
"description": "Debian mirror for chroot creation"
|
||||
},
|
||||
"source_dir": {
|
||||
"type": "string",
|
||||
"default": ".",
|
||||
"description": "Directory containing package source"
|
||||
},
|
||||
"output_dir": {
|
||||
"type": "string",
|
||||
"default": ".",
|
||||
"description": "Directory for built packages"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"devices": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"mounts": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"capabilities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": ["CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_FOWNER", "CAP_FSETID", "CAP_MKNOD", "CAP_SETGID", "CAP_SETUID", "CAP_SYS_CHROOT"]
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue