deb-bootc-compose/internal/phases/ostree.go
robojerk cca68c90f6 Add comprehensive phase system, types, and treefile support for deb-bootc-compose
- Add internal/phases/ with complete phase management system
- Add internal/types/ with core data structures
- Add internal/treefile/ for OSTree treefile generation
- Update examples with YAML configurations
- Update .gitignore to properly exclude test artifacts and build outputs
- Update dependencies and configuration files
2025-08-19 20:48:46 -07:00

203 lines
6.2 KiB
Go

package phases
import (
"fmt"
"os"
"path/filepath"
"time"
"deb-bootc-compose/internal/types"
)
// OSTreePhase handles OSTree commit creation and repository management
type OSTreePhase struct {
PhaseBase
}
// NewOSTreePhase creates a new OSTreePhase
func NewOSTreePhase() *OSTreePhase {
return &OSTreePhase{
PhaseBase: NewPhaseBase("ostree", []string{"build"}),
}
}
// Run executes the OSTree phase
func (p *OSTreePhase) Run(engine types.Engine) error {
logger := engine.GetLogger()
logger.Printf("Starting OSTree phase...")
// Get package information from treefile
treefile := engine.GetTreefile()
// Process each variant and architecture
for _, variant := range treefile.Variants {
for _, arch := range variant.Architectures {
logger.Printf("Processing variant %s for architecture %s", variant.Name, arch)
// Get packages for this variant/architecture combination
packages := treefile.GetPackagesForVariant(variant.Name, arch)
// Create OSTree commit using apt-ostree
ref := treefile.GetOSTreeRef(variant.Name, arch)
subject := fmt.Sprintf("Debian %s %s variant for %s", treefile.Release, variant.Name, arch)
body := fmt.Sprintf("Debian %s %s variant for %s architecture\nGenerated by deb-bootc-compose", treefile.Release, variant.Name, arch)
// Collect all package names
allPackages := make([]string, 0)
allPackages = append(allPackages, packages.Required...)
allPackages = append(allPackages, packages.Optional...)
allPackages = append(allPackages, packages.Recommended...)
allPackages = append(allPackages, packages.Development...)
allPackages = append(allPackages, packages.Kernel...)
allPackages = append(allPackages, packages.Bootloader...)
commitID, err := engine.GetOSTreeTool().CreateCommit(ref, subject, body, allPackages)
if err != nil {
return fmt.Errorf("failed to create OSTree commit for variant %s/%s: %w", variant.Name, arch, err)
}
// Create variant-specific work directory
variantWorkDir := filepath.Join(engine.GetWorkDir(), "variants", variant.Name, arch)
if err := os.MkdirAll(variantWorkDir, 0755); err != nil {
return fmt.Errorf("failed to create variant work directory: %w", err)
}
// Write commit information
if err := p.writeCommitInfo(variantWorkDir, ref, commitID, subject, body, allPackages); err != nil {
return fmt.Errorf("failed to write commit info for variant %s/%s: %w", variant.Name, arch, err)
}
logger.Printf("Completed OSTree commit for variant %s/%s: %s", variant.Name, arch, commitID)
}
}
logger.Printf("OSTree phase completed successfully")
return nil
}
// createOSTreeCommit creates an OSTree commit for a specific variant and architecture
func (p *OSTreePhase) createOSTreeCommit(engine types.Engine, workDir string, variant types.Variant, arch string) error {
logger := engine.GetLogger()
ostreeTool := engine.GetOSTreeTool()
// Get packages for this variant
packages := engine.GetTreefile().GetPackagesForVariant(variant.Name, arch)
// Generate OSTree reference
ref := engine.GetTreefile().GetOSTreeRef(variant.Name, arch)
// Generate commit subject and body
subject := fmt.Sprintf("Debian %s %s variant for %s",
engine.GetTreefile().Release,
variant.Name,
arch)
body := fmt.Sprintf(`Debian %s %s variant for %s architecture
Generated by deb-bootc-compose
Timestamp: %s
Variant: %s
Architecture: %s
Packages included:
- Required: %d
- Optional: %d
- Recommended: %d
- Development: %d
- Kernel: %d
- Bootloader: %d`,
engine.GetTreefile().Release,
variant.Name,
arch,
time.Now().Format(time.RFC3339),
variant.Name,
arch,
len(packages.Required),
len(packages.Optional),
len(packages.Recommended),
len(packages.Development),
len(packages.Kernel),
len(packages.Bootloader))
// Collect all package names
allPackages := make([]string, 0)
allPackages = append(allPackages, packages.Required...)
allPackages = append(allPackages, packages.Optional...)
allPackages = append(allPackages, packages.Recommended...)
allPackages = append(allPackages, packages.Development...)
allPackages = append(allPackages, packages.Kernel...)
allPackages = append(allPackages, packages.Bootloader...)
// Remove duplicates
uniquePackages := make(map[string]bool)
for _, pkg := range allPackages {
uniquePackages[pkg] = true
}
uniqueList := make([]string, 0, len(uniquePackages))
for pkg := range uniquePackages {
uniqueList = append(uniqueList, pkg)
}
// Create OSTree commit
logger.Printf("Creating OSTree commit for reference: %s", ref)
commitID, err := ostreeTool.CreateCommit(ref, subject, body, uniqueList)
if err != nil {
return fmt.Errorf("failed to create OSTree commit: %w", err)
}
// Update the reference to point to the new commit
if err := ostreeTool.UpdateRef(ref, commitID); err != nil {
return fmt.Errorf("failed to update OSTree reference: %w", err)
}
// Validate the commit
if err := ostreeTool.ValidateCommit(commitID); err != nil {
return fmt.Errorf("failed to validate OSTree commit: %w", err)
}
// Write commit information
if err := p.writeCommitInfo(workDir, ref, commitID, subject, body, uniqueList); err != nil {
return fmt.Errorf("failed to write commit information: %w", err)
}
logger.Printf("Successfully created OSTree commit %s for reference %s", commitID, ref)
return nil
}
// writeCommitInfo writes commit information to files
func (p *OSTreePhase) writeCommitInfo(workDir string, ref, commitID, subject, body string, packages []string) error {
// Write commit details
commitFile := filepath.Join(workDir, "commit-info.txt")
content := fmt.Sprintf(`OSTree Commit Information
Reference: %s
Commit ID: %s
Subject: %s
Timestamp: %s
Body:
%s
Packages (%d):
`, ref, commitID, subject, time.Now().Format(time.RFC3339), body, len(packages))
for _, pkg := range packages {
content += fmt.Sprintf(" - %s\n", pkg)
}
if err := os.WriteFile(commitFile, []byte(content), 0644); err != nil {
return fmt.Errorf("failed to write commit info: %w", err)
}
// Write package list
packagesFile := filepath.Join(workDir, "packages.txt")
pkgContent := ""
for _, pkg := range packages {
pkgContent += pkg + "\n"
}
if err := os.WriteFile(packagesFile, []byte(pkgContent), 0644); err != nil {
return fmt.Errorf("failed to write packages list: %w", err)
}
return nil
}