From f322e0ab7d4907a11ccff26341f40ce89f814fc4 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 16 Nov 2023 10:55:57 +0100 Subject: [PATCH 1/5] Implement initial template with example data from the design Rendering this results in the equivalent output of the design. --- cmd/comment.md | 54 ++++++++++++++++++ cmd/getchange.go | 141 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 166 insertions(+), 29 deletions(-) create mode 100644 cmd/comment.md diff --git a/cmd/comment.md b/cmd/comment.md new file mode 100644 index 00000000..d3e4e1f3 --- /dev/null +++ b/cmd/comment.md @@ -0,0 +1,54 @@ +# mapped Expected Changes + +{{range .ExpectedChanges }} +
+{{ .StatusAlt }} {{ .Type }} › {{ .Title }} + +```diff +{{ .Diff }} +``` +
+{{else}} +No expected changes found. +{{end}} + + +## unmapped Unmapped Changes + +> [!NOTE] +> These changes couldn't be mapped to a real cloud resource and therefore won't be included in the blast radius calculation. + + +{{range .UnmappedChanges }} +
+{{ .StatusAlt }} {{ .Type }} › {{ .Title }} + +```diff +{{ .Diff }} +``` +
+{{else}} +No expected changes found. +{{end}} + + + +# Blast Radius + +| mapped Items | edge Edges | +|---|---| +| 75 | 97 + +[Open in Overmind]({{ .ChangeUrl }}) + + + +{{if .Risks }} +# warning Risks + +{{range .Risks }} +## {{ .SeverityAlt }} Impact on Target Groups [High] + +The various target groups including \"944651592624.eu-west-2.elbv2-target-group.k8s-default-nats-4650f3a363\", \"944651592624.eu-west-2.elbv2-target-group.k8s-default-smartloo-fd2416d9f8\", etc., that work alongside the load balancer for traffic routing may be indirectly affected if the security group change causes networking issues. This is especially important if these target groups rely on different ports other than 8080 for health checks or for directing incoming requests to backend services. +{{end}} +{{end}} diff --git a/cmd/getchange.go b/cmd/getchange.go index 7a693dc1..0688b1bf 100644 --- a/cmd/getchange.go +++ b/cmd/getchange.go @@ -2,11 +2,13 @@ package cmd import ( "context" + _ "embed" "encoding/json" "fmt" "os" "os/signal" "syscall" + "text/template" "time" "connectrpc.com/connect" @@ -20,6 +22,9 @@ import ( "go.opentelemetry.io/otel/trace" ) +//go:embed comment.md +var commentTemplate string + // getChangeCmd represents the get-change command var getChangeCmd = &cobra.Command{ Use: "get-change {--uuid ID | --change https://app.overmind.tech/changes/c772d072-6b0b-4763-b7c5-ff5069beed4c}", @@ -87,7 +92,7 @@ func GetChange(ctx context.Context, ready chan bool) int { lf["uuid"] = changeUuid.String() client := AuthenticatedChangesClient(ctx) - response, err := client.GetChange(ctx, &connect.Request[sdp.GetChangeRequest]{ + changeRes, err := client.GetChange(ctx, &connect.Request[sdp.GetChangeRequest]{ Msg: &sdp.GetChangeRequest{ UUID: changeUuid[:], }, @@ -99,44 +104,122 @@ func GetChange(ctx context.Context, ready chan bool) int { return 1 } log.WithContext(ctx).WithFields(log.Fields{ - "change-uuid": uuid.UUID(response.Msg.Change.Metadata.UUID), - "change-created": response.Msg.Change.Metadata.CreatedAt.AsTime(), - "change-status": response.Msg.Change.Metadata.Status.String(), - "change-name": response.Msg.Change.Properties.Title, - "change-description": response.Msg.Change.Properties.Description, + "change-uuid": uuid.UUID(changeRes.Msg.Change.Metadata.UUID), + "change-created": changeRes.Msg.Change.Metadata.CreatedAt.AsTime(), + "change-status": changeRes.Msg.Change.Metadata.Status.String(), + "change-name": changeRes.Msg.Change.Properties.Title, + "change-description": changeRes.Msg.Change.Properties.Description, }).Info("found change") + // diffRes, err := client.GetDiff(ctx, &connect.Request[sdp.GetDiffRequest]{ + // Msg: &sdp.GetDiffRequest{ + // ChangeUUID: changeUuid[:], + // }, + // }) + // if err != nil { + // log.WithContext(ctx).WithError(err).WithFields(log.Fields{ + // "change-url": viper.GetString("change-url"), + // }).Error("failed to get change diff") + // return 1 + // } + // log.WithContext(ctx).WithFields(log.Fields{ + // "change-uuid": uuid.UUID(changeRes.Msg.Change.Metadata.UUID), + // }).Info("loaded change diff") + switch viper.GetString("format") { case "json": - b, err := json.MarshalIndent(response.Msg.Change.ToMap(), "", " ") + b, err := json.MarshalIndent(changeRes.Msg.Change.ToMap(), "", " ") if err != nil { - log.Errorf("Error rendering change: %v", err) + log.WithContext(ctx).WithField("input", fmt.Sprintf("%#v", changeRes.Msg.Change.ToMap())).WithError(err).Error("Error rendering change") return 1 } fmt.Println(string(b)) case "markdown": - changeUrl := fmt.Sprintf("%v/changes/%v", viper.GetString("frontend"), changeUuid.String()) - if response.Msg.Change.Metadata.NumAffectedApps != 0 || response.Msg.Change.Metadata.NumAffectedItems != 0 { - // we have affected stuff - fmt.Printf(`## Blast Radius   ·   [View in Overmind](%v) chain link icon - -> **Warning** -> Overmind identified potentially affected apps and items as a result of this pull request. - -
- -| icon for blast radius items Affected items | -| -------------- | -| [%v items](%v) | -`, changeUrl, response.Msg.Change.Metadata.NumAffectedItems, changeUrl) - } else { - fmt.Printf(`## Blast Radius   ·   [View in Overmind](%v) chain link icon - -> **✅ Checks complete** -> Overmind didn't identify any potentially affected apps and items as a result of this pull request. - -`, changeUrl) + type TemplateItem struct { + StatusAlt string + StatusIcon string + Type string + Title string + Diff string + } + type TemplateRisk struct { + SeverityAlt string + SeverityIcon string + SeverityText string + Title string + Description string + } + type TemplateData struct { + ChangeUrl string + ExpectedChanges []TemplateItem + UnmappedChanges []TemplateItem + BlastItems int + BlastEdges int + Risks []TemplateRisk + } + data := TemplateData{ + ChangeUrl: fmt.Sprintf("%v/changes/%v", viper.GetString("frontend"), changeUuid.String()), + ExpectedChanges: []TemplateItem{ + { + StatusAlt: "updated", + StatusIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/db3e59a9-a560-4ea9-b38b-854d88ab2cd6", + Type: "Deployment", + Title: "api-server", + Diff: " Once again a diff here", + }, + }, + UnmappedChanges: []TemplateItem{ + { + StatusAlt: "created", + StatusIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/2fc6cb63-9ee1-4e15-91ea-b234a92edddb", + Type: "auth0_action", + Title: "add_to_crm", + Diff: " This should be diff with everything", + }, { + StatusAlt: "updated", + StatusIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/db3e59a9-a560-4ea9-b38b-854d88ab2cd6", + Type: "auth0_action", + Title: "create_account", + Diff: ` code: | + const { createPromiseClient } = require( "@connectrpc/connect") + const { createConnectTransport } = require( "@connectrpc/connect-node") +- const { Auth0Support,Auth0CreateUserRequest } = require('@overmindtech/sdp-js') ++ const { Auth0Support} = require('@overmindtech/sdp-js') + const ClientOAuth2 = require('client-oauth2') + const transport = createConnectTransport({ + --- + api.accessToken.setCustomClaim('https://api.overmind.tech/account-name', event.user.app_metadata.account_name) + // wake up all sources +- const res = await client.keepaliveSources( ++ await client.keepaliveSources( + { + account: event.user.app_metadata.account_name, + }, +`, + }, + }, + BlastItems: 75, + BlastEdges: 97, + Risks: []TemplateRisk{ + { + SeverityAlt: "high", + SeverityIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/76a34fd0-7699-4636-9a4c-3cdabdf7783e", + SeverityText: "high", + Title: "Impact on Target Groups", + Description: `The various target groups including \"944651592624.eu-west-2.elbv2-target-group.k8s-default-nats-4650f3a363\", \"944651592624.eu-west-2.elbv2-target-group.k8s-default-smartloo-fd2416d9f8\", etc., that work alongside the load balancer for traffic routing may be indirectly affected if the security group change causes networking issues. This is especially important if these target groups rely on different ports other than 8080 for health checks or for directing incoming requests to backend services.`, + }, + }, + } + tmpl, err := template.New("comment").Parse(commentTemplate) + if err != nil { + log.WithContext(ctx).WithError(err).Error("error parsing comment template") + return 1 + } + err = tmpl.Execute(os.Stdout, data) + if err != nil { + log.WithContext(ctx).WithField("input", fmt.Sprintf("%#v", data)).WithError(err).Error("error rendering comment") + return 1 } } From ac4feb1b9dd73b5c42c5a515d12517b551d2886b Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 16 Nov 2023 11:16:39 +0100 Subject: [PATCH 2/5] Add icons --- assets/change.png | Bin 0 -> 1234 bytes assets/changed.png | Bin 0 -> 498 bytes assets/created.png | Bin 0 -> 488 bytes assets/deleted.png | Bin 0 -> 384 bytes assets/edge.png | Bin 0 -> 560 bytes assets/high.png | Bin 0 -> 935 bytes assets/item.png | Bin 0 -> 502 bytes assets/low.png | Bin 0 -> 619 bytes assets/medium.png | Bin 0 -> 535 bytes assets/replaced.png | Bin 0 -> 627 bytes assets/risks.png | Bin 0 -> 885 bytes 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/change.png create mode 100644 assets/changed.png create mode 100644 assets/created.png create mode 100644 assets/deleted.png create mode 100644 assets/edge.png create mode 100644 assets/high.png create mode 100644 assets/item.png create mode 100644 assets/low.png create mode 100644 assets/medium.png create mode 100644 assets/replaced.png create mode 100644 assets/risks.png diff --git a/assets/change.png b/assets/change.png new file mode 100644 index 0000000000000000000000000000000000000000..670f275c5ded6246f0862562fce1a5a83a9ba5dc GIT binary patch literal 1234 zcmV;@1TFiCP)Tgg5PGF2s-0#<5(VruMpe4er%2wu zen{8=?nbBo!!WK>tbiGkAH!i0YjGls0=#W=txuu&AuS5~rmTMI^(szOqcV;9bgj2w z_T&Xt`C2zkjYa`%+SXxCz`kY6)TUxaRbhT$nHtOj5FD5v7`d1Q0L7ZG2L+;$i%|d} zwP8*m-r3Y<6wrOMGSEQ#Fmup;TxgN#iMKZ|dPukhGXU>`qweu?Bd(8v1jqw8>YTxL zqWvWD0;2%&#N+?n{z|K)RRxd+Fl}%|N=kG1u-r`5-PEvC|1gRQrnXx=a@{6H3Tf8cr z?449{`5mKx?fUx`lYc#a8Slw9FKf@#Uj+U43@oi&OKDg_Kr7fzK(lXR>Zvju70qSCklgzJZ@@7{ohHQR1NBiAkVER|e89_PB{_fg zv^3bu_~Ir{(A7t`1`1b+pvFYr9rjL(VRedx*z;N(q#qPdkhsO4KlD;5m=EV}e+8k|p&Xm1!VBj$DjA-m^e)xx% zd7#Sb_wa%BidpD3L8;Xo<}(%f;I=_jjl<*0k*tIwTvb}F$)x(vF$uWf!;3XYFrgym zX2Gp07o-vKMx^Zt6t6Y|`ZY_GE;@ipO(5~QIJLzq^_^C<;faZ;8axDfzkf7}hSNsBF+uYFm}pER zoSrm!f1DYU4yOa&Jxn4Od4FueOEZSkrcXrPWPm=8Ads89AhE2{=~ssGf+Wl1#rH9v zpm-A2@82s%UXUn2kR_bf;6{GU;T8J%&J9jVijo&BWa;deJO;7hw2M~MSXm*Gnh&{W wJZ*!lY9RL6T07*qoM6N<$f}!3<{r~^~ literal 0 HcmV?d00001 diff --git a/assets/changed.png b/assets/changed.png new file mode 100644 index 0000000000000000000000000000000000000000..3fa9725bcb4d06ceb8bc4239c645bb79f575daa3 GIT binary patch literal 498 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 LNkvXXu0mjfUMZJ2 literal 0 HcmV?d00001 From e7ac8c283db60db4dc73b1ce352b06b1d0ed76c5 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 16 Nov 2023 12:09:43 +0100 Subject: [PATCH 3/5] Use actual items and calculate attribute diffs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example:
updated Deployment › api-server ```diff --- current +++ planned @@ -46,7 +46,6 @@ value: TRYMJyCxFCWU4FycHj1oztPyGyvtiv9f value_from: [] - name: API_KEY_CLIENT_SECRET - value: REDACTED value_from: [] - name: AUTH0_AUDIENCE value: https://api.overmind.tech ``` --- cmd/getchange.go | 134 ++++++++++++++++++++++++++++++----------------- go.mod | 3 +- go.sum | 2 + 3 files changed, 89 insertions(+), 50 deletions(-) diff --git a/cmd/getchange.go b/cmd/getchange.go index 0688b1bf..ef1a7982 100644 --- a/cmd/getchange.go +++ b/cmd/getchange.go @@ -13,6 +13,9 @@ import ( "connectrpc.com/connect" "github.com/google/uuid" + "github.com/hexops/gotextdiff" + "github.com/hexops/gotextdiff/myers" + diffspan "github.com/hexops/gotextdiff/span" "github.com/overmindtech/ovm-cli/tracing" "github.com/overmindtech/sdp-go" log "github.com/sirupsen/logrus" @@ -20,6 +23,7 @@ import ( "github.com/spf13/viper" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "gopkg.in/yaml.v3" ) //go:embed comment.md @@ -158,59 +162,91 @@ func GetChange(ctx context.Context, ready chan bool) int { BlastEdges int Risks []TemplateRisk } - data := TemplateData{ - ChangeUrl: fmt.Sprintf("%v/changes/%v", viper.GetString("frontend"), changeUuid.String()), - ExpectedChanges: []TemplateItem{ - { - StatusAlt: "updated", - StatusIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/db3e59a9-a560-4ea9-b38b-854d88ab2cd6", - Type: "Deployment", - Title: "api-server", - Diff: " Once again a diff here", - }, + status := map[sdp.ItemDiffStatus]TemplateItem{ + sdp.ItemDiffStatus_ITEM_DIFF_STATUS_UNSPECIFIED: { + StatusAlt: "unspecified", + StatusIcon: "", + }, + sdp.ItemDiffStatus_ITEM_DIFF_STATUS_UNCHANGED: { + StatusAlt: "unchanged", + StatusIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/item.png", + }, + sdp.ItemDiffStatus_ITEM_DIFF_STATUS_CREATED: { + StatusAlt: "created", + StatusIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/created.png", + }, + sdp.ItemDiffStatus_ITEM_DIFF_STATUS_UPDATED: { + StatusAlt: "updated", + StatusIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/changed.png", }, - UnmappedChanges: []TemplateItem{ - { - StatusAlt: "created", - StatusIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/2fc6cb63-9ee1-4e15-91ea-b234a92edddb", - Type: "auth0_action", - Title: "add_to_crm", - Diff: " This should be diff with everything", - }, { - StatusAlt: "updated", - StatusIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/db3e59a9-a560-4ea9-b38b-854d88ab2cd6", - Type: "auth0_action", - Title: "create_account", - Diff: ` code: | - const { createPromiseClient } = require( "@connectrpc/connect") - const { createConnectTransport } = require( "@connectrpc/connect-node") -- const { Auth0Support,Auth0CreateUserRequest } = require('@overmindtech/sdp-js') -+ const { Auth0Support} = require('@overmindtech/sdp-js') - const ClientOAuth2 = require('client-oauth2') - const transport = createConnectTransport({ - --- - api.accessToken.setCustomClaim('https://api.overmind.tech/account-name', event.user.app_metadata.account_name) - // wake up all sources -- const res = await client.keepaliveSources( -+ await client.keepaliveSources( - { - account: event.user.app_metadata.account_name, - }, -`, - }, + sdp.ItemDiffStatus_ITEM_DIFF_STATUS_DELETED: { + StatusAlt: "deleted", + StatusIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/deleted.png", }, - BlastItems: 75, - BlastEdges: 97, - Risks: []TemplateRisk{ - { - SeverityAlt: "high", - SeverityIcon: "https://github.com/overmindtech/ovm-cli/assets/8799341/76a34fd0-7699-4636-9a4c-3cdabdf7783e", - SeverityText: "high", - Title: "Impact on Target Groups", - Description: `The various target groups including \"944651592624.eu-west-2.elbv2-target-group.k8s-default-nats-4650f3a363\", \"944651592624.eu-west-2.elbv2-target-group.k8s-default-smartloo-fd2416d9f8\", etc., that work alongside the load balancer for traffic routing may be indirectly affected if the security group change causes networking issues. This is especially important if these target groups rely on different ports other than 8080 for health checks or for directing incoming requests to backend services.`, - }, + sdp.ItemDiffStatus_ITEM_DIFF_STATUS_REPLACED: { + StatusAlt: "replaced", + StatusIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/replaced.png", }, } + data := TemplateData{ + ChangeUrl: fmt.Sprintf("%v/changes/%v", viper.GetString("frontend"), changeUuid.String()), + ExpectedChanges: []TemplateItem{}, + UnmappedChanges: []TemplateItem{}, + BlastItems: 75, + BlastEdges: 97, + Risks: []TemplateRisk{}, + } + + for _, item := range changeRes.Msg.Change.Properties.PlannedChanges { + var before, after string + if item.Before != nil { + bb, err := yaml.Marshal(item.Before.Attributes.AttrStruct.AsMap()) + if err != nil { + log.WithContext(ctx).WithError(err).Error("error marshalling 'before' attributes") + before = "" + } else { + before = string(bb) + } + } + if item.After != nil { + ab, err := yaml.Marshal(item.After.Attributes.AttrStruct.AsMap()) + if err != nil { + log.WithContext(ctx).WithError(err).Error("error marshalling 'after' attributes") + after = "" + } else { + after = string(ab) + } + } + edits := myers.ComputeEdits(diffspan.URIFromPath("current"), before, after) + diff := fmt.Sprint(gotextdiff.ToUnified("current", "planned", before, edits)) + + if item.Item != nil { + data.ExpectedChanges = append(data.ExpectedChanges, TemplateItem{ + StatusAlt: status[item.Status].StatusAlt, + StatusIcon: status[item.Status].StatusIcon, + Type: item.Item.Type, + Title: item.Item.UniqueAttributeValue, + Diff: diff, + }) + } else { + var typ, title string + if item.After != nil { + typ = item.After.Type + title = item.After.UniqueAttributeValue() + } else if item.Before != nil { + typ = item.Before.Type + title = item.Before.UniqueAttributeValue() + } + data.UnmappedChanges = append(data.ExpectedChanges, TemplateItem{ + StatusAlt: status[item.Status].StatusAlt, + StatusIcon: status[item.Status].StatusIcon, + Type: typ, + Title: title, + Diff: diff, + }) + } + } + tmpl, err := template.New("comment").Parse(commentTemplate) if err != nil { log.WithContext(ctx).WithError(err).Error("error parsing comment template") diff --git a/go.mod b/go.mod index 2b1d3969..c1f61dd3 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( connectrpc.com/connect v1.12.0 github.com/getsentry/sentry-go v0.25.0 github.com/google/uuid v1.4.0 + github.com/hexops/gotextdiff v1.0.3 github.com/jedib0t/go-pretty/v6 v6.4.9 github.com/mattn/go-isatty v0.0.20 github.com/overmindtech/sdp-go v0.57.0 @@ -26,6 +27,7 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 golang.org/x/oauth2 v0.14.0 google.golang.org/protobuf v1.31.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -76,6 +78,5 @@ require ( google.golang.org/grpc v1.58.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.10 // indirect ) diff --git a/go.sum b/go.sum index df3e4d09..3b5963c9 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= From 4e8f4e260e2a1108d56b851ae1987d9a03197c0e Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 16 Nov 2023 12:15:35 +0100 Subject: [PATCH 4/5] Render risks from data --- cmd/getchange.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/cmd/getchange.go b/cmd/getchange.go index ef1a7982..1d373ca3 100644 --- a/cmd/getchange.go +++ b/cmd/getchange.go @@ -188,6 +188,29 @@ func GetChange(ctx context.Context, ready chan bool) int { StatusIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/replaced.png", }, } + + severity := map[sdp.Risk_Severity]TemplateRisk{ + sdp.Risk_SEVERITY_UNSPECIFIED: { + SeverityAlt: "unspecified", + SeverityIcon: "", + SeverityText: "unspecified", + }, + sdp.Risk_SEVERITY_LOW: { + SeverityAlt: "low", + SeverityIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/low.png", + SeverityText: "Low", + }, + sdp.Risk_SEVERITY_MEDIUM: { + SeverityAlt: "medium", + SeverityIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/medium.png", + SeverityText: "Medium", + }, + sdp.Risk_SEVERITY_HIGH: { + SeverityAlt: "high", + SeverityIcon: "https://raw.githubusercontent.com/overmindtech/ovm-cli/ac4feb1b9dd73b5c42c5a515d12517b551d2886b/assets/high.png", + SeverityText: "High", + }, + } data := TemplateData{ ChangeUrl: fmt.Sprintf("%v/changes/%v", viper.GetString("frontend"), changeUuid.String()), ExpectedChanges: []TemplateItem{}, @@ -247,6 +270,16 @@ func GetChange(ctx context.Context, ready chan bool) int { } } + for _, risk := range changeRes.Msg.Change.Metadata.Risks { + data.Risks = append(data.Risks, TemplateRisk{ + SeverityAlt: severity[risk.Severity].SeverityAlt, + SeverityIcon: severity[risk.Severity].SeverityIcon, + SeverityText: severity[risk.Severity].SeverityText, + Title: risk.Title, + Description: risk.Description, + }) + } + tmpl, err := template.New("comment").Parse(commentTemplate) if err != nil { log.WithContext(ctx).WithError(err).Error("error parsing comment template") From c6ab49ff2de13fe2d8274c7a7b8aacb6ab9dace2 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 16 Nov 2023 14:49:24 +0100 Subject: [PATCH 5/5] Improve display of unchanged attributes --- cmd/comment.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cmd/comment.md b/cmd/comment.md index d3e4e1f3..b47c1e28 100644 --- a/cmd/comment.md +++ b/cmd/comment.md @@ -4,9 +4,13 @@
{{ .StatusAlt }} {{ .Type }} › {{ .Title }} +{{if .Diff }} ```diff {{ .Diff }} ``` +{{else}} +(no changed attributes) +{{end}}
{{else}} No expected changes found. @@ -23,12 +27,16 @@ No expected changes found.
{{ .StatusAlt }} {{ .Type }} › {{ .Title }} +{{if .Diff }} ```diff {{ .Diff }} ``` +{{else}} +(no changed attributes) +{{end}}
{{else}} -No expected changes found. +No unmapped changes found. {{end}}