- 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
161 lines
4.7 KiB
Go
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
|
|
}
|