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
This commit is contained in:
parent
57bb8aafbe
commit
cca68c90f6
18 changed files with 2543 additions and 717 deletions
169
internal/phases/output.go
Normal file
169
internal/phases/output.go
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
package phases
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"deb-bootc-compose/internal/types"
|
||||
)
|
||||
|
||||
// OutputPhase handles generating final output artifacts
|
||||
type OutputPhase struct {
|
||||
PhaseBase
|
||||
}
|
||||
|
||||
// NewOutputPhase creates a new OutputPhase
|
||||
func NewOutputPhase() *OutputPhase {
|
||||
return &OutputPhase{
|
||||
PhaseBase: NewPhaseBase("output", []string{"ostree"}),
|
||||
}
|
||||
}
|
||||
|
||||
// Run executes the output phase
|
||||
func (p *OutputPhase) Run(engine types.Engine) error {
|
||||
logger := engine.GetLogger()
|
||||
logger.Printf("Starting output generation phase")
|
||||
|
||||
// Get output manager
|
||||
outputManager := engine.GetOutputManager()
|
||||
if outputManager == nil {
|
||||
logger.Printf("No output manager configured, skipping output phase")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get treefile and process variants
|
||||
treefile := engine.GetTreefile()
|
||||
|
||||
for _, variant := range treefile.Variants {
|
||||
for _, arch := range variant.Architectures {
|
||||
logger.Printf("Generating output for variant %s on architecture %s", variant.Name, arch)
|
||||
|
||||
// Create output work directory
|
||||
outputWorkDir := filepath.Join(engine.GetWorkDir(), "variants", variant.Name, arch, "output")
|
||||
if err := os.MkdirAll(outputWorkDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create output work directory: %w", err)
|
||||
}
|
||||
|
||||
// Generate outputs for this variant/architecture
|
||||
if err := p.generateOutputs(engine, outputWorkDir, variant, arch); err != nil {
|
||||
return fmt.Errorf("failed to generate outputs for variant %s on architecture %s: %w", variant.Name, arch, err)
|
||||
}
|
||||
|
||||
logger.Printf("Completed output generation for variant %s on architecture %s", variant.Name, arch)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Printf("Output generation phase completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateOutputs generates all configured output formats
|
||||
func (p *OutputPhase) generateOutputs(engine types.Engine, workDir string, variant types.Variant, arch string) error {
|
||||
logger := engine.GetLogger()
|
||||
outputManager := engine.GetOutputManager()
|
||||
|
||||
// Get OSTree reference
|
||||
ref := engine.GetTreefile().GetOSTreeRef(variant.Name, arch)
|
||||
|
||||
// Get output configuration
|
||||
outputConfig := engine.GetTreefile().Output
|
||||
|
||||
// Generate container image if requested
|
||||
if p.containsFormat(outputConfig.Formats, "container") {
|
||||
logger.Printf("Generating container image for variant %s on architecture %s", variant.Name, arch)
|
||||
|
||||
containerConfig := map[string]interface{}{
|
||||
"base_image": outputConfig.Container.BaseImage,
|
||||
"labels": outputConfig.Container.Labels,
|
||||
"entrypoint": outputConfig.Container.Entrypoint,
|
||||
"cmd": outputConfig.Container.CMD,
|
||||
}
|
||||
|
||||
containerPath := filepath.Join(workDir, "container")
|
||||
if err := outputManager.GenerateContainerImage(ref, containerPath, containerConfig); err != nil {
|
||||
logger.Printf("Warning: failed to generate container image: %v", err)
|
||||
} else {
|
||||
logger.Printf("Successfully generated container image")
|
||||
}
|
||||
}
|
||||
|
||||
// Generate disk image if requested
|
||||
if p.containsFormat(outputConfig.Formats, "disk") {
|
||||
logger.Printf("Generating disk image for variant %s on architecture %s", variant.Name, arch)
|
||||
|
||||
diskConfig := map[string]interface{}{
|
||||
"size": outputConfig.DiskImage.Size,
|
||||
"formats": outputConfig.DiskImage.Formats,
|
||||
"bootloader": outputConfig.DiskImage.Bootloader,
|
||||
"kernel": outputConfig.DiskImage.Kernel,
|
||||
"initramfs": outputConfig.DiskImage.Initramfs,
|
||||
}
|
||||
|
||||
diskPath := filepath.Join(workDir, "disk")
|
||||
if err := outputManager.GenerateDiskImage(ref, diskPath, diskConfig); err != nil {
|
||||
logger.Printf("Warning: failed to generate disk image: %v", err)
|
||||
} else {
|
||||
logger.Printf("Successfully generated disk image")
|
||||
}
|
||||
}
|
||||
|
||||
// Generate tarball if requested
|
||||
if p.containsFormat(outputConfig.Formats, "tarball") {
|
||||
logger.Printf("Generating tarball for variant %s on architecture %s", variant.Name, arch)
|
||||
|
||||
tarballConfig := map[string]interface{}{
|
||||
"compression": "gzip",
|
||||
"format": "tar.gz",
|
||||
}
|
||||
|
||||
tarballPath := filepath.Join(workDir, "tarball")
|
||||
if err := outputManager.GenerateTarball(ref, tarballPath, tarballConfig); err != nil {
|
||||
logger.Printf("Warning: failed to generate tarball: %v", err)
|
||||
} else {
|
||||
logger.Printf("Successfully generated tarball")
|
||||
}
|
||||
}
|
||||
|
||||
// Write output summary
|
||||
if err := p.writeOutputSummary(workDir, variant, arch, outputConfig.Formats); err != nil {
|
||||
return fmt.Errorf("failed to write output summary: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// containsFormat checks if a format is in the list
|
||||
func (p *OutputPhase) containsFormat(formats []string, format string) bool {
|
||||
for _, f := range formats {
|
||||
if f == format {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// writeOutputSummary writes a summary of generated outputs
|
||||
func (p *OutputPhase) writeOutputSummary(workDir string, variant types.Variant, arch string, formats []string) error {
|
||||
summaryFile := filepath.Join(workDir, "output-summary.txt")
|
||||
|
||||
summary := fmt.Sprintf(`Output Generation Summary
|
||||
Variant: %s
|
||||
Architecture: %s
|
||||
Timestamp: %s
|
||||
Formats: %v
|
||||
|
||||
Generated outputs:
|
||||
`, variant.Name, arch, time.Now().Format(time.RFC3339), formats)
|
||||
|
||||
for _, format := range formats {
|
||||
summary += fmt.Sprintf(" - %s\n", format)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(summaryFile, []byte(summary), 0644); err != nil {
|
||||
return fmt.Errorf("failed to write output summary: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue