From b26aeabe8afaabcc81f914cac0c627b5d9bb6d79 Mon Sep 17 00:00:00 2001 From: Srevin Saju Date: Thu, 14 Mar 2024 13:06:09 +0530 Subject: [PATCH] feat: forward parent lifecycles to child stages defined on the module In scenarios where lifecycles are defined on the module level, there was an issue preventing the same lifecycle phases from being applied to the child modules. This was very inconvenient when reusing multiple modules and the caller may have custom lifecycle phases, but the module's are not owned by the caller to make changes --- internal/behavior/models.go | 2 ++ internal/ci/module_run.go | 24 +++++++++++++++++++----- internal/ci/run.go | 14 ++++++++++---- tests/togomak.hcl | 30 ++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/internal/behavior/models.go b/internal/behavior/models.go index 3649166..7bc6151 100644 --- a/internal/behavior/models.go +++ b/internal/behavior/models.go @@ -7,6 +7,8 @@ type Child struct { // Parent is the flag to indicate whether the program is running in parent mode Parent string + ParentLifecycles []string + // ParentParams is the list of parameters to be passed to the parent ParentParams []string } diff --git a/internal/ci/module_run.go b/internal/ci/module_run.go index 29ecffd..ba6c7f1 100644 --- a/internal/ci/module_run.go +++ b/internal/ci/module_run.go @@ -163,13 +163,28 @@ func (m *Module) run(conductor *Conductor, source string, evalCtx *hcl.EvalConte }) } + var parentLifecycles []string + if cfg.Behavior.Child.ParentLifecycles != nil { + parentLifecycles = cfg.Behavior.Child.ParentLifecycles + } + if m.Lifecycle != nil { + conductor.Eval().Mutex().RLock() + lifecyclePhases, d := m.Lifecycle.Phase.Value(evalCtx) + conductor.Eval().Mutex().RUnlock() + diags = diags.Extend(d) + for _, phase := range lifecyclePhases.AsValueSlice() { + parentLifecycles = append(parentLifecycles, phase.AsString()) + } + } + b := &behavior.Behavior{ Unattended: conductor.Config.Behavior.Unattended, Ci: conductor.Config.Behavior.Ci, Child: behavior.Child{ - Enabled: true, - Parent: "", - ParentParams: nil, + Enabled: true, + Parent: "", + ParentParams: nil, + ParentLifecycles: parentLifecycles, }, DryRun: false, } @@ -194,8 +209,7 @@ func (m *Module) run(conductor *Conductor, source string, evalCtx *hcl.EvalConte conductorOptions = append(conductorOptions, ConductorWithParser(conductor.Parser)) // populate input variables for the child conductor, which would be passed to the module - attrs, d := m.Body.JustAttributes() - diags = diags.Extend(d) + attrs, _ := m.Body.JustAttributes() for _, attr := range attrs { //we need to evaluate the values first within the parent's evaluation context //before sending it to the child goroutine and child conductor diff --git a/internal/ci/run.go b/internal/ci/run.go index 6f0c8fe..9ee8aa1 100644 --- a/internal/ci/run.go +++ b/internal/ci/run.go @@ -112,10 +112,16 @@ func BlockCanRun(runnable Block, conductor *Conductor, runnableId string, depGra ok = false overridden = false - // if the list is empty, we will assume that the runnable is not overridden + // if the list is empty, we will assume that the runnable is not overridden, // and we will run all module blocks. This is so that the child processoe var phases []cty.Value - var phasesDefined bool + + // if the parent config has lifecycles defined, we will append it to the child + for _, phase := range conductor.Config.Behavior.Child.ParentLifecycles { + phases = append(phases, cty.StringVal(phase)) + } + + var phasesDefined bool = len(phases) > 0 stage := runnable.(PhasedBlock) if stage.LifecycleConfig() != nil { evalContext := conductor.Eval().Context() @@ -126,8 +132,8 @@ func BlockCanRun(runnable Block, conductor *Conductor, runnableId string, depGra diags = diags.Extend(d) return false, false, diags } - phasesDefined = !phaseHcl.IsNull() - phases = phaseHcl.AsValueSlice() + phasesDefined = !phaseHcl.IsNull() || len(phases) > 0 + phases = append(phases, phaseHcl.AsValueSlice()...) } if runnable.Type() == blocks.ModuleBlock && len(phases) == 0 && !phasesDefined { diff --git a/tests/togomak.hcl b/tests/togomak.hcl index 0a944d4..2ea4c83 100644 --- a/tests/togomak.hcl +++ b/tests/togomak.hcl @@ -49,6 +49,36 @@ stage "tests" { } } +stage "module_phase_test" { + pre_hook { + stage { + script = "echo ${ansi.fg.green}${each.key}${ansi.reset}: full" + } + } + + for_each = toset([ + "../examples/module-phases-inheritance/togomak.hcl", + ]) + + depends_on = [stage.build, stage.coverage_prepare] + args = [ + "./togomak_coverage", + "-C", dirname(each.key), + "--ci", "-v", "-v", "-v", + "add" + ] + + env { + name = "GOCOVERDIR" + value = local.coverage_data_dir + } + env { + name = "TOGOMAK_VAR_name" + value = "bot" + } + +} + stage "tests_dry_run" { pre_hook {