deb-bootc-compose/internal/phases/init.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

161 lines
4.7 KiB
Go

package phases
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
"deb-bootc-compose/internal/types"
)
// InitPhase handles the initial setup of the compose process
type InitPhase struct {
PhaseBase
}
// NewInitPhase creates a new InitPhase
func NewInitPhase() *InitPhase {
return &InitPhase{
PhaseBase: NewPhaseBase("init", nil),
}
}
// Run executes the init phase
func (p *InitPhase) Run(engine types.Engine) error {
logger := engine.GetLogger()
logger.Printf("Initializing compose environment")
// Create necessary directories
dirs := []string{
engine.GetWorkDir(),
filepath.Join(engine.GetWorkDir(), "packages"),
filepath.Join(engine.GetWorkDir(), "ostree"),
filepath.Join(engine.GetWorkDir(), "build"),
filepath.Join(engine.GetWorkDir(), "cache"),
filepath.Join(engine.GetWorkDir(), "logs"),
}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
}
logger.Printf("Created directory: %s", dir)
}
// Write compose metadata
if err := p.writeComposeMetadata(engine); err != nil {
return fmt.Errorf("failed to write compose metadata: %w", err)
}
// Initialize OSTree repository if needed
if err := p.initializeOSTreeRepo(engine); err != nil {
return fmt.Errorf("failed to initialize OSTree repository: %w", err)
}
// Validate build system connection
if err := p.validateBuildSystem(engine); err != nil {
return fmt.Errorf("failed to validate build system: %w", err)
}
logger.Printf("Init phase completed successfully")
return nil
}
// writeComposeMetadata writes compose metadata files
func (p *InitPhase) writeComposeMetadata(engine types.Engine) error {
logger := engine.GetLogger()
config := engine.GetConfig()
treefile := engine.GetTreefile()
// Write COMPOSE_ID file
composeID := fmt.Sprintf("%s-%s-%s", config.Release.Short, config.Release.Version, treefile.Name)
composeIDPath := filepath.Join(engine.GetOutputDir(), "COMPOSE_ID")
if err := os.WriteFile(composeIDPath, []byte(composeID), 0644); err != nil {
return fmt.Errorf("failed to write COMPOSE_ID: %w", err)
}
logger.Printf("Wrote COMPOSE_ID: %s", composeID)
// Write compose info
composeInfo := map[string]interface{}{
"compose_id": composeID,
"release": map[string]interface{}{
"name": config.Release.Name,
"short": config.Release.Short,
"version": config.Release.Version,
"type": config.Release.Type,
},
"treefile": map[string]interface{}{
"name": treefile.Name,
"version": treefile.Version,
"description": treefile.Description,
"release": treefile.Release,
},
"timestamp": time.Now().Format(time.RFC3339),
}
// Convert to JSON and write
composeInfoPath := filepath.Join(engine.GetWorkDir(), "compose-info.json")
composeInfoData, err := json.MarshalIndent(composeInfo, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal compose info: %w", err)
}
if err := os.WriteFile(composeInfoPath, composeInfoData, 0644); err != nil {
return fmt.Errorf("failed to write compose info: %w", err)
}
logger.Printf("Wrote compose info: %s", composeInfoPath)
return nil
}
// initializeOSTreeRepo initializes the OSTree repository
func (p *InitPhase) initializeOSTreeRepo(engine types.Engine) error {
logger := engine.GetLogger()
config := engine.GetConfig()
if config.OSTree.Repository == "" {
logger.Printf("No OSTree repository specified, skipping initialization")
return nil
}
// Check if repository exists
if _, err := os.Stat(config.OSTree.Repository); os.IsNotExist(err) {
// Create repository directory
if err := os.MkdirAll(config.OSTree.Repository, 0755); err != nil {
return fmt.Errorf("failed to create OSTree repository directory: %w", err)
}
logger.Printf("Created OSTree repository directory: %s", config.OSTree.Repository)
// Initialize repository using apt-ostree
ostreeTool := engine.GetOSTreeTool()
if err := ostreeTool.InitRepo(); err != nil {
return fmt.Errorf("failed to initialize OSTree repository: %w", err)
}
logger.Printf("Initialized OSTree repository")
} else {
logger.Printf("OSTree repository already exists: %s", config.OSTree.Repository)
}
return nil
}
// validateBuildSystem validates the build system connection
func (p *InitPhase) validateBuildSystem(engine types.Engine) error {
logger := engine.GetLogger()
buildSystem := engine.GetBuildSystem()
if buildSystem == nil {
logger.Printf("No build system configured, skipping validation")
return nil
}
// Test connection to build system
if err := buildSystem.TestConnection(); err != nil {
return fmt.Errorf("build system connection test failed: %w", err)
}
logger.Printf("Build system connection validated successfully")
return nil
}