Skip to content

Commit

Permalink
fix: generate_file.context=root not handled in the safeguards.
Browse files Browse the repository at this point in the history
Signed-off-by: i4k <[email protected]>
  • Loading branch information
i4ki committed Sep 23, 2024
1 parent e57310e commit 3f027d4
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 56 deletions.
2 changes: 0 additions & 2 deletions e2etests/core/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,7 @@ func TestE2EGenerateRespectsWorkingDirectory(t *testing.T) {
).String()

runFromDir := func(t *testing.T, generateWd string, runWd string, wantGenerate generate.Report, wantRun RunExpected) {
t.Helper()
t.Run(fmt.Sprintf("terramate -C %s generate", generateWd), func(t *testing.T) {
t.Helper()
t.Parallel()
s := sandbox.NoGit(t, true)
s.BuildTree([]string{
Expand Down
2 changes: 1 addition & 1 deletion e2etests/core/safeguard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ func TestSafeguardCheckRemoteDisabled(t *testing.T) {
})
})

t.Run("re-enabled from config.disable_safegaurds by --disable-safeguards=none",
t.Run("re-enabled from config.disable_safeguards by --disable-safeguards=none",
func(t *testing.T) {
tmcli, file, s := setup(t)

Expand Down
116 changes: 66 additions & 50 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ func doStackGeneration(
report := Report{}

for _, cfg := range tree.Stacks() {
stack, err := cfg.Stack()
st, err := cfg.Stack()
if err != nil {
report.BootstrapErr = err
return report
}

globals := globals.ForStack(root, stack)
globals := globals.ForStack(root, st)
if err := globals.AsError(); err != nil {
report.addFailure(cfg.Dir(), err)
continue
Expand Down Expand Up @@ -532,75 +532,60 @@ func DetectOutdated(root *config.Root, target *config.Tree, vendorDir project.Pa

logger.Debug().Msg("checking outdated code inside stacks")

for _, stackTree := range target.Stacks() {
st, err := stackTree.Stack()
if err != nil {
return nil, err
}
outdated, err := stackOutdated(root, stackTree, vendorDir)
for _, cfg := range target.AsList() {
outdated, err := stackOutdated(root, cfg, vendorDir)
if err != nil {
errs.Append(err)
continue
}

// We want results relative to root
stackRelPath := st.Dir.String()[1:]
dirRelPath := cfg.Dir().String()[1:]
for _, file := range outdated {
outdatedFiles = append(outdatedFiles,
path.Join(stackRelPath, file))
path.Join(dirRelPath, file))
}
}

// If the base dir is a stack then there is no need to check orphaned files.
// All files are owned by the parent stack or its children.
if target.IsStack() {
logger.Debug().Msg("project root is stack, no need to check for orphaned files")

sort.Strings(outdatedFiles)
return outdatedFiles, nil
}

logger.Debug().Msg("checking for orphaned files")

orphanedFiles, err := ListGenFiles(root, target.HostDir())
if err != nil {
errs.Append(err)
}

if err := errs.AsError(); err != nil {
return nil, err
}

outdatedFiles = append(outdatedFiles, orphanedFiles...)
sort.Strings(outdatedFiles)
return outdatedFiles, nil
}

// stackOutdated will verify if a given stack has outdated code and return a list
// stackOutdated will verify if a given directory has outdated code and return a list
// of filenames that are outdated, ordered lexicographically.
// If the stack has an invalid configuration it will return an error.
func stackOutdated(
root *config.Root,
cfg *config.Tree,
vendorDir project.Path,
) ([]string, error) {
func stackOutdated(root *config.Root, cfg *config.Tree, vendorDir project.Path) ([]string, error) {
logger := log.With().
Str("action", "generate.stackOutdated").
Stringer("stack", cfg.Dir()).
Logger()

generated, err := loadStackCodeCfgs(root, cfg, vendorDir, nil)
if err != nil {
return nil, err
cfgpath := cfg.HostDir()

var generated []GenFile
if cfg.IsStack() {
stackGenerated, err := loadStackCodeCfgs(root, cfg, vendorDir, nil)
if err != nil {
return nil, err
}
err = validateStackGeneratedFiles(root, cfgpath, stackGenerated)
if err != nil {
return nil, err
}
generated = append(generated, stackGenerated...)
}

stackpath := cfg.HostDir()
err = validateStackGeneratedFiles(root, stackpath, generated)
rootGenerated, err := loadRootCodeCfgs(root, cfg)
if err != nil {
return nil, err
}

genfilesOnFs, err := ListGenFiles(root, stackpath)
generated = append(generated, rootGenerated...)

genfilesOnFs, err := ListGenFiles(root, cfgpath)
if err != nil {
return nil, errors.E(err, "checking for outdated code")
}
Expand All @@ -610,24 +595,20 @@ func stackOutdated(
// We start with the assumption that all gen files on the stack
// are outdated and then update the outdated files set as we go.
outdatedFiles := newStringSet(genfilesOnFs...)
err = updateOutdatedFiles(stackpath, generated, outdatedFiles)
err = updateOutdatedFiles(root, cfgpath, generated, outdatedFiles)
if err != nil {
return nil, errors.E(err, "checking for outdated files")
return nil, errors.E(err, "handling detected files")
}

outdated := outdatedFiles.slice()
sort.Strings(outdated)
return outdated, nil
}

func updateOutdatedFiles(
stackpath string,
generated []GenFile,
outdatedFiles *stringSet,
) error {
func updateOutdatedFiles(root *config.Root, cfgpath string, generated []GenFile, outdatedFiles *stringSet) error {
logger := log.With().
Str("action", "generate.updateOutdatedFiles").
Str("stack", stackpath).
Str("stack", cfgpath).
Logger()

// So we can properly check blocks with condition false/true in any order
Expand All @@ -638,8 +619,15 @@ func updateOutdatedFiles(
Str("label", genfile.Label()).
Logger()

filename := genfile.Label()
targetpath := filepath.Join(stackpath, filename)
var targetpath string
var filename string
if genfile.Context() == "root" {
filename = genfile.Label()[1:]
targetpath = filepath.Join(root.HostDir(), filename)
} else {
filename = genfile.Label()
targetpath = filepath.Join(cfgpath, filename)
}

currentCode, codeFound, err := readFile(targetpath)
if err != nil {
Expand Down Expand Up @@ -1179,6 +1167,34 @@ func loadAsserts(root *config.Root, st *config.Stack, evalctx *eval.Context) ([]
return asserts, nil
}

func loadRootCodeCfgs(root *config.Root, cfg *config.Tree) ([]GenFile, error) {
blocks := cfg.Node.Generate.Files

genfiles := []GenFile{}
for _, block := range blocks {
if block.Context != "root" {
continue
}
err := validateRootGenerateBlock(root, block)
if err != nil {
return nil, err
}

evalctx := eval.NewContext(stdlib.Functions(cfg.RootDir(), root.Tree().Node.Experiments()))
evalctx.SetNamespace("terramate", root.Runtime())

file, skip, err := genfile.Eval(block, cfg, evalctx)
if err != nil {
return nil, err
}
if skip {
continue
}
genfiles = append(genfiles, file)
}
return genfiles, nil
}

func loadStackCodeCfgs(
root *config.Root,
cfg *config.Tree,
Expand Down
5 changes: 2 additions & 3 deletions generate/outdated_detection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func TestOutdatedDetection(t *testing.T) {
},
},
{
name: "generate blocks content changed",
name: "generate_file block content changed",
steps: []step{
{
layout: []string{
Expand Down Expand Up @@ -397,7 +397,7 @@ func TestOutdatedDetection(t *testing.T) {
},
},
{
name: "generate_hcl is detected on ex stack",
name: "generate_hcl/generate_file deletes on deleted stack",
steps: []step{
{
layout: []string{
Expand Down Expand Up @@ -1273,7 +1273,6 @@ func TestOutdatedDetection(t *testing.T) {
}

got, err := generate.DetectOutdated(s.Config(), s.Config().Tree(), vendorDir)

assert.IsError(t, err, step.wantErr)
if err != nil {
continue
Expand Down

0 comments on commit 3f027d4

Please sign in to comment.