- Notifications
You must be signed in to change notification settings - Fork1.1k
feat: warn when .terraform.lock.hcl is modified during terraform init#18276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
1ef78b6262c9f2c16008fa45984db397d1e085d462File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -4,6 +4,8 @@ | ||
| "bufio" | ||
| "bytes" | ||
| "context" | ||
| "crypto/sha256" | ||
| "encoding/hex" | ||
| "encoding/json" | ||
| "fmt" | ||
| "io" | ||
| @@ -222,6 +224,16 @@ | ||
| e.mut.Lock() | ||
| defere.mut.Unlock() | ||
| // Save .terraform.lock.hcl content before running terraform init | ||
| lockFilePath:=getTerraformLockFilePath(e.workdir) | ||
| preInitLockFile:=lockFilePath+".pre-init" | ||
| // Copy the lock file if it exists | ||
| iflockFileData,err:=os.ReadFile(lockFilePath);err==nil { | ||
| _=os.WriteFile(preInitLockFile,lockFileData,0644) | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more.
| ||
| deferos.Remove(preInitLockFile)// Clean up temporary file | ||
| } | ||
| outWriter,doneOut:=logWriter(logr,proto.LogLevel_DEBUG) | ||
| errWriter,doneErr:=logWriter(logr,proto.LogLevel_ERROR) | ||
| deferfunc() { | ||
| @@ -242,6 +254,28 @@ | ||
| } | ||
| err:=e.execWriteOutput(ctx,killCtx,args,e.basicEnv(),outWriter,errBuf) | ||
| // Check if .terraform.lock.hcl was modified after terraform init | ||
| diff:=generateFileDiff(preInitLockFile,lockFilePath) | ||
| ifdiff!="" { | ||
| // Log informational message about lock file changes with diff | ||
| infoMsg:="INFO: .terraform.lock.hcl was modified during 'terraform init'. "+ | ||
| "This is normal when Terraform downloads providers or updates dependencies. "+ | ||
| "See https://developer.hashicorp.com/terraform/language/files/dependency-lock#understanding-lock-file-changes "+ | ||
| "for more information about lock file changes." | ||
| // Write info message to debug stream | ||
| ifoutWriter!=nil { | ||
| _,_=outWriter.Write([]byte(infoMsg+"\n")) | ||
| _,_=outWriter.Write([]byte("\nLock file changes:\n"+diff+"\n")) | ||
| } | ||
| e.logger.Info(ctx,"terraform lock file modified during init", | ||
| slog.F("lock_file_path",lockFilePath), | ||
| slog.F("diff",diff), | ||
| ) | ||
| } | ||
| varexitErr*exec.ExitError | ||
| ifxerrors.As(err,&exitErr) { | ||
| ifbytes.Contains(errBuf.b.Bytes(), []byte("text file busy")) { | ||
| @@ -259,6 +293,73 @@ | ||
| returnfilepath.Join(workdir,"terraform.tfstate") | ||
| } | ||
| funcgetTerraformLockFilePath(workdirstring)string { | ||
| returnfilepath.Join(workdir,".terraform.lock.hcl") | ||
| } | ||
| // calculateFileChecksum calculates the SHA256 checksum of a file. | ||
| // Returns empty string if file doesn't exist or can't be read. | ||
| funccalculateFileChecksum(filePathstring)string { | ||
| data,err:=os.ReadFile(filePath) | ||
| iferr!=nil { | ||
| return"" | ||
| } | ||
| hash:=sha256.Sum256(data) | ||
| returnhex.EncodeToString(hash[:]) | ||
| } | ||
| // generateFileDiff generates a simple diff between two file contents. | ||
| // Returns empty string if files can't be read or are identical. | ||
| funcgenerateFileDiff(beforePath,afterPathstring)string { | ||
| beforeData,err:=os.ReadFile(beforePath) | ||
| iferr!=nil { | ||
| return"" | ||
| } | ||
| afterData,err:=os.ReadFile(afterPath) | ||
| iferr!=nil { | ||
| return"" | ||
| } | ||
| ifbytes.Equal(beforeData,afterData) { | ||
| return"" | ||
| } | ||
| // Simple line-by-line diff | ||
| beforeLines:=strings.Split(string(beforeData),"\n") | ||
| afterLines:=strings.Split(string(afterData),"\n") | ||
| vardiff strings.Builder | ||
| diff.WriteString("--- .terraform.lock.hcl (before terraform init)\n") | ||
| diff.WriteString("+++ .terraform.lock.hcl (after terraform init)\n") | ||
| // Simple diff showing added/removed lines | ||
| beforeMap:=make(map[string]bool) | ||
| for_,line:=rangebeforeLines { | ||
| beforeMap[line]=true | ||
| } | ||
| afterMap:=make(map[string]bool) | ||
| for_,line:=rangeafterLines { | ||
| afterMap[line]=true | ||
| } | ||
| // Show removed lines | ||
| for_,line:=rangebeforeLines { | ||
| if!afterMap[line]&&strings.TrimSpace(line)!="" { | ||
| diff.WriteString("- "+line+"\n") | ||
| } | ||
| } | ||
| // Show added lines | ||
| for_,line:=rangeafterLines { | ||
| if!beforeMap[line]&&strings.TrimSpace(line)!="" { | ||
| diff.WriteString("+ "+line+"\n") | ||
| } | ||
| } | ||
| returndiff.String() | ||
| } | ||
| // revive:disable-next-line:flag-parameter | ||
| func (e*executor)plan(ctx,killCtx context.Context,env,vars []string,logrlogSink,metadata*proto.Metadata) (*proto.PlanComplete,error) { | ||
| ctx,span:=e.server.startTrace(ctx,tracing.FuncName()) | ||
Uh oh!
There was an error while loading.Please reload this page.