diff --git a/internal/actions/cmd/changefinder/README.md b/internal/actions/cmd/changefinder/README.md index d9f29857af4d..29dc8b3d6a43 100644 --- a/internal/actions/cmd/changefinder/README.md +++ b/internal/actions/cmd/changefinder/README.md @@ -20,6 +20,8 @@ The available flags are as follows: * `-content-pattern=[regex]`: A regex to match on diff contents. * `-commit-message=[commit message]`: Message to use in the nested commit block * `-commit-scope=[conventional commit scope]`: Scope to use for the commit e.g. `fix` + * `-touch`: touches the `CHANGES.md` file to elicit a submodule change - only + works when used with `-format=commit` Example usages from this repo root: @@ -33,3 +35,34 @@ go run ./internal/actions/cmd/changefinder -q -format=github # quiet mode, github format, github var name "foo" go run ./internal/actions/cmd/changefinder -q -format=github -gh-var=foo ``` + +## Example using `-touch` + +The `-touch` flag is best used when attempting to generate nested commits for an +already submitted change. For example, a GAPIC generator change touches every +gapic module, but the PR doesn't have nested commits for each changed module. +The PR is submitted as is, perhaps because it was included with a bunch of other +changes or for timing purposes, and the nested commits were not added with +`changefinder` while the PR was open. In this case, we can do the following +using `changefinder`: + +1. checkout the merged commit with the target changes: `git checkout ` +2. "save" this to a branch: `git checkout -b changed` +3. checkout the commit just before the target commit: `git checkout ` +4. "save" this to a branch : `git checkout -b base` +5. checkout the changes: `git checkout changed` +6. generate the nested commits + touch each module: +``` +go run ./internal/actions/cmd/changefinder -q \ + -format=commit \ + -commit-scope=fix \ + -commit-message="describe the change" \ + -touch +``` +7. checkout main, new branch, commit: +``` +git checkout main && \ + git checkout -b bump-modules && \ + git commit -a -m 'chore: bump changed modules' && \ + git push +``` diff --git a/internal/actions/cmd/changefinder/main.go b/internal/actions/cmd/changefinder/main.go index 80962a420775..b49421adcc9f 100644 --- a/internal/actions/cmd/changefinder/main.go +++ b/internal/actions/cmd/changefinder/main.go @@ -21,6 +21,7 @@ import ( "fmt" "os" "os/exec" + "path" "strings" "cloud.google.com/go/internal/actions/logg" @@ -37,6 +38,7 @@ var ( contentPattern = flag.String("content-regex", "", "regular expression to execute against contents of diff") commitMessage = flag.String("commit-message", "", "message to use with the module in nested commit format") commitScope = flag.String("commit-scope", "", "scope to use in commit message - only for format=commit") + touch = flag.Bool("touch", false, "touches the CHANGES.md file to elicit a submodule change - only works when used with -format=commit") ) func main() { @@ -45,6 +47,9 @@ func main() { if *format == "commit" && (*commitMessage == "" || *commitScope == "") { logg.Fatalf("requested format=commit and missing commit-message or commit-scope") } + if *touch && *format != "commit" { + logg.Fatalf("requested modules be touched without using format=commit") + } rootDir, err := os.Getwd() if err != nil { logg.Fatal(err) @@ -79,6 +84,11 @@ func main() { logg.Printf("changes in submodule: %s", submodDir) updatedSubmoduleDirs = append(updatedSubmoduleDirs, submodDir) modulesSeen[submodDir] = true + if *touch { + if err := touchModule(rootDir, submodDir); err != nil { + logg.Printf("error touching module %q: %v", submodDir, err) + } + } } } @@ -168,3 +178,23 @@ func gitFilesChanges(dir string) ([]string, error) { logg.Printf("Files changed:\n%s", b) return strings.Split(string(b), "\n"), nil } + +func touchModule(root, mod string) error { + c := exec.Command("echo") + logg.Printf(c.String()) + + f, err := os.OpenFile(path.Join(root, mod, "CHANGES.md"), os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer f.Close() + c.Stdout = f + + err = c.Run() + if err != nil { + return err + } + + logg.Printf("Module touched: %s", mod) + return nil +}