this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(controller): minor clean up

+18 -57
+1 -14
controller/activities/git.go
··· 19 19 return "", err 20 20 } 21 21 22 - // Clone the repository 23 22 cmd := exec.CommandContext(ctx, "git", "clone", "--branch", revision, url, path) 24 23 if err := cmd.Run(); err != nil { 25 24 return "", err ··· 32 31 logger := activity.GetLogger(ctx) 33 32 logger.Info("Getting changed files", "path", path, "oldRevision", oldRevision) 34 33 35 - // Get changed files using git diff --name-only 36 34 cmd := exec.CommandContext(ctx, "git", "diff", "--name-only", oldRevision, "HEAD") 37 35 cmd.Dir = path 38 36 output, err := cmd.Output() ··· 40 38 return nil, err 41 39 } 42 40 43 - // Split output by newlines and filter empty lines 44 41 lines := strings.Split(strings.TrimSpace(string(output)), "\n") 45 42 var files []string 46 43 for _, line := range lines { ··· 57 54 logger := activity.GetLogger(ctx) 58 55 logger.Info("Getting changed modules", "path", repoPath, "oldRevision", oldRevision) 59 56 60 - // Get all changed files 61 57 changedFiles, err := changedFiles(ctx, repoPath, oldRevision) 62 58 if err != nil { 63 59 return nil, err 64 60 } 65 61 66 62 seen := make(map[string]struct{}) 67 - modules := make([]string, 0) 63 + var modules []string 68 64 69 65 for _, file := range changedFiles { 70 - // Get the directory of the changed file 71 66 dir := filepath.Dir(file) 72 67 73 - // Walk up the directory tree to find the closest directory containing terragrunt.hcl 74 68 currentDir := dir 75 69 for { 76 70 terragruntPath := filepath.Join(repoPath, currentDir, "terragrunt.hcl") 77 71 if _, err := os.Stat(terragruntPath); err == nil { 78 - // Found terragrunt.hcl, this is a module directory 79 72 modulePath := currentDir 80 73 81 - // Remove infra/<env>/ prefix if present 82 74 if strings.HasPrefix(modulePath, "infra/") { 83 75 parts := strings.Split(filepath.ToSlash(modulePath), "/") 84 76 if len(parts) >= 3 && parts[0] == "infra" { 85 - // Remove "infra" and environment (e.g., "dev", "prod") 86 77 modulePath = strings.Join(parts[2:], "/") 87 78 } 88 79 } 89 80 90 - // Skip empty paths 91 81 if modulePath != "" && modulePath != "." { 92 - // Normalize path separators to forward slashes 93 82 modulePath = filepath.ToSlash(modulePath) 94 83 95 84 if _, exists := seen[modulePath]; !exists { ··· 100 89 break 101 90 } 102 91 103 - // Move up one directory level 104 92 parent := filepath.Dir(currentDir) 105 93 if parent == currentDir || parent == "." { 106 - // Reached the root, no terragrunt.hcl found 107 94 break 108 95 } 109 96 currentDir = parent
+12 -25
controller/activities/graph.go
··· 155 155 var b strings.Builder 156 156 b.WriteString("digraph {\n") 157 157 158 - // Write edges first (they implicitly declare nodes) 159 158 for src, dests := range g.Edges { 160 159 for _, dest := range dests { 161 160 b.WriteString(fmt.Sprintf(" %q -> %q;\n", src, dest)) 162 161 } 163 162 } 164 163 165 - // Write standalone nodes (nodes without edges) 164 + // Write standalone nodes (those not in any edge) 165 + edgeNodes := make(map[string]bool) 166 + for src, dests := range g.Edges { 167 + edgeNodes[src] = true 168 + for _, dest := range dests { 169 + edgeNodes[dest] = true 170 + } 171 + } 172 + 166 173 for node := range g.Nodes { 167 - hasEdge := false 168 - // Check if node appears in any edge 169 - if _, exists := g.Edges[node]; exists { 170 - hasEdge = true 171 - } 172 - if !hasEdge { 173 - for _, dests := range g.Edges { 174 - for _, dest := range dests { 175 - if dest == node { 176 - hasEdge = true 177 - break 178 - } 179 - } 180 - if hasEdge { 181 - break 182 - } 183 - } 184 - } 185 - if !hasEdge { 174 + if !edgeNodes[node] { 186 175 b.WriteString(fmt.Sprintf(" %q;\n", node)) 187 176 } 188 177 } ··· 191 180 return b.String() 192 181 } 193 182 194 - // TopologicalSort returns modules grouped by dependency levels. 195 - // Modules in the same level can be executed in parallel. 196 - // Each level must complete before the next level can start. 197 - // An edge from A to B means A depends on B, so B must run before A. 183 + // TopologicalSort returns modules grouped by dependency levels for parallel execution. 184 + // Edge from A to B means A depends on B, so B must run before A. 198 185 func (g *Graph) TopologicalSort() [][]string { 199 186 // Build adjacency list and in-degree count 200 187 adjList := make(map[string][]string)
+2 -12
controller/activities/terragrunt.go
··· 28 28 return graph, nil 29 29 } 30 30 31 - func TerragruntGraphShaking(ctx context.Context, graph *Graph, changedFiles []string) (*Graph, error) { 32 - logger := activity.GetLogger(ctx) 33 - 34 - logger.Info("Pruning Terragrunt DAG graph") 35 - 36 - prunedGraph, err := PruneGraph(ctx, graph, changedFiles) 37 - if err != nil { 38 - return nil, fmt.Errorf("failed to prune dependency graph: %w", err) 39 - } 40 - 41 - return prunedGraph, nil 31 + func TerragruntPrune(ctx context.Context, graph *Graph, changedFiles []string) (*Graph, error) { 32 + return PruneGraph(ctx, graph, changedFiles) 42 33 } 43 34 44 35 func TerragruntApply(ctx context.Context, repoPath string, modulePath string, stack string) error { 45 36 logger := activity.GetLogger(ctx) 46 37 logger.Info("Running terragrunt apply", "module", modulePath, "stack", stack) 47 38 48 - // Construct the full path to the module 49 39 fullPath := filepath.Join(repoPath, "infra", stack, modulePath) 50 40 51 41 cmd := exec.CommandContext(ctx, "terragrunt", "apply", "--backend-bootstrap", "--auto-approve")
+2 -1
controller/worker/main.go
··· 6 6 7 7 "cloudlab/controller/activities" 8 8 "cloudlab/controller/workflows" 9 + 9 10 "go.temporal.io/sdk/client" 10 11 "go.temporal.io/sdk/worker" 11 12 ) ··· 26 27 w.RegisterActivity(activities.Clone) 27 28 w.RegisterActivity(activities.ChangedModules) 28 29 w.RegisterActivity(activities.TerragruntGraph) 29 - w.RegisterActivity(activities.TerragruntGraphShaking) 30 + w.RegisterActivity(activities.TerragruntPrune) 30 31 w.RegisterActivity(activities.TerragruntApply) 31 32 32 33 err = w.Run(worker.InterruptCh())
+1 -5
controller/workflows/infra.go
··· 53 53 } 54 54 55 55 var prunedGraph *activities.Graph 56 - err = workflow.ExecuteActivity(ctx, activities.TerragruntGraphShaking, graph, changedModules).Get(ctx, &prunedGraph) 56 + err = workflow.ExecuteActivity(ctx, activities.TerragruntPrune, graph, changedModules).Get(ctx, &prunedGraph) 57 57 if err != nil { 58 58 logger.Error("Activity failed.", "Error", err) 59 59 return nil, err ··· 61 61 62 62 logger.Info("Infra workflow completed graph pruning.", "nodes", prunedGraph.NodeCount(), "edges", prunedGraph.EdgeCount()) 63 63 64 - // Get dependency levels for parallel execution 65 64 dependencyLevels := prunedGraph.TopologicalSort() 66 65 67 - // Execute terragrunt apply for each level in dependency order 68 66 for levelIndex, level := range dependencyLevels { 69 67 logger.Info("Starting terragrunt apply for dependency level", "level", levelIndex, "modules", level) 70 68 71 - // Create futures for parallel execution within this level 72 69 var futures []workflow.Future 73 70 for _, moduleName := range level { 74 71 moduleActivityOptions := workflow.ActivityOptions{ ··· 81 78 futures = append(futures, future) 82 79 } 83 80 84 - // Wait for all modules in this level to complete 85 81 for i, future := range futures { 86 82 err := future.Get(ctx, nil) 87 83 if err != nil {