diff --git a/main.go b/main.go index e830d76..87f09f1 100644 --- a/main.go +++ b/main.go @@ -844,6 +844,7 @@ func run(c *cli.Context) { RedisClient: sysutil.Redis{Client: rdb}, Runner: &runner, Log: logger.With("logger", "pr-planner"), + WebserverURL: c.String("oidc-callback-url"), } // setup subscription for key set diff --git a/prplanner/msg.go b/prplanner/msg.go index 8e804dc..7279d63 100644 --- a/prplanner/msg.go +++ b/prplanner/msg.go @@ -28,27 +28,16 @@ var ( autoPlanDisabledTml = "Auto plan is disabled for this PR.\n" + "Please post `@terraform-applier plan ` as comment if you want to request terraform plan for a particular module." - requestAcknowledgedMsgTml = "Received terraform plan request\n" + - "```\n" + - "Cluster: %s\n" + - "Module: %s\n" + - "Path: %s\n" + - "Commit ID: %s\n" + - "Requested At: %s\n" + - "```\n" + - "Do not edit this comment. This message will be updated once the plan run is completed.\n" + - "To manually trigger plan again please post `@terraform-applier plan %s` as comment." - - runOutputMsgTml = "Terraform run output for\n" + - "```\n" + - "Cluster: %s\n" + - "Module: %s\n" + - "Path: %s\n" + - "Commit ID: %s\n" + - "```\n" + + requestAcknowledgedMsgTml = "### Received terraform plan request for `%s`\n" + + "🏷️ **Commit:** %s | 🕒 **Requested At:** %s | 🔗 [View in %s dashboard](%s)\n\n" + + "*(Do not edit this comment. This message will be updated once the plan run is completed.)*\n" + + ">To manually trigger plan again please post `@terraform-applier plan %s` as comment." + + runOutputMsgTml = "### Terraform Plan Output for `%s`\n" + + "🏷️ **Commit:** %s | 🔗 [View in %s dashboard](%s)\n\n" + + "> To manually trigger plan again please post `@terraform-applier plan %s` as comment.\n" + "
%s Run Status: %s, Run Summary: %s" + - "\n\n```terraform\n%s\n```\n
\n" + - "\n> To manually trigger plan again please post `@terraform-applier plan %s` as comment." + "\n\n```terraform\n%s\n```\n\n" ) type MsgType string @@ -110,13 +99,15 @@ func parsePlanReqMsg(commentBody string) string { return "" } -func requestAcknowledgedMsg(cluster, module, path, commitID string, reqAt *metav1.Time) string { - display := fmt.Sprintf(requestAcknowledgedMsgTml, cluster, module, path, commitID, reqAt.Format(time.RFC3339), path) +func requestAcknowledgedMsg(cluster string, module types.NamespacedName, path, commitID string, reqAt *metav1.Time, webserverURL string) string { + moduleURL := webserverURL + "/#" + module.Namespace + "_" + module.Name + + display := fmt.Sprintf(requestAcknowledgedMsgTml, module.Name, commitID, reqAt.Format(time.RFC3339), cluster, moduleURL, path) meta := CommentMetadata{ Type: MsgTypePlanRequest, Cluster: cluster, - Module: module, + Module: module.String(), Path: path, CommitID: commitID, ReqAt: reqAt.Format(time.RFC3339), @@ -146,7 +137,7 @@ func parseRunOutputMsg(comment string) (cluster string, module types.NamespacedN return meta.Cluster, parseNamespaceName(meta.Module), meta.Path, meta.CommitID } -func runOutputMsg(cluster, module, path string, run *v1beta1.Run) string { +func runOutputMsg(cluster string, module types.NamespacedName, path string, run *v1beta1.Run, webserverURL string) string { // https://github.com/orgs/community/discussions/27190 characterLimit := 65000 @@ -160,19 +151,26 @@ func runOutputMsg(cluster, module, path string, run *v1beta1.Run) string { runOutput = run.InitOutput + "\n" + run.Output } + msgTml := runOutputMsgTml + if !run.PlanOnly { + msgTml = strings.Replace(msgTml, "Terraform Plan Output", "Terraform Apply Output", 1) + } + runes := []rune(runOutput) if len(runes) > characterLimit { - runOutput = "Plan output has reached the max character limit of " + fmt.Sprintf("%d", characterLimit) + " characters. " + + runOutput = "Plan output has reached the max character limit of " + fmt.Sprintf("%d", characterLimit) + " characters.\n" + "The output is truncated from the top.\n" + string(runes[(len(runes)-characterLimit):]) } - display := fmt.Sprintf(runOutputMsgTml, cluster, module, path, run.CommitHash, statusSymbol, run.Status, run.Summary, runOutput, path) + moduleURL := webserverURL + "/#" + module.Namespace + "_" + module.Name + + display := fmt.Sprintf(msgTml, module.Name, run.CommitHash, cluster, moduleURL, path, statusSymbol, run.Status, run.Summary, runOutput) meta := CommentMetadata{ Type: MsgTypeRunOutput, Cluster: cluster, - Module: module, + Module: module.String(), Path: path, CommitID: run.CommitHash, } diff --git a/prplanner/msg_test.go b/prplanner/msg_test.go index c62df27..06c992e 100644 --- a/prplanner/msg_test.go +++ b/prplanner/msg_test.go @@ -69,12 +69,12 @@ func Test_parsePlanReqMsg(t *testing.T) { }, { name: "do not trigger plan on our module request Acknowledged Msg", - args: args{commentBody: requestAcknowledgedMsg("default", "foo/one", "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"))}, + args: args{commentBody: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"), "link")}, wantModuleNameOrPath: "", }, { name: "do not trigger plan on our module run Output Msg", - args: args{commentBody: runOutputMsg("default", "foo/one", "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{commentBody: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "link")}, wantModuleNameOrPath: "", }, { @@ -106,7 +106,7 @@ func Test_parsePlanReqMsg(t *testing.T) { func Test_requestAcknowledgedMsg(t *testing.T) { type args struct { cluster string - module string + module types.NamespacedName path string commitID string reqAt *metav1.Time @@ -118,17 +118,11 @@ func Test_requestAcknowledgedMsg(t *testing.T) { }{ { "1", - args{cluster: "default", module: "foo/one", path: "path/to/module/one", commitID: "hash1", reqAt: mustParseMetaTime("2006-01-02T15:04:05+07:00")}, - "Received terraform plan request\n" + - "```\n" + - "Cluster: default\n" + - "Module: foo/one\n" + - "Path: path/to/module/one\n" + - "Commit ID: hash1\n" + - "Requested At: 2006-01-02T15:04:05+07:00\n" + - "```\n" + - "Do not edit this comment. This message will be updated once the plan run is completed.\n" + - "To manually trigger plan again please post `@terraform-applier plan path/to/module/one` as comment." + + args{cluster: "default", module: types.NamespacedName{Name: "one", Namespace: "foo"}, path: "path/to/module/one", commitID: "hash1", reqAt: mustParseMetaTime("2006-01-02T15:04:05+07:00")}, + "### Received terraform plan request for `one`\n" + + "🏷️ **Commit:** hash1 | 🕒 **Requested At:** 2006-01-02T15:04:05+07:00 | 🔗 [View in default dashboard](https://dashboard-url/#foo_one)\n\n" + + "*(Do not edit this comment. This message will be updated once the plan run is completed.)*\n" + + ">To manually trigger plan again please post `@terraform-applier plan path/to/module/one` as comment." + embedMetadata(CommentMetadata{ Type: MsgTypePlanRequest, Cluster: "default", @@ -141,7 +135,7 @@ func Test_requestAcknowledgedMsg(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := requestAcknowledgedMsg(tt.args.cluster, tt.args.module, tt.args.path, tt.args.commitID, tt.args.reqAt) + got := requestAcknowledgedMsg(tt.args.cluster, tt.args.module, tt.args.path, tt.args.commitID, tt.args.reqAt, "https://dashboard-url") if diff := cmp.Diff(tt.want, got); diff != "" { t.Errorf("requestAcknowledgedMsg() mismatch (-want +got):\n%s", diff) @@ -171,7 +165,7 @@ func Test_parseRequestAcknowledgedMsg(t *testing.T) { }, { name: "NamespacedName + Requested At", - args: args{commentBody: requestAcknowledgedMsg("default", "foo/one", "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"))}, + args: args{commentBody: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"), "link")}, wantModule: types.NamespacedName{Namespace: "foo", Name: "one"}, wantCluster: "default", wantPath: "path/to/module/one", @@ -180,7 +174,7 @@ func Test_parseRequestAcknowledgedMsg(t *testing.T) { }, { name: "cluster env with spec char", - args: args{commentBody: requestAcknowledgedMsg("clusterEnv-with_", "foo/one", "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"))}, + args: args{commentBody: requestAcknowledgedMsg("clusterEnv-with_", types.NamespacedName{Name: "one", Namespace: "foo"}, "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"), "link")}, wantModule: types.NamespacedName{Namespace: "foo", Name: "one"}, wantCluster: "clusterEnv-with_", wantPath: "path/to/module/one", @@ -189,7 +183,7 @@ func Test_parseRequestAcknowledgedMsg(t *testing.T) { }, { name: "NamespacedName + Requested At UTC", - args: args{commentBody: requestAcknowledgedMsg("default", "foo/one", "foo/one", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z"))}, + args: args{commentBody: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z"), "link")}, wantModule: types.NamespacedName{Namespace: "foo", Name: "one"}, wantCluster: "default", wantPath: "foo/one", @@ -198,7 +192,7 @@ func Test_parseRequestAcknowledgedMsg(t *testing.T) { }, { name: "Name + Requested At", - args: args{commentBody: requestAcknowledgedMsg("default", "one", "foo/one", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z"))}, + args: args{commentBody: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: ""}, "foo/one", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z"), "link")}, wantModule: types.NamespacedName{Name: "one"}, wantCluster: "default", wantPath: "foo/one", @@ -252,7 +246,7 @@ func Test_parseRequestAcknowledgedMsg(t *testing.T) { func Test_runOutputMsg(t *testing.T) { type args struct { cluster string - module string + module types.NamespacedName path string run *v1beta1.Run } @@ -263,21 +257,16 @@ func Test_runOutputMsg(t *testing.T) { }{ { "1", - args{cluster: "default", module: "baz/one", path: "path/baz/one", run: &v1beta1.Run{Status: v1beta1.StatusOk, CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "Terraform apply output...."}}, - "Terraform run output for\n" + - "```\n" + - "Cluster: default\n" + - "Module: baz/one\n" + - "Path: path/baz/one\n" + - "Commit ID: hash2\n" + - "```\n" + + args{cluster: "default", module: types.NamespacedName{Name: "one", Namespace: "baz"}, path: "path/baz/one", run: &v1beta1.Run{Status: v1beta1.StatusOk, PlanOnly: true, CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "Terraform apply output...."}}, + "### Terraform Plan Output for `one`\n" + + "🏷️ **Commit:** hash2 | 🔗 [View in default dashboard](https://dashboard-url/#baz_one)\n\n" + + "> To manually trigger plan again please post `@terraform-applier plan path/baz/one` as comment.\n" + "
✅ Run Status: Ok, Run Summary: Plan: x to add, x to change, x to destroy.\n\n" + "```" + "terraform\n" + "Terraform apply output....\n" + "```\n" + "
\n" + - "\n> To manually trigger plan again please post `@terraform-applier plan path/baz/one` as comment." + embedMetadata(CommentMetadata{ Type: MsgTypeRunOutput, Cluster: "default", @@ -288,21 +277,16 @@ func Test_runOutputMsg(t *testing.T) { }, { "2", - args{cluster: "default", module: "baz/one", path: "path/baz/one", run: &v1beta1.Run{Status: v1beta1.StatusErrored, CommitHash: "hash2", Summary: "unable to plan module", InitOutput: "Some Init Output...", Output: "Some TF Output ....."}}, - "Terraform run output for\n" + - "```\n" + - "Cluster: default\n" + - "Module: baz/one\n" + - "Path: path/baz/one\n" + - "Commit ID: hash2\n" + - "```\n" + + args{cluster: "default", module: types.NamespacedName{Name: "one", Namespace: "baz"}, path: "path/baz/one", run: &v1beta1.Run{Status: v1beta1.StatusErrored, PlanOnly: true, CommitHash: "hash2", Summary: "unable to plan module", InitOutput: "Some Init Output...", Output: "Some TF Output ....."}}, + "### Terraform Plan Output for `one`\n" + + "🏷️ **Commit:** hash2 | 🔗 [View in default dashboard](https://dashboard-url/#baz_one)\n\n" + + "> To manually trigger plan again please post `@terraform-applier plan path/baz/one` as comment.\n" + "
⛔ Run Status: Errored, Run Summary: unable to plan module\n\n" + "```" + "terraform\n" + "Some Init Output...\nSome TF Output .....\n" + "```\n" + "
\n" + - "\n> To manually trigger plan again please post `@terraform-applier plan path/baz/one` as comment." + embedMetadata(CommentMetadata{ Type: MsgTypeRunOutput, Cluster: "default", @@ -312,21 +296,16 @@ func Test_runOutputMsg(t *testing.T) { }), }, { "3", - args{cluster: "default", module: "baz/one", path: "path/baz/one", run: &v1beta1.Run{Status: v1beta1.StatusOk, DiffDetected: true, CommitHash: "hash2", Summary: "Applied: x to add, x to change, x to destroy.", Output: "Terraform apply output...."}}, - "Terraform run output for\n" + - "```\n" + - "Cluster: default\n" + - "Module: baz/one\n" + - "Path: path/baz/one\n" + - "Commit ID: hash2\n" + - "```\n" + + args{cluster: "default", module: types.NamespacedName{Name: "one", Namespace: "baz"}, path: "path/baz/one", run: &v1beta1.Run{Status: v1beta1.StatusOk, PlanOnly: false, DiffDetected: true, CommitHash: "hash2", Summary: "Applied: x to add, x to change, x to destroy.", Output: "Terraform apply output...."}}, + "### Terraform Apply Output for `one`\n" + + "🏷️ **Commit:** hash2 | 🔗 [View in default dashboard](https://dashboard-url/#baz_one)\n\n" + + "> To manually trigger plan again please post `@terraform-applier plan path/baz/one` as comment.\n" + "
✅ Run Status: Ok, Run Summary: Applied: x to add, x to change, x to destroy.\n\n" + "```" + "terraform\n" + "Terraform apply output....\n" + "```\n" + "
\n" + - "\n> To manually trigger plan again please post `@terraform-applier plan path/baz/one` as comment." + embedMetadata(CommentMetadata{ Type: MsgTypeRunOutput, Cluster: "default", @@ -338,7 +317,7 @@ func Test_runOutputMsg(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := runOutputMsg(tt.args.cluster, tt.args.module, tt.args.path, tt.args.run) + got := runOutputMsg(tt.args.cluster, tt.args.module, tt.args.path, tt.args.run, "https://dashboard-url") if diff := cmp.Diff(tt.want, got); diff != "" { t.Errorf("runOutputMsg() mismatch (-want +got):\n%s", diff) @@ -361,7 +340,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }{ { name: "NamespaceName + Commit ID", - args: args{comment: runOutputMsg("default", "baz/one", "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{comment: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "baz"}, "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "dashboard-url")}, wantModule: types.NamespacedName{Namespace: "baz", Name: "one"}, wantCluster: "default", wantPath: "foo/one", @@ -369,7 +348,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }, { name: "cluster env with spec char", - args: args{comment: runOutputMsg("default_-", "baz/one", "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{comment: runOutputMsg("default_-", types.NamespacedName{Name: "one", Namespace: "baz"}, "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "dashboard-url")}, wantModule: types.NamespacedName{Namespace: "baz", Name: "one"}, wantCluster: "default_-", wantPath: "foo/one", @@ -377,7 +356,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }, { name: "Module Name only", - args: args{comment: runOutputMsg("default", "one", "foo/one", &v1beta1.Run{CommitHash: "", Summary: "Plan: x to add..."})}, + args: args{comment: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: ""}, "foo/one", &v1beta1.Run{CommitHash: "", Summary: "Plan: x to add..."}, "dashboard-url")}, wantModule: types.NamespacedName{Name: "one"}, wantCluster: "default", wantPath: "foo/one", @@ -385,7 +364,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }, { name: "Module Name + Commit ID", - args: args{comment: runOutputMsg("default", "one", "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{comment: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: ""}, "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "dashboard-url")}, wantModule: types.NamespacedName{Name: "one"}, wantCluster: "default", wantPath: "foo/one", @@ -393,7 +372,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }, { name: "Path cluster only", - args: args{comment: runOutputMsg("default", "baz/one", "foo/", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{comment: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "baz"}, "foo/", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "dashboard-url")}, wantModule: types.NamespacedName{Namespace: "baz", Name: "one"}, wantCluster: "default", wantPath: "foo/", @@ -401,7 +380,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }, { name: "Path Module Name only", - args: args{comment: runOutputMsg("default", "baz/one", "/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{comment: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "baz"}, "/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "dashboard-url")}, wantModule: types.NamespacedName{Namespace: "baz", Name: "one"}, wantCluster: "default", wantPath: "/one", @@ -409,7 +388,7 @@ func Test_parseRunOutputMsg(t *testing.T) { }, { name: "Path one word only", - args: args{comment: runOutputMsg("default", "baz/one", "one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, + args: args{comment: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "baz"}, "one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "dashboard-url")}, wantModule: types.NamespacedName{Namespace: "baz", Name: "one"}, wantCluster: "default", wantPath: "one", @@ -541,8 +520,8 @@ func Test_IsSelfComment(t *testing.T) { {"empty", args{""}, false}, // Updated to simulate comments WITH metadata {"autoPlanDisabledTml", args{autoPlanDisabledTml + embedMetadata(CommentMetadata{Type: MsgTypeAutoPlanDisabled})}, true}, - {"requestAcknowledgedMsg", args{requestAcknowledgedMsg("default", "foo/one", "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"))}, true}, - {"runOutputMsg", args{runOutputMsg("default", "one", "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."})}, true}, + {"requestAcknowledgedMsg", args{requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "path/to/module/one", "hash1", mustParseMetaTime("2006-01-02T15:04:05+07:00"), "link")}, true}, + {"runOutputMsg", args{runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "baz"}, "foo/one", &v1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "link")}, true}, {"other", args{"other"}, false}, } for _, tt := range tests { diff --git a/prplanner/outputs.go b/prplanner/outputs.go index be02558..d41d61f 100644 --- a/prplanner/outputs.go +++ b/prplanner/outputs.go @@ -35,7 +35,7 @@ func (p *Planner) uploadRequestOutput(ctx context.Context, pr *pr) { } payload := prComment{ - Body: runOutputMsg(p.ClusterEnvName, moduleNamespacedName.String(), path, run), + Body: runOutputMsg(p.ClusterEnvName, moduleNamespacedName, path, run, p.WebserverURL), } _, err = p.github.postComment(pr.BaseRepository.Owner.Login, pr.BaseRepository.Name, comment.DatabaseID, pr.Number, payload) @@ -104,7 +104,7 @@ func (p *Planner) processRedisKeySetMsg(ctx context.Context, ch <-chan *redis.Me } comment := prComment{ - Body: runOutputMsg(p.ClusterEnvName, run.Module.String(), module.Spec.Path, run), + Body: runOutputMsg(p.ClusterEnvName, run.Module, module.Spec.Path, run, p.WebserverURL), } repo, err := giturl.Parse(module.Spec.RepoURL) diff --git a/prplanner/planner.go b/prplanner/planner.go index 91dda0e..b263f31 100644 --- a/prplanner/planner.go +++ b/prplanner/planner.go @@ -30,6 +30,7 @@ type Planner struct { github GithubInterface Interval time.Duration Log *slog.Logger + WebserverURL string } func (p *Planner) Init(ctx context.Context, ghApp sysutil.CredsProvider, ch <-chan *redis.Message) error { diff --git a/prplanner/requests.go b/prplanner/requests.go index bde182b..0af07c8 100644 --- a/prplanner/requests.go +++ b/prplanner/requests.go @@ -176,7 +176,7 @@ func (p *Planner) addNewRequest(module *tfaplv1beta1.Module, pr *pr, commitID st req := module.NewRunRequest(tfaplv1beta1.PRPlan, "") commentBody := prComment{ - Body: requestAcknowledgedMsg(p.ClusterEnvName, module.NamespacedName().String(), module.Spec.Path, commitID, req.RequestedAt), + Body: requestAcknowledgedMsg(p.ClusterEnvName, module.NamespacedName(), module.Spec.Path, commitID, req.RequestedAt, p.WebserverURL), } commentID, err := p.github.postComment(pr.BaseRepository.Owner.Login, pr.BaseRepository.Name, 0, pr.Number, commentBody) diff --git a/prplanner/requests_test.go b/prplanner/requests_test.go index c89a12a..173c40c 100644 --- a/prplanner/requests_test.go +++ b/prplanner/requests_test.go @@ -189,7 +189,7 @@ func TestCheckPRCommits(t *testing.T) { planner.RedisClient = testRedis p := generateMockPR(123, "ref1", - []string{"random comment", runOutputMsg("default", "foo/two", "foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}), "random comment"}, + []string{"random comment", runOutputMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}, "link"), "random comment"}, ) commitsInfo := []repository.CommitInfo{ @@ -225,7 +225,7 @@ func TestCheckPRCommits(t *testing.T) { planner.RedisClient = testRedis p := generateMockPR(123, "ref1", - []string{"random comment", runOutputMsg("default", "foo/two", "foo/two", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}), "random comment"}, + []string{"random comment", runOutputMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "foo/two", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}, "link"), "random comment"}, ) commitsInfo := []repository.CommitInfo{ {Hash: "hash3", ChangedFiles: []string{"foo/two", "foo/three"}}, @@ -261,7 +261,7 @@ func TestCheckPRCommits(t *testing.T) { planner.RedisClient = testRedis p := generateMockPR(123, "ref1", - []string{"random comment", runOutputMsg("diff-cluster", "foo/two", "foo/two", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}), "random comment"}, + []string{"random comment", runOutputMsg("diff-cluster", types.NamespacedName{Name: "two", Namespace: "foo"}, "foo/two", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}, "link"), "random comment"}, ) commitsInfo := []repository.CommitInfo{ {Hash: "hash3", ChangedFiles: []string{"foo/two", "foo/three"}}, @@ -327,7 +327,7 @@ func TestCheckPRCommits(t *testing.T) { planner.RedisClient = testRedis p := generateMockPR(123, "ref1", - []string{"random comment", requestAcknowledgedMsg("default", "foo/two", "foo/two", "hash3", &metav1.Time{Time: time.Now()}), "random comment"}, + []string{"random comment", requestAcknowledgedMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "foo/two", "hash3", &metav1.Time{Time: time.Now()}, "link"), "random comment"}, ) commitsInfo := []repository.CommitInfo{ {Hash: "hash3", ChangedFiles: []string{"foo/two", "foo/three"}}, @@ -363,7 +363,7 @@ func TestCheckPRCommits(t *testing.T) { planner.RedisClient = testRedis p := generateMockPR(123, "ref1", - []string{"random comment", requestAcknowledgedMsg("diff-cluster", "foo/two", "foo/two", "hash3", &metav1.Time{Time: time.Now()}), "random comment"}, + []string{"random comment", requestAcknowledgedMsg("diff-cluster", types.NamespacedName{Name: "two", Namespace: "foo"}, "foo/two", "hash3", &metav1.Time{Time: time.Now()}, "link"), "random comment"}, ) commitsInfo := []repository.CommitInfo{ {Hash: "hash3", ChangedFiles: []string{"foo/two", "foo/three"}}, @@ -429,7 +429,7 @@ func TestCheckPRCommits(t *testing.T) { planner.RedisClient = testRedis p := generateMockPR(123, "ref1", - []string{"random comment", runOutputMsg("default", "foo/two", "foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}), "random comment"}, + []string{"random comment", runOutputMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "some output"}, "link"), "random comment"}, ) commitsInfo := []repository.CommitInfo{ {Hash: "hash3", ChangedFiles: []string{"foo/two", "foo/three"}}, @@ -577,8 +577,8 @@ func Test_checkPRCommentsForPlanRequests(t *testing.T) { pr := generateMockPR(123, "ref1", []string{ "@terraform-applier plan two", - requestAcknowledgedMsg("default", "foo/two", "path/foo/two", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z")), - requestAcknowledgedMsg("default", "foo/three", "path/foo/three", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z")), + requestAcknowledgedMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "path/foo/two", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z"), "link"), + requestAcknowledgedMsg("default", types.NamespacedName{Name: "three", Namespace: "foo"}, "path/foo/three", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z"), "link"), }, ) @@ -600,8 +600,8 @@ func Test_checkPRCommentsForPlanRequests(t *testing.T) { pr := generateMockPR(123, "ref1", []string{ "@terraform-applier plan path/foo/two", - requestAcknowledgedMsg("default", "foo/two", "path/foo/two", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z")), - requestAcknowledgedMsg("default", "foo/three", "path/foo/three", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z")), + requestAcknowledgedMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "path/foo/two", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z"), "link"), + requestAcknowledgedMsg("default", types.NamespacedName{Name: "three", Namespace: "foo"}, "path/foo/three", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z"), "link"), }, ) @@ -619,8 +619,8 @@ func Test_checkPRCommentsForPlanRequests(t *testing.T) { pr := generateMockPR(123, "ref1", []string{ "@terraform-applier plan two", - runOutputMsg("default", "foo/two", "path/foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}), - runOutputMsg("default", "foo/three", "path/foo/three", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}), + runOutputMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "path/foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}, "link"), + runOutputMsg("default", types.NamespacedName{Name: "three", Namespace: "foo"}, "path/foo/three", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}, "link"), }, ) @@ -638,8 +638,8 @@ func Test_checkPRCommentsForPlanRequests(t *testing.T) { pr := generateMockPR(123, "ref1", []string{ "@terraform-applier plan path/foo/two", - runOutputMsg("default", "foo/two", "path/foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}), - runOutputMsg("default", "foo/three", "path/foo/three", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}), + runOutputMsg("default", types.NamespacedName{Name: "two", Namespace: "foo"}, "path/foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}, "link"), + runOutputMsg("default", types.NamespacedName{Name: "three", Namespace: "foo"}, "path/foo/three", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}, "link"), }, ) @@ -789,8 +789,8 @@ func Test_checkPRCommentsForPlanRequests(t *testing.T) { pr := generateMockPR(123, "ref1", []string{ "@terraform-applier plan two", - requestAcknowledgedMsg("diff-cluster", "foo/two", "path/foo/two", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z")), - requestAcknowledgedMsg("default", "foo/three", "path/foo/three", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z")), + requestAcknowledgedMsg("diff-cluster", types.NamespacedName{Name: "two", Namespace: "foo"}, "path/foo/two", "hash2", mustParseMetaTime("2023-04-02T15:04:05Z"), "link"), + requestAcknowledgedMsg("default", types.NamespacedName{Name: "three", Namespace: "foo"}, "path/foo/three", "hash3", mustParseMetaTime("2023-04-02T15:04:05Z"), "link"), }, ) @@ -841,8 +841,8 @@ func Test_checkPRCommentsForPlanRequests(t *testing.T) { pr := generateMockPR(123, "ref1", []string{ "@terraform-applier plan two", - runOutputMsg("diff-cluster", "foo/two", "path/foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}), - runOutputMsg("default", "foo/three", "path/foo/three", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}), + runOutputMsg("diff-cluster", types.NamespacedName{Name: "two", Namespace: "foo"}, "path/foo/two", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}, "link"), + runOutputMsg("default", types.NamespacedName{Name: "three", Namespace: "foo"}, "path/foo/three", &tfaplv1beta1.Run{CommitHash: "hash3", Summary: "Plan: x to add, x to change, x to destroy.", Output: "tf plan output"}, "link"), }, ) @@ -954,7 +954,7 @@ func Test_isPlanOutputPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: runOutputMsg("default", "foo/one", "foo/one", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}), + Body: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "link"), }, }}}, cluster: "default", @@ -972,7 +972,7 @@ func Test_isPlanOutputPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: runOutputMsg("diff-cluster", "foo/one", "foo/one", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}), + Body: runOutputMsg("diff-cluster", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "link"), }, }}}, cluster: "default", @@ -990,7 +990,7 @@ func Test_isPlanOutputPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: runOutputMsg("default", "one", "foo/one", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}), + Body: runOutputMsg("default", types.NamespacedName{Name: "one", Namespace: ""}, "foo/one", &tfaplv1beta1.Run{CommitHash: "hash2", Summary: "Plan: x to add, x to change, x to destroy."}, "link"), }, }}}, cluster: "default", @@ -1116,7 +1116,7 @@ func Test_isPlanRequestAckPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: requestAcknowledgedMsg("default", "foo/one", "foo/one", "hash2", &metav1.Time{Time: time.Now()}), + Body: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", "hash2", &metav1.Time{Time: time.Now()}, "link"), }, }}}, cluster: "default", @@ -1133,7 +1133,7 @@ func Test_isPlanRequestAckPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: requestAcknowledgedMsg("diff-cluster", "foo/one", "foo/one", "hash2", &metav1.Time{Time: time.Now()}), + Body: requestAcknowledgedMsg("diff-cluster", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", "hash2", &metav1.Time{Time: time.Now()}, "link"), }, }}}, cluster: "default", @@ -1150,7 +1150,7 @@ func Test_isPlanRequestAckPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: requestAcknowledgedMsg("default", "foo/one", "foo/one", "hash2", &metav1.Time{Time: time.Now().Add(-30 * time.Minute)}), + Body: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", "hash2", &metav1.Time{Time: time.Now().Add(-30 * time.Minute)}, "link"), }, }}}, cluster: "default", @@ -1167,7 +1167,7 @@ func Test_isPlanRequestAckPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: requestAcknowledgedMsg("default", "foo/one", "foo/one", "hash2", &metav1.Time{Time: time.Now().Add(5 * time.Minute)}), + Body: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", "hash2", &metav1.Time{Time: time.Now().Add(5 * time.Minute)}, "link"), }, }}}, cluster: "default", @@ -1184,7 +1184,7 @@ func Test_isPlanRequestAckPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: requestAcknowledgedMsg("default", "foo/one", "foo/one", "hash2", &metav1.Time{Time: time.Now()}), + Body: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/one", "hash2", &metav1.Time{Time: time.Now()}, "link"), }, }}}, cluster: "default", @@ -1201,7 +1201,7 @@ func Test_isPlanRequestAckPostedForCommit(t *testing.T) { }{Nodes: []prComment{ { DatabaseID: 01234567, - Body: requestAcknowledgedMsg("default", "foo/two", "foo/two", "hash3", &metav1.Time{Time: time.Now()}), + Body: requestAcknowledgedMsg("default", types.NamespacedName{Name: "one", Namespace: "foo"}, "foo/two", "hash3", &metav1.Time{Time: time.Now()}, "link"), }, }}}, cluster: "default", diff --git a/prplanner/webhook.go b/prplanner/webhook.go index a4cd9a6..9072ae7 100644 --- a/prplanner/webhook.go +++ b/prplanner/webhook.go @@ -12,17 +12,17 @@ func (p *Planner) ProcessPRWebHookEvent(event GitHubWebhook, prNumber int) { pr, err := p.github.PR(ctx, event.Repository.Owner.Login, event.Repository.Name, prNumber) if err != nil { - p.Log.Error("unable to get PR info", "pr", prNumber, "err", err) + p.Log.Error("unable to get PR info", "repo", event.Repository.Name, "pr", prNumber, "err", err) return } kubeModuleList := &tfaplv1beta1.ModuleList{} if err := p.ClusterClt.List(ctx, kubeModuleList); err != nil { - p.Log.Error("error retrieving list of modules", "pr", prNumber, "error", err) + p.Log.Error("error retrieving list of modules", "repo", event.Repository.Name, "pr", prNumber, "error", err) return } - p.Log.Debug("processing PR event", "pr", prNumber) + p.Log.Debug("processing PR event", "repo", event.Repository.Name, "pr", prNumber) p.processPullRequest(ctx, pr, kubeModuleList) }