deb-bootc-image-builder/scripts/integration-scripts/integrate-apt-ostree.sh
robojerk 126ee1a849
Some checks failed
particle-os CI / Test particle-os (push) Failing after 1s
particle-os CI / Integration Test (push) Has been skipped
particle-os CI / Security & Quality (push) Failing after 1s
Test particle-os Basic Functionality / test-basic (push) Failing after 1s
particle-os CI / Build and Release (push) Has been skipped
cleanup
2025-08-27 12:30:24 -07:00

320 lines
9.7 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Integration script between apt-ostree and deb-bootc-image-builder
# Creates complete Debian Atomic pipeline: treefile → apt-ostree → bootable image
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
WORKSPACE_PATH="/home/rob/Documents/Projects/overseer"
APT_OSTREE_PATH="$WORKSPACE_PATH/apt-ostree"
DEB_BOOTC_PATH="$WORKSPACE_PATH/deb-bootc-image-builder"
ATOMIC_CONFIGS_PATH="$WORKSPACE_PATH/debian-atomic-configs"
TEMP_DIR=$(mktemp -d /tmp/debian-atomic-XXXXXX)
# Functions
log_info() {
echo -e "${BLUE} $1${NC}"
}
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}"
}
cleanup() {
log_info "Cleaning up temporary files..."
if [[ -d "$TEMP_DIR" ]]; then
rm -rf "$TEMP_DIR"
fi
}
# Set up cleanup on exit
trap cleanup EXIT
# Validate paths
validate_paths() {
log_info "Validating required components..."
local missing_paths=()
[[ ! -d "$APT_OSTREE_PATH" ]] && missing_paths+=("apt-ostree")
[[ ! -d "$DEB_BOOTC_PATH" ]] && missing_paths+=("deb-bootc-image-builder")
[[ ! -d "$ATOMIC_CONFIGS_PATH" ]] && missing_paths+=("debian-atomic-configs")
if [[ ${#missing_paths[@]} -gt 0 ]]; then
log_error "Missing required components: ${missing_paths[*]}"
exit 1
fi
log_success "All required components found"
}
# Build apt-ostree if needed
build_apt_ostree() {
local apt_ostree_bin="$APT_OSTREE_PATH/target/debug/apt-ostree"
if [[ ! -f "$apt_ostree_bin" ]]; then
log_info "Building apt-ostree..."
cd "$APT_OSTREE_PATH"
if ! cargo build --bin apt-ostree; then
log_error "Failed to build apt-ostree"
exit 1
fi
log_success "apt-ostree built successfully"
else
log_info "apt-ostree binary found, skipping build"
fi
}
# Build deb-bootc-image-builder if needed
build_deb_bootc() {
local bib_bin="$DEB_BOOTC_PATH/bib/create-ostree-bootable-image"
if [[ ! -f "$bib_bin" ]]; then
log_info "Building deb-bootc-image-builder..."
cd "$DEB_BOOTC_PATH"
if ! go build -o bib/create-ostree-bootable-image ./bib/create-ostree-bootable-image.go; then
log_error "Failed to build deb-bootc-image-builder"
exit 1
fi
log_success "deb-bootc-image-builder built successfully"
else
log_info "deb-bootc-image-builder binary found, skipping build"
fi
}
# Step 1: Create OSTree commit using apt-ostree
create_ostree_commit() {
echo "DEBUG: create_ostree_commit function called with: $1"
local treefile="$1"
local treefile_path="$ATOMIC_CONFIGS_PATH/treefiles/$treefile"
log_info "Step 1: Creating OSTree commit from $treefile"
log_info "Treefile path: $treefile_path"
if [[ ! -f "$treefile_path" ]]; then
log_error "Treefile not found: $treefile_path"
return 1
fi
# Run apt-ostree inside the Debian container where libraries are available
local apt_ostree_bin="$APT_OSTREE_PATH/target/release/apt-ostree"
log_info "Running apt-ostree inside Debian container..."
log_info "apt-ostree binary: $apt_ostree_bin"
# Create a temporary working directory that's shared between host and container
local container_workdir="$TEMP_DIR/apt-ostree-build"
# Run the command in the container and capture output
log_info "Executing: podman run --rm --privileged -v $APT_OSTREE_PATH:/workspace:z -v $ATOMIC_CONFIGS_PATH:/configs:z -v $TEMP_DIR:/shared:z apt-ostree-builder:latest bash -c 'cd /workspace && ./target/release/apt-ostree compose tree /configs/treefiles/$(basename $treefile_path) --workdir /shared/apt-ostree-build'"
local output
local exit_code
output=$(podman run --rm --privileged -v "$APT_OSTREE_PATH:/workspace:z" -v "$ATOMIC_CONFIGS_PATH:/configs:z" -v "$TEMP_DIR:/shared:z" apt-ostree-builder:latest bash -c "cd /workspace && ./target/release/apt-ostree compose tree /configs/treefiles/$(basename $treefile_path) --workdir /shared/apt-ostree-build" 2>&1)
exit_code=$?
log_info "Command completed with exit code: $exit_code"
log_info "Command output:"
echo "$output"
if [[ $exit_code -ne 0 ]]; then
log_error "apt-ostree failed with exit code $exit_code"
return 1
fi
log_success "OSTree commit created successfully"
# apt-ostree creates the repository in the shared workdir
local repo_path="$TEMP_DIR/apt-ostree-build/repo"
log_info "Checking for repository at: $repo_path"
if [[ ! -d "$repo_path" ]]; then
log_error "OSTree repository not found at $repo_path"
return 1
fi
log_info "Repository found, checking commits..."
# Get commit information
local commits_dir="$repo_path/commits"
if [[ ! -d "$commits_dir" ]]; then
log_error "No commits directory found"
return 1
fi
local commits=($(ls "$commits_dir" | grep -E "^commit_"))
log_info "Found commits: ${commits[*]}"
if [[ ${#commits[@]} -eq 0 ]]; then
log_error "No commits found in repository"
return 1
fi
local commit_id="${commits[0]}"
log_info "Selected commit: $commit_id"
# Read metadata if available
local metadata_file="$commits_dir/$commit_id/metadata.json"
if [[ -f "$metadata_file" ]]; then
log_info "Commit metadata:"
cat "$metadata_file" | jq '.' 2>/dev/null || cat "$metadata_file"
fi
log_success "Successfully created commit: $commit_id"
echo "$commit_id"
}
# Step 2: Extract rootfs from OSTree commit and create bootable image
create_bootable_image() {
local commit_id="$1"
local repo_path="/tmp/apt-ostree-build/repo"
log_info "Step 2: Creating bootable image from OSTree commit"
cd "$TEMP_DIR"
# Extract the rootfs from the OSTree commit
local rootfs_path="$TEMP_DIR/rootfs"
log_info "Extracting rootfs from OSTree commit..."
# Use ostree to checkout the commit to a directory
if ! ostree checkout --repo="$repo_path" --subpath=/ "$commit_id" "$rootfs_path"; then
log_error "Failed to extract rootfs from OSTree commit"
exit 1
fi
log_success "Rootfs extracted to: $rootfs_path"
# Verify rootfs structure
if [[ ! -d "$rootfs_path/usr" ]] || [[ ! -d "$rootfs_path/etc" ]]; then
log_error "Invalid rootfs structure"
exit 1
fi
# Create bootable image using deb-bootc-image-builder
local bib_bin="$DEB_BOOTC_PATH/bib/create-ostree-bootable-image"
local output_image="$TEMP_DIR/debian-atomic.img"
log_info "Creating bootable image from rootfs..."
if ! "$bib_bin" "$rootfs_path" "$output_image"; then
log_error "Failed to create bootable image"
exit 1
fi
log_success "Bootable image created successfully"
# Check if image was created
if [[ ! -f "$output_image" ]]; then
log_error "Output image not found: $output_image"
exit 1
fi
# Show image information
local image_size=$(du -h "$output_image" | cut -f1)
log_info "Image created: $output_image ($image_size)"
echo "$output_image"
}
# Main pipeline function
run_pipeline() {
local treefile="$1"
local variant="${2:-minimal}"
log_info "🚀 Starting Debian Atomic pipeline"
log_info "Treefile: $treefile"
log_info "Variant: $variant"
log_info "Working directory: $TEMP_DIR"
# Step 1: Create OSTree commit
log_info "Executing Step 1: Create OSTree commit..."
local commit_id
if ! commit_id=$(create_ostree_commit "$treefile"); then
log_error "Step 1 failed: Could not create OSTree commit"
return 1
fi
log_success "Step 1 completed: OSTree commit $commit_id created"
# Step 2: Create bootable image
log_info "Executing Step 2: Create bootable image..."
local output_image
if ! output_image=$(create_bootable_image "$commit_id"); then
log_error "Step 2 failed: Could not create bootable image"
return 1
fi
log_success "Step 2 completed: Bootable image created"
log_success "🎉 Pipeline completed successfully!"
log_info "Output image: $output_image"
# Copy image to workspace for easy access
local final_image="$WORKSPACE_PATH/debian-atomic-$variant.img"
cp "$output_image" "$final_image"
log_info "Image copied to: $final_image"
# Show testing instructions
echo
log_info "🧪 To test the image:"
echo "qemu-system-x86_64 -m 2G -drive file=$final_image,format=raw -nographic"
echo
log_info "📋 Summary:"
log_success "✅ OSTree commit created from $treefile"
log_success "✅ Bootable image created: $final_image"
log_success "✅ Debian Atomic pipeline completed successfully!"
return 0
}
# Main function
main() {
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <treefile> [variant]"
echo "Example: $0 debian-minimal.yaml minimal"
echo
echo "Available treefiles:"
if [[ -d "$ATOMIC_CONFIGS_PATH/treefiles" ]]; then
ls "$ATOMIC_CONFIGS_PATH/treefiles/"*.yaml 2>/dev/null | sed 's/.*\///' || echo "No treefiles found"
fi
exit 1
fi
local treefile="$1"
local variant="${2:-minimal}"
# Validate and build components
validate_paths
build_apt_ostree
build_deb_bootc
# Run the pipeline
if ! run_pipeline "$treefile" "$variant"; then
log_error "Pipeline failed"
exit 1
fi
log_success "Pipeline completed successfully"
}
# Run main function
main "$@"