Repository: GoogleCloudPlatform/k8s-config-connector
Pull request #4153: conductor: create commit messages that are unique/descriptive
Author: login: justinsb
Labels: name: lgtm
name: approved
Created: 2025-03-22T12:51:29Z | Merged: 2025-03-22T23:01:05Z



Diff:
diff --git a/experiments/conductor/cmd/runner/runner.go b/experiments/conductor/cmd/runner/runner.go
index f2105cc31a7..88b3c5277be 100644
--- a/experiments/conductor/cmd/runner/runner.go
+++ b/experiments/conductor/cmd/runner/runner.go
@@ -341,33 +341,33 @@ func RunRunner(ctx context.Context, opts *RunnerOptions) error {
 		}
 	case cmdPushBranch: // 9
 		processors := []BranchProcessor{
-			{Fn: makeReadyPR, CommitMsg: "make ready-pr"},
-			{Fn: pushBranch, CommitMsg: "push branch"},
+			{Fn: makeReadyPR, CommitMsgTemplate: "make ready-pr"},
+			{Fn: pushBranch, CommitMsgTemplate: "push branch"},
 		}
 		processBranches(ctx, opts, branches.Branches, "Pushing Branch", processors)
 	case cmdCreateScriptYaml: // 10
-		processBranches(ctx, opts, branches.Branches, "Script YAML", []BranchProcessor{{Fn: createScriptYaml, CommitMsg: "Create gcloud script.yaml"}})
+		processBranches(ctx, opts, branches.Branches, "Script YAML", []BranchProcessor{{Fn: createScriptYaml, CommitMsgTemplate: "mockgcp: create test script for {{command}}"}})
 	case cmdCaptureHttpLog: // 11
-		processBranches(ctx, opts, branches.Branches, "HTTP Log", []BranchProcessor{{Fn: captureHttpLog, CommitMsg: "Capture HTTP Log for mocks"}})
+		processBranches(ctx, opts, branches.Branches, "HTTP Log", []BranchProcessor{{Fn: captureHttpLog, CommitMsgTemplate: "mockgcp: golden output for TestScripts/mock{{group}}/testdata/{{resource}}/crud"}})
 	case cmdGenerateMockGo: // 12
-		processBranches(ctx, opts, branches.Branches, "Mock Go Files", []BranchProcessor{{Fn: generateMockGo, CommitMsg: "Add generated mock files"}})
+		processBranches(ctx, opts, branches.Branches, "Mock Go Files", []BranchProcessor{{Fn: generateMockGo, CommitMsgTemplate: "Add generated mock files"}})
 	case cmdAddServiceRoundTrip: // 13
-		processBranches(ctx, opts, branches.Branches, "Service RoundTrip", []BranchProcessor{{Fn: addServiceToRoundTrip, CommitMsg: "Add service to mock_http_roundtrip.go"}})
+		processBranches(ctx, opts, branches.Branches, "Service RoundTrip", []BranchProcessor{{Fn: addServiceToRoundTrip, CommitMsgTemplate: "mockgcp: Add mock{{group}} service to mock_http_roundtrip.go"}})
 	case cmdAddProtoMakefile: // 14
-		processBranches(ctx, opts, branches.Branches, "Proto Makefile", []BranchProcessor{{Fn: addProtoToMakefile, CommitMsg: "Add proto generation to makefile", AttemptsOnNoChange: 1}})
+		processBranches(ctx, opts, branches.Branches, "Proto Makefile", []BranchProcessor{{Fn: addProtoToMakefile, CommitMsgTemplate: "Add proto generation to makefile", AttemptsOnNoChange: 1}})
 	case cmdBuildProto: // 15
-		processBranches(ctx, opts, branches.Branches, "Build Proto", []BranchProcessor{{Fn: buildProtoFiles, CommitMsg: "Build and add generated proto files"}})
+		processBranches(ctx, opts, branches.Branches, "Build Proto", []BranchProcessor{{Fn: buildProtoFiles, CommitMsgTemplate: "Build and add generated proto files"}})
 	case cmdRunMockTests: // 16
-		processBranches(ctx, opts, branches.Branches, "Mock Tests", []BranchProcessor{{Fn: fixMockgcpFailures, CommitMsg: "Verify and Fix mock tests", VerifyFn: runMockgcpTests, VerifyAttempts: 5, AttemptsOnNoChange: 2}})
+		processBranches(ctx, opts, branches.Branches, "Mock Tests", []BranchProcessor{{Fn: fixMockgcpFailures, CommitMsgTemplate: "Verify and Fix mock tests", VerifyFn: runMockgcpTests, VerifyAttempts: 5, AttemptsOnNoChange: 2}})
 	case cmdGenerateTypes: // 20
-		processBranches(ctx, opts, branches.Branches, "Types", []BranchProcessor{{Fn: generateTypes, CommitMsg: "Add generated types"}})
+		processBranches(ctx, opts, branches.Branches, "Types", []BranchProcessor{{Fn: generateTypes, CommitMsgTemplate: "Add generated types"}})
 	case cmdAdjustTypes: // 21
 		processors := []BranchProcessor{
-			{Fn: setTypeSpecStatus, CommitMsg: "Add spec and status to generated type"},
-			{Fn: setTypeParent, CommitMsg: "Add parent to generated type"},
-			{Fn: adjustIdentityParent, CommitMsg: "Adjust identity parent"},
+			{Fn: setTypeSpecStatus, CommitMsgTemplate: "Add spec and status to generated type"},
+			{Fn: setTypeParent, CommitMsgTemplate: "Add parent to generated type"},
+			{Fn: adjustIdentityParent, CommitMsgTemplate: "Adjust identity parent"},
 			//{Fn: adjustIdentityParentNewFunction, CommitMsg: "Adjust identity parent NewIdentity method"},
-			{Fn: regenerateTypes, CommitMsg: "Regenerate types"},
+			{Fn: regenerateTypes, CommitMsgTemplate: "Regenerate types"},
 			// preferred manual: Add something for Capitalization of Abbreviations: any acronyms that are not all caps should be all caps
 			// manual: Add something to handle references to other resources: https://github.com/GoogleCloudPlatform/k8s-config-connector/pull/4010/commits/1651a0a7af5bca37b5c2e134dd3f600ebac6a172
 			// * https://github.com/GoogleCloudPlatform/k8s-config-connector/pull/4017/commits/cc726106aff55d41e6bc94272acc3612f2636397
@@ -375,28 +375,28 @@ func RunRunner(ctx context.Context, opts *RunnerOptions) error {
 		}
 		processBranches(ctx, opts, branches.Branches, "Adjusting types", processors)
 	case cmdGenerateCRD: // 22
-		processBranches(ctx, opts, branches.Branches, "CRD", []BranchProcessor{{Fn: generateCRD, CommitMsg: "Add generated CRD"}})
+		processBranches(ctx, opts, branches.Branches, "CRD", []BranchProcessor{{Fn: generateCRD, CommitMsgTemplate: "Add generated CRD"}})
 	case cmdGenerateMapper: // 23
-		processBranches(ctx, opts, branches.Branches, "Mapper", []BranchProcessor{{Fn: generateMapper, CommitMsg: "Add generated mapper"}})
+		processBranches(ctx, opts, branches.Branches, "Mapper", []BranchProcessor{{Fn: generateMapper, CommitMsgTemplate: "Add generated mapper"}})
 		// handle references to other resources: https://github.com/GoogleCloudPlatform/k8s-config-connector/pull/4010/commits/1651a0a7af5bca37b5c2e134dd3f600ebac6a172
 	case cmdGenerateFuzzer: // 24
-		processBranches(ctx, opts, branches.Branches, "Fuzzer", []BranchProcessor{{Fn: generateFuzzer, CommitMsg: "Add generated fuzzer"}})
+		processBranches(ctx, opts, branches.Branches, "Fuzzer", []BranchProcessor{{Fn: generateFuzzer, CommitMsgTemplate: "Add generated fuzzer"}})
 	case cmdControllerClient: // 40
-		processBranches(ctx, opts, branches.Branches, "Controller Client", []BranchProcessor{{Fn: generateControllerClient, CommitMsg: "Add controller client"}})
+		processBranches(ctx, opts, branches.Branches, "Controller Client", []BranchProcessor{{Fn: generateControllerClient, CommitMsgTemplate: "Add controller client"}})
 	case cmdGenerateController: // 41
-		processBranches(ctx, opts, branches.Branches, "Controller", []BranchProcessor{{Fn: generateController, CommitMsg: "Add controller"}})
+		processBranches(ctx, opts, branches.Branches, "Controller", []BranchProcessor{{Fn: generateController, CommitMsgTemplate: "Add controller"}})
 	case cmdCreateIdentity: // 43
 		processBranches(ctx, opts, branches.Branches, "Identity and Reference", []BranchProcessor{
-			{Fn: generateControllerIdentity, CommitMsg: "Add controller identity"},
-			{Fn: generateControllerReference, CommitMsg: "Add controller reference"},
+			{Fn: generateControllerIdentity, CommitMsgTemplate: "Add controller identity"},
+			{Fn: generateControllerReference, CommitMsgTemplate: "Add controller reference"},
 		})
 	case cmdControllerCreateTest: // 44
 		processBranches(ctx, opts, branches.Branches, "Controller Test", []BranchProcessor{
-			{Fn: createControllerTest, CommitMsg: "Create minimal test"},
-			{Fn: updateTestHarness, CommitMsg: "Support for testing with mockgcp"},
+			{Fn: createControllerTest, CommitMsgTemplate: "Create minimal test"},
+			{Fn: updateTestHarness, CommitMsgTemplate: "Support for testing with mockgcp"},
 		})
 	case cmdCaptureGoldenTestOutput: // 45
-		processBranches(ctx, opts, branches.Branches, "Golden Test Output", []BranchProcessor{{Fn: captureGoldenTestOutput, CommitMsg: "Capture golden output"}})
+		processBranches(ctx, opts, branches.Branches, "Golden Test Output", []BranchProcessor{{Fn: captureGoldenTestOutput, CommitMsgTemplate: "Capture golden output"}})
 	default:
 		log.Fatalf("unrecognized command: %d", opts.command)
 	}
diff --git a/experiments/conductor/cmd/runner/utilities.go b/experiments/conductor/cmd/runner/utilities.go
index dd27ef190e5..771b7226163 100644
--- a/experiments/conductor/cmd/runner/utilities.go
+++ b/experiments/conductor/cmd/runner/utilities.go
@@ -207,7 +207,7 @@ func gitAdd(ctx context.Context, workDir string, files ...string) error {
 
 func gitCommit(ctx context.Context, workDir string, msg string) error {
 	log.Printf("COMMAND: git commit -m %q", msg)
-	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", fmt.Sprintf("conductor: %q", msg))
+	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", msg)
 	gitcommit.Dir = workDir
 
 	results, err := execCommand(gitcommit)
@@ -551,19 +551,27 @@ func stageChanges(ctx context.Context, opts *RunnerOptions, paths []string, comm
 
 type BranchProcessorFn func(ctx context.Context, opts *RunnerOptions, branch Branch, execResults *ExecResults) ([]string, *ExecResults, error)
 type BranchProcessor struct {
-	CommitMsg          string
+	CommitMsgTemplate  string
 	Fn                 BranchProcessorFn
 	AttemptsOnNoChange int
 	VerifyFn           BranchProcessorFn
 	VerifyAttempts     int
 }
 
+func (b *BranchProcessor) CommitMsg(branch Branch) string {
+	s := b.CommitMsgTemplate
+	s = strings.ReplaceAll(s, "{{command}}", branch.Command)
+	s = strings.ReplaceAll(s, "{{group}}", branch.Group)
+	s = strings.ReplaceAll(s, "{{resource}}", branch.Resource)
+	return s
+}
+
 // runBranchFnWithRetries runs the processor multiple times until changes are detected and commits them
 func runBranchFnWithRetriesAndCommit(ctx context.Context, opts *RunnerOptions, branch Branch, description string, processor BranchProcessor, commitMsg string, inExecResults *ExecResults) (*ExecResults, error) {
 	// Try running processor up to N times until we see changes in all affected paths
 	var execResults *ExecResults
 	if commitMsg == "" {
-		commitMsg = processor.CommitMsg
+		commitMsg = processor.CommitMsg(branch)
 	}
 	maxAttempts := processor.AttemptsOnNoChange
 	if maxAttempts == 0 {
@@ -639,7 +647,7 @@ func runBranchFnWithRetriesAndCommit(ctx context.Context, opts *RunnerOptions, b
 
 // processBranch handles the processing of a single branch
 func processBranch(ctx context.Context, opts *RunnerOptions, branch Branch, description string, processor BranchProcessor) error {
-	log.Printf("Processing branch %s: %s, processor: %s", branch.Name, description, processor.CommitMsg)
+	log.Printf("Processing branch %s: %s, processor: %s", branch.Name, description, processor.CommitMsg(branch))
 
 	// Skip if branch should be skipped
 	if branch.Skip {
@@ -662,17 +670,17 @@ func processBranch(ctx context.Context, opts *RunnerOptions, branch Branch, desc
 		var err error
 		paths, execResults, err := processor.VerifyFn(ctx, opts, branch, nil)
 		if execResults == nil {
-			log.Printf("execResults is nil for branch %s, commit message: %s", branch.Name, processor.CommitMsg)
+			log.Printf("execResults is nil for branch %s, commit message: %s", branch.Name, processor.CommitMsg(branch))
 			continue
 		}
 		if execResults.ExitCode == 0 {
-			log.Printf("Verification attempt %d succeeded for branch %s, commit message: %s", i+1, branch.Name, processor.CommitMsg)
+			log.Printf("Verification attempt %d succeeded for branch %s, commit message: %s", i+1, branch.Name, processor.CommitMsg(branch))
 			break
 		}
 		if err != nil {
-			log.Printf("Verification attempt %d Error: %v for branch %s, commit message: %s", i+1, err, branch.Name, processor.CommitMsg)
+			log.Printf("Verification attempt %d Error: %v for branch %s, commit message: %s", i+1, err, branch.Name, processor.CommitMsg(branch))
 		} else {
-			log.Printf("Verification attempt %d failed for branch %s, commit message: %s", i+1, branch.Name, processor.CommitMsg)
+			log.Printf("Verification attempt %d failed for branch %s, commit message: %s", i+1, branch.Name, processor.CommitMsg(branch))
 		}
 		if len(paths) != 0 {
 			// Revert the changes for the failed verification
@@ -683,8 +691,8 @@ func processBranch(ctx context.Context, opts *RunnerOptions, branch Branch, desc
 				}
 			}
 		}
-		log.Printf("Verification attempt %d failed for branch %s, commit message: %s", i+1, branch.Name, processor.CommitMsg)
-		commitMsg := fmt.Sprintf("Autofix attempt %d. %s", i+1, processor.CommitMsg)
+		log.Printf("Verification attempt %d failed for branch %s, commit message: %s", i+1, branch.Name, processor.CommitMsg(branch))
+		commitMsg := fmt.Sprintf("Autofix attempt %d. %s", i+1, processor.CommitMsg(branch))
 		_, err = runBranchFnWithRetriesAndCommit(ctx, opts, branch, description, processor, commitMsg, execResults)
 		if err != nil {
 			log.Printf("Failed to run branch %s: %v", branch.Name, err)


Reviews:
user: login: jingyih
body: Thank you for improving this!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-22T20:52:27Z
user: login: justinsb
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-22T22:48:32Z
user: login: justinsb
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-22T22:50:06Z
user: login: jingyih
body: /lgtm
/approve
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-22T23:00:29Z

Review comments:
diff_hunk: @@ -207,7 +207,7 @@ func gitAdd(ctx context.Context, workDir string, files ...string) error {
 
 func gitCommit(ctx context.Context, workDir string, msg string) error {
 	log.Printf("COMMAND: git commit -m %q", msg)
-	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", fmt.Sprintf("conductor: %q", msg))
+	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", msg)
path: experiments/conductor/cmd/runner/utilities.go
user: login: jingyih
body: We probably still want to include something like `autogen: "` to indicate that this is a generated commit, or should we rely solely on the commit message?
created_at: 2025-03-22T20:48:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -341,62 +341,62 @@ func RunRunner(ctx context.Context, opts *RunnerOptions) error {
 		}
 	case cmdPushBranch: // 9
 		processors := []BranchProcessor{
-			{Fn: makeReadyPR, CommitMsg: "make ready-pr"},
-			{Fn: pushBranch, CommitMsg: "push branch"},
+			{Fn: makeReadyPR, CommitMsgTemplate: "make ready-pr"},
+			{Fn: pushBranch, CommitMsgTemplate: "push branch"},
 		}
 		processBranches(ctx, opts, branches.Branches, "Pushing Branch", processors)
 	case cmdCreateScriptYaml: // 10
-		processBranches(ctx, opts, branches.Branches, "Script YAML", []BranchProcessor{{Fn: createScriptYaml, CommitMsg: "Create gcloud script.yaml"}})
+		processBranches(ctx, opts, branches.Branches, "Script YAML", []BranchProcessor{{Fn: createScriptYaml, CommitMsgTemplate: "mockgcp: create test script for {{command}}"}})
 	case cmdCaptureHttpLog: // 11
-		processBranches(ctx, opts, branches.Branches, "HTTP Log", []BranchProcessor{{Fn: captureHttpLog, CommitMsg: "Capture HTTP Log for mocks"}})
+		processBranches(ctx, opts, branches.Branches, "HTTP Log", []BranchProcessor{{Fn: captureHttpLog, CommitMsgTemplate: "mockgcp: golden output for TestScripts/mock{{group}}/testdata/{{resource}}/crud"}})
path: experiments/conductor/cmd/runner/runner.go
user: login: jingyih
body: Other commands face the same issue. For example, "Add proto generation to makefile", "Add generated types". I’m thinking maybe we just prefix every commit in conductor with {{group}} and {{resource}}?
created_at: 2025-03-22T20:52:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -207,7 +207,7 @@ func gitAdd(ctx context.Context, workDir string, files ...string) error {
 
 func gitCommit(ctx context.Context, workDir string, msg string) error {
 	log.Printf("COMMAND: git commit -m %q", msg)
-	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", fmt.Sprintf("conductor: %q", msg))
+	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", msg)
path: experiments/conductor/cmd/runner/utilities.go
user: login: justinsb
body: So if the commit is automatically generated by running a script, yes, we should include autogen.  (And I think I've started doing that)

But when the code is generated by an LLM, that's a little different.  We do expect some manual edits, and I `git commit --fixup` those commits.  I don't think in the long term we will be able to draw the line here, like we don't include `[autocomplete]` when we are using autocomplete.  We could include a co-author statement (`Co-Author: Gemini 2.0 Flash`), but TBH  I think even that is redundant today.
created_at: 2025-03-22T22:48:31Z
author_association: COLLABORATOR
diff_hunk: @@ -341,62 +341,62 @@ func RunRunner(ctx context.Context, opts *RunnerOptions) error {
 		}
 	case cmdPushBranch: // 9
 		processors := []BranchProcessor{
-			{Fn: makeReadyPR, CommitMsg: "make ready-pr"},
-			{Fn: pushBranch, CommitMsg: "push branch"},
+			{Fn: makeReadyPR, CommitMsgTemplate: "make ready-pr"},
+			{Fn: pushBranch, CommitMsgTemplate: "push branch"},
 		}
 		processBranches(ctx, opts, branches.Branches, "Pushing Branch", processors)
 	case cmdCreateScriptYaml: // 10
-		processBranches(ctx, opts, branches.Branches, "Script YAML", []BranchProcessor{{Fn: createScriptYaml, CommitMsg: "Create gcloud script.yaml"}})
+		processBranches(ctx, opts, branches.Branches, "Script YAML", []BranchProcessor{{Fn: createScriptYaml, CommitMsgTemplate: "mockgcp: create test script for {{command}}"}})
 	case cmdCaptureHttpLog: // 11
-		processBranches(ctx, opts, branches.Branches, "HTTP Log", []BranchProcessor{{Fn: captureHttpLog, CommitMsg: "Capture HTTP Log for mocks"}})
+		processBranches(ctx, opts, branches.Branches, "HTTP Log", []BranchProcessor{{Fn: captureHttpLog, CommitMsgTemplate: "mockgcp: golden output for TestScripts/mock{{group}}/testdata/{{resource}}/crud"}})
path: experiments/conductor/cmd/runner/runner.go
user: login: justinsb
body: That could work, though conductor will evolve over time and I think the commit messages should be about what we are doing, not the tools we used to create the code.
created_at: 2025-03-22T22:50:06Z
author_association: COLLABORATOR
diff_hunk: @@ -207,7 +207,7 @@ func gitAdd(ctx context.Context, workDir string, files ...string) error {
 
 func gitCommit(ctx context.Context, workDir string, msg string) error {
 	log.Printf("COMMAND: git commit -m %q", msg)
-	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", fmt.Sprintf("conductor: %q", msg))
+	gitcommit := exec.CommandContext(ctx, "git", "commit", "-m", msg)
path: experiments/conductor/cmd/runner/utilities.go
user: login: jingyih
body: Yeah this makes sense.
created_at: 2025-03-22T23:00:23Z
author_association: CONTRIBUTOR

PR comments:
user: login: google-oss-prow[bot]
created_at: 2025-03-22T23:00:48Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/GoogleCloudPlatform/k8s-config-connector/pull/4153#pullrequestreview-2708392154" title="Approved">jingyih</a>*

The full list of commands accepted by this bot can be found [here](https://oss.gprow.dev/command-help?repo=GoogleCloudPlatform%2Fk8s-config-connector).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[experiments/OWNERS](https://github.com/GoogleCloudPlatform/k8s-config-connector/blob/master/experiments/OWNERS)~~ [jingyih]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR