Skip to content

Commit cfc9663

Browse files
authored
feat/support drift advanced mode (#2062)
* support advanced drift detection in slack
1 parent 96cd075 commit cfc9663

File tree

13 files changed

+220
-71
lines changed

13 files changed

+220
-71
lines changed

action.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ inputs:
191191
description: 'drift-detection slack drift url'
192192
required: false
193193
default: ''
194+
drift-detection-advanced-slack-notification-url:
195+
description: 'drift-detection slack drift url (advanced mode, ee only)'
196+
required: false
197+
default: ''
194198
cache-dependencies:
195199
description: "Leverage actions/cache to cache dependencies to speed up execution"
196200
required: false
@@ -420,6 +424,8 @@ runs:
420424
INPUT_DIGGER_MODE: ${{ inputs.mode }}
421425
INPUT_DIGGER_COMMAND: ${{ inputs.command }}
422426
INPUT_DRIFT_DETECTION_SLACK_NOTIFICATION_URL: ${{ inputs.drift-detection-slack-notification-url }}
427+
INPUT_DRIFT_DETECTION_ADVANCED_SLACK_NOTIFICATION_URL: ${{ inputs.drift-detection-advanced-slack-notification-url }}
428+
423429
NO_BACKEND: ${{ inputs.no-backend }}
424430
DEBUG: 'true'
425431
TG_PROVIDER_CACHE: ${{ inputs.cache-dependencies == 'true' && 1 || 0 }}
@@ -467,6 +473,7 @@ runs:
467473
INPUT_DIGGER_MODE: ${{ inputs.mode }}
468474
INPUT_DIGGER_COMMAND: ${{ inputs.command }}
469475
INPUT_DRIFT_DETECTION_SLACK_NOTIFICATION_URL: ${{ inputs.drift-detection-slack-notification-url }}
476+
INPUT_DRIFT_DETECTION_ADVANCED_SLACK_NOTIFICATION_URL: ${{ inputs.drift-detection-advanced-slack-notification-url }}
470477
NO_BACKEND: ${{ inputs.no-backend }}
471478
TG_PROVIDER_CACHE: ${{ inputs.cache-dependencies == 'true' && 1 || 0 }}
472479
TERRAGRUNT_PROVIDER_CACHE: ${{ inputs.cache-dependencies == 'true' && 1 || 0 }}

cli/pkg/core/drift/drift.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package drift
22

33
type Notification interface {
4-
Send(projectName string, plan string) error
4+
SendNotificationForProject(projectName string, repoFullName string, plan string) error
5+
SendErrorNotificationForProject(projectName string, repoFullName string, err error) error
6+
Flush() error
57
}

cli/pkg/digger/digger.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,9 +762,11 @@ func runDriftDetection(policyChecker policy.Checker, SCMOrganisation string, SCM
762762
slog.Warn("Warning: no notification configured, not sending any notifications")
763763
return plan, nil
764764
}
765-
err := (*notification).Send(projectName, plan)
765+
repoFullName := fmt.Sprintf("%s/%s", SCMOrganisation, SCMrepository)
766+
err := (*notification).SendNotificationForProject(projectName, repoFullName, plan)
766767
if err != nil {
767768
slog.Error("Error sending drift drift.", "error", err)
769+
return plan, fmt.Errorf("failed to send drift. %v", err)
768770
}
769771
} else if planPerformed && !nonEmptyPlan {
770772
slog.Info("No drift detected")

cli/pkg/drift/Provider.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func (d DriftNotificationProviderBasic) Get(prService ci.PullRequestService) (co
1717
slackNotificationUrl := os.Getenv("INPUT_DRIFT_DETECTION_SLACK_NOTIFICATION_URL")
1818
var notification core_drift.Notification
1919
if slackNotificationUrl != "" {
20-
notification = SlackNotification{slackNotificationUrl}
20+
notification = &SlackNotification{slackNotificationUrl}
2121
} else {
2222
return nil, fmt.Errorf("could not identify drift mode, please specify slack using env variable INPUT_DRIFT_DETECTION_SLACK_NOTIFICATION_URL")
2323
}

cli/pkg/drift/slack.go

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
package drift
22

33
import (
4-
"bytes"
5-
"encoding/json"
64
"fmt"
7-
"io"
85
"log/slog"
9-
"net/http"
106
"regexp"
117
"strings"
128
)
@@ -40,48 +36,39 @@ func SplitCodeBlocks(message string) []string {
4036
return res
4137
}
4238

43-
func (slack SlackNotification) Send(projectName string, plan string) error {
44-
message := fmt.Sprintf(":bangbang: Drift detected in digger project %v details below: \n\n```\n%v\n```", projectName, plan)
45-
httpClient := &http.Client{}
46-
type SlackMessage struct {
47-
Text string `json:"text"`
48-
}
39+
func (slack *SlackNotification) SendNotificationForProject(projectName string, repoFullName string, plan string) error {
40+
message := fmt.Sprintf(
41+
":warning: *Infrastructure Drift Detected* :warning:\n\n"+
42+
":file_folder: *Project:* `%s`\n"+
43+
":books: *Repository:* `%s`\n\n"+
44+
":memo: *Terraform Plan:*\n```\n%v\n```\n\n",
45+
projectName, repoFullName, plan,
46+
)
4947
parts := SplitCodeBlocks(message)
5048
for _, part := range parts {
51-
slackMessage := SlackMessage{
52-
Text: part,
53-
}
54-
55-
jsonData, err := json.Marshal(slackMessage)
56-
if err != nil {
57-
slog.Error("failed to marshal slack message", "error", err)
58-
return err
59-
}
60-
61-
request, err := http.NewRequest("POST", slack.Url, bytes.NewBuffer(jsonData))
62-
if err != nil {
63-
slog.Error("failed to create slack drift request", "error", err)
64-
return err
65-
}
66-
67-
request.Header.Set("Content-Type", "application/json")
68-
resp, err := httpClient.Do(request)
49+
err := SendSlackMessage(slack.Url, part)
6950
if err != nil {
7051
slog.Error("failed to send slack drift request", "error", err)
7152
return err
7253
}
73-
if resp.StatusCode != 200 {
74-
body, err := io.ReadAll(resp.Body)
75-
if err != nil {
76-
slog.Error("failed to read response body", "error", err)
77-
return err
78-
}
79-
slog.Error("failed to send slack drift request", "status code", resp.Status, "body", body)
80-
msg := fmt.Sprintf("failed to send slack drift request. %v. Message: %v", resp.Status, body)
81-
return fmt.Errorf("%s", msg)
82-
}
83-
resp.Body.Close()
8454
}
8555

8656
return nil
8757
}
58+
59+
func (slack *SlackNotification) SendErrorNotificationForProject(projectName string, repoFullName string, err error) error {
60+
message := fmt.Sprintf(
61+
":rotating_light: *Error While Drift Processing* :rotating_light:\n\n"+
62+
":file_folder: *Project:* `%s`\n"+
63+
":books: *Repository:* `%s`\n\n"+
64+
":warning: *Error Details:*\n```\n%v\n```\n\n"+
65+
"_Please check the workflow logs for more information._",
66+
projectName, repoFullName, err,
67+
)
68+
69+
return SendSlackMessage(slack.Url, message)
70+
}
71+
72+
func (slack *SlackNotification) Flush() error {
73+
return nil
74+
}

cli/pkg/drift/slack_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ func TestSendSlackMessageThatIsLargerThan2Parts(t *testing.T) {
2828
t.Skip("Skipping slack message test: $TEST_SLACK_NOTIFICATION_URL not set")
2929
}
3030
projectName := "dev"
31+
repoFullName := "terraform-aws-modules/terraform-aws-eks"
3132
plan := ":bangbang: drift detected\n\n ```\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\n\n\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\nhere it is\n\n```"
3233
notification := SlackNotification{Url: url}
33-
err := notification.Send(projectName, plan)
34+
err := notification.SendNotificationForProject(projectName, repoFullName, plan)
3435
assert.Equal(t, nil, err)
3536
}

cli/pkg/drift/utils.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package drift
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"log/slog"
9+
"net/http"
10+
)
11+
12+
func SendSlackMessage(slackUrl string, message string) error {
13+
type SlackMessage struct {
14+
Text string `json:"text"`
15+
}
16+
17+
httpClient := &http.Client{}
18+
slackMessage := SlackMessage{
19+
Text: message,
20+
}
21+
jsonData, err := json.Marshal(slackMessage)
22+
if err != nil {
23+
slog.Error("failed to marshal slack message", "error", err)
24+
return err
25+
}
26+
27+
request, err := http.NewRequest("POST", slackUrl, bytes.NewBuffer(jsonData))
28+
if err != nil {
29+
slog.Error("failed to create slack drift request", "error", err)
30+
return err
31+
}
32+
33+
request.Header.Set("Content-Type", "application/json")
34+
resp, err := httpClient.Do(request)
35+
if err != nil {
36+
slog.Error("failed to send slack drift request", "error", err)
37+
return err
38+
}
39+
if resp.StatusCode != 200 {
40+
body, err := io.ReadAll(resp.Body)
41+
if err != nil {
42+
slog.Error("failed to read response body", "error", err)
43+
return err
44+
}
45+
slog.Error("failed to send slack drift request", "status code", resp.Status, "body", body)
46+
msg := fmt.Sprintf("failed to send slack drift request. %v. Message: %v", resp.Status, body)
47+
return fmt.Errorf("%s", msg)
48+
}
49+
resp.Body.Close()
50+
return nil
51+
}

cli/pkg/github/github.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func GitHubCI(lock core_locking.Lock, policyCheckerProvider core_policy.PolicyCh
146146
usage.ReportErrorAndExit(githubActor, "provide 'project' to run in 'manual' mode", 2)
147147
}
148148

149-
projectConfig, projectFound := findProjectInConfig(diggerConfig.Projects, project)
149+
projectConfig, projectFound := findProjectInConfig(diggerConfig.Projects, project)
150150

151151
if !projectFound {
152152
// Log available projects to help with debugging
@@ -197,6 +197,10 @@ func GitHubCI(lock core_locking.Lock, policyCheckerProvider core_policy.PolicyCh
197197
} else if runningMode == "drift-detection" {
198198
blockFiltersStr := os.Getenv("INPUT_DIGGER_BLOCK_FILTERS")
199199
blockFilters := strings.Split(blockFiltersStr, ",")
200+
notification, err := driftNotificationProvider.Get(githubPrService)
201+
if err != nil {
202+
usage.ReportErrorAndExit(githubActor, fmt.Sprintf("could not get drift notification type: %v", err), 8)
203+
}
200204
for _, projectConfig := range diggerConfig.Projects {
201205
if !projectConfig.DriftDetection {
202206
continue
@@ -249,16 +253,19 @@ func GitHubCI(lock core_locking.Lock, policyCheckerProvider core_policy.PolicyCh
249253
CommandRoleArn: cmdArn,
250254
}
251255

252-
notification, err := driftNotificationProvider.Get(githubPrService)
253-
if err != nil {
254-
usage.ReportErrorAndExit(githubActor, fmt.Sprintf("could not get drift notification type: %v", err), 8)
255-
}
256-
257256
err = digger.RunJob(job, ghRepository, githubActor, &githubPrService, policyChecker, nil, backendApi, &notification, currentDir)
258257
if err != nil {
259-
usage.ReportErrorAndExit(githubActor, fmt.Sprintf("Failed to run commands. %s", err), 8)
258+
slog.Error("Failed to run commands", "repository", ghRepository, "project", projectConfig.Name, "error", err)
259+
notificationErr := notification.SendErrorNotificationForProject(projectConfig.Name, ghRepository, err)
260+
if notificationErr != nil {
261+
slog.Error("Failed to send error notification", "repository", ghRepository, "project", projectConfig.Name, "error", notificationErr)
262+
}
260263
}
261264
}
265+
err = notification.Flush()
266+
if err != nil {
267+
usage.ReportErrorAndExit(githubActor, fmt.Sprintf("Failed to flush drift notification. %s", err), 8)
268+
}
262269
} else {
263270

264271
impactedProjects, requestedProject, prNumber, err := dg_github.ProcessGitHubEvent(ghEvent, diggerConfig, &githubPrService)

ee/cli/pkg/drift/github_issue.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type GithubIssueNotification struct {
1212
RelatedPrNumber *int64
1313
}
1414

15-
func (ghi GithubIssueNotification) Send(projectName string, plan string) error {
15+
func (ghi *GithubIssueNotification) SendNotificationForProject(projectName string, repoFullName string, plan string) error {
1616
log.Printf("Info: Sending drift notification regarding project: %v", projectName)
1717
title := fmt.Sprintf("Drift detected in project: %v", projectName)
1818
message := fmt.Sprintf(":bangbang: Drift detected in digger project %v details below: \n\n```\n%v\n```", projectName, plan)
@@ -41,3 +41,11 @@ func (ghi GithubIssueNotification) Send(projectName string, plan string) error {
4141
}
4242
return nil
4343
}
44+
45+
func (ghi *GithubIssueNotification) SendErrorNotificationForProject(projectName string, repoFullName string, err error) error {
46+
return nil
47+
}
48+
49+
func (ghi *GithubIssueNotification) Flush() error {
50+
return nil
51+
}

ee/cli/pkg/drift/provider.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ type DriftNotificationProviderAdvanced struct{}
1212

1313
func (d DriftNotificationProviderAdvanced) Get(prService ci.PullRequestService) (core_drift.Notification, error) {
1414
slackNotificationUrl := os.Getenv("INPUT_DRIFT_DETECTION_SLACK_NOTIFICATION_URL")
15+
slackNotificationAdvancedUrl := os.Getenv("INPUT_DRIFT_DETECTION_ADVANCED_SLACK_NOTIFICATION_URL")
1516
DriftAsGithubIssues := os.Getenv("INPUT_DRIFT_GITHUB_ISSUES")
1617
var notification core_drift.Notification
1718
if slackNotificationUrl != "" {
18-
notification = drift.SlackNotification{slackNotificationUrl}
19+
notification = &drift.SlackNotification{Url: slackNotificationUrl}
20+
} else if slackNotificationAdvancedUrl != "" {
21+
notification = NewSlackAdvancedAggregatedNotificationWithAiSummary(slackNotificationAdvancedUrl)
1922
} else if DriftAsGithubIssues != "" {
20-
notification = GithubIssueNotification{GithubService: &prService}
23+
notification = &GithubIssueNotification{GithubService: &prService}
2124
} else {
22-
return nil, fmt.Errorf("could not identify drift mode, please specify slack or github")
25+
return nil, fmt.Errorf("could not identify drift mode, please specify using env variable INPUT_DRIFT_DETECTION_SLACK_NOTIFICATION_URL, INPUT_DRIFT_DETECTION_ADVANCED_SLACK_NOTIFICATION_URL or INPUT_DRIFT_GITHUB_ISSUES")
2326
}
2427
return notification, nil
2528
}

0 commit comments

Comments
 (0)