diff --git a/pkg/app/piped/notifier/BUILD.bazel b/pkg/app/piped/notifier/BUILD.bazel index d22de40391..1b1c45dd36 100644 --- a/pkg/app/piped/notifier/BUILD.bazel +++ b/pkg/app/piped/notifier/BUILD.bazel @@ -12,6 +12,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/config:go_default_library", + "//pkg/git:go_default_library", "//pkg/model:go_default_library", "//pkg/version:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", diff --git a/pkg/app/piped/notifier/slack.go b/pkg/app/piped/notifier/slack.go index 99da863514..aba9c26890 100644 --- a/pkg/app/piped/notifier/slack.go +++ b/pkg/app/piped/notifier/slack.go @@ -27,6 +27,7 @@ import ( "go.uber.org/zap" "github.com/pipe-cd/pipe/pkg/config" + "github.com/pipe-cd/pipe/pkg/git" "github.com/pipe-cd/pipe/pkg/model" ) @@ -151,6 +152,22 @@ func (s *slack) buildSlackMessage(event model.NotificationEvent, webURL string) {"Started At", makeSlackDate(d.CreatedAt), true}, } } + generateDeploymentEventDataForTriggerFailed := func(app *model.Application, hash, msg string) { + link = fmt.Sprintf("%s/applications/%s?project=%s", webURL, app.Id, app.ProjectId) + commitURL, err := git.MakeCommitURL(app.GitPath.Repo.Remote, hash) + if err != nil { + s.logger.Error(fmt.Sprintf("failed to get the URL for the specified commit: %v", err)) + } + fields = []slackField{ + {"Project", truncateText(app.ProjectId, 8), true}, + {"Application", makeSlackLink(app.Name, link), true}, + {"Kind", strings.ToLower(app.Kind.String()), true}, + } + if commitURL != "" { + fields = append(fields, slackField{"Commit", makeSlackLink(truncateText(msg, 8), commitURL), true}) + } + + } generatePipedEventData := func(id, name, version, project string) { link = fmt.Sprintf("%s/settings/piped?project=%s", webURL, project) fields = []slackField{ @@ -204,6 +221,12 @@ func (s *slack) buildSlackMessage(event model.NotificationEvent, webURL string) color = slackWarnColor generateDeploymentEventData(md.Deployment, md.EnvName, getAccountsAsString(md.MentionedAccounts)) + case model.NotificationEventType_EVENT_DEPLOYMENT_TRIGGER_FAILED: + md := event.Metadata.(*model.NotificationEventDeploymentTriggerFailed) + title = fmt.Sprintf("Failed to trigger a new deployment for %s", md.Application.Name) + text = md.Reason + generateDeploymentEventDataForTriggerFailed(md.Application, md.CommitHash, md.CommitMessage) + case model.NotificationEventType_EVENT_PIPED_STARTED: md := event.Metadata.(*model.NotificationEventPipedStarted) title = "A piped has been started" diff --git a/pkg/app/piped/trigger/BUILD.bazel b/pkg/app/piped/trigger/BUILD.bazel index 28126f1dca..eb8fc419c4 100644 --- a/pkg/app/piped/trigger/BUILD.bazel +++ b/pkg/app/piped/trigger/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//pkg/filematcher:go_default_library", "//pkg/git:go_default_library", "//pkg/model:go_default_library", + "//pkg/version:go_default_library", "@com_github_google_uuid//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", diff --git a/pkg/app/piped/trigger/deployment.go b/pkg/app/piped/trigger/deployment.go index 2d5a2d8d53..980ca569c0 100644 --- a/pkg/app/piped/trigger/deployment.go +++ b/pkg/app/piped/trigger/deployment.go @@ -44,12 +44,14 @@ func (t *Trigger) triggerDeployment( n, err := t.getNotification(app.GitPath) if err != nil { t.logger.Error("failed to get the list of mentions", zap.Error(err)) + t.reportDeploymentFailed(app, fmt.Sprintf("failed to find the list of mentions from %s: %v", app.GitPath.GetDeploymentConfigFilePath(), err), commit) return } deployment, err = buildDeployment(app, branch, commit, commander, syncStrategy, time.Now(), n) if err != nil { t.logger.Error("failed to build the deployment", zap.Error(err)) + t.reportDeploymentFailed(app, fmt.Sprintf("failed to build the deployment: %v", err), commit) return } @@ -60,10 +62,12 @@ func (t *Trigger) triggerDeployment( defer func() { if err != nil { + t.reportDeploymentFailed(app, fmt.Sprintf("%v", err), commit) return } env, err := t.environmentLister.Get(ctx, deployment.EnvId) if err != nil { + t.reportDeploymentFailed(app, fmt.Sprintf("%v", err), commit) return } t.notifier.Notify(model.NotificationEvent{ @@ -84,6 +88,7 @@ func (t *Trigger) triggerDeployment( } if _, err = t.apiClient.CreateDeployment(ctx, req); err != nil { t.logger.Error("failed to create deployment", zap.Error(err)) + t.reportDeploymentFailed(app, fmt.Sprintf("failed to create deployment: %v", err), commit) return } @@ -183,6 +188,18 @@ func buildDeployment( return deployment, nil } +func (t *Trigger) reportDeploymentFailed(app *model.Application, reason string, commit git.Commit) { + t.notifier.Notify(model.NotificationEvent{ + Type: model.NotificationEventType_EVENT_DEPLOYMENT_TRIGGER_FAILED, + Metadata: &model.NotificationEventDeploymentTriggerFailed{ + Application: app, + CommitHash: commit.Hash, + CommitMessage: commit.Message, + Reason: reason, + }, + }) +} + func (t *Trigger) getNotification(p *model.ApplicationGitPath) (*config.DeploymentNotification, error) { // Find the application repo from pre-loaded ones. repo, ok := t.gitRepos[p.Repo.Id] diff --git a/pkg/app/piped/trigger/trigger.go b/pkg/app/piped/trigger/trigger.go index 7b3831a75c..e87fc57184 100644 --- a/pkg/app/piped/trigger/trigger.go +++ b/pkg/app/piped/trigger/trigger.go @@ -233,6 +233,7 @@ func (t *Trigger) checkNewCommits(ctx context.Context) error { shouldTrigger, err := d.ShouldTrigger(ctx, app) if err != nil { t.logger.Error(fmt.Sprintf("failed to check application: %s", app.Id), zap.Error(err)) + t.reportDeploymentFailed(app, fmt.Sprintf("failed to find the list of mentions from %s: %v", app.GitPath.GetDeploymentConfigFilePath(), err), headCommit) continue } diff --git a/pkg/model/notificationevent.proto b/pkg/model/notificationevent.proto index 650dd256ef..17cd7dcf6c 100644 --- a/pkg/model/notificationevent.proto +++ b/pkg/model/notificationevent.proto @@ -30,6 +30,7 @@ enum NotificationEventType { EVENT_DEPLOYMENT_FAILED = 5; EVENT_DEPLOYMENT_CANCELLED = 6; EVENT_DEPLOYMENT_WAIT_APPROVAL = 7; + EVENT_DEPLOYMENT_TRIGGER_FAILED = 8; EVENT_APPLICATION_SYNCED = 100; EVENT_APPLICATION_OUT_OF_SYNC = 101; @@ -39,7 +40,6 @@ enum NotificationEventType { EVENT_PIPED_STARTED = 300; EVENT_PIPED_STOPPED = 301; - } enum NotificationEventGroup { @@ -101,6 +101,13 @@ message NotificationEventDeploymentWaitApproval { repeated string mentioned_accounts = 3; } +message NotificationEventDeploymentTriggerFailed { + Application application = 1 [(validate.rules).message.required = true]; + string commit_hash = 2 [(validate.rules).string.min_len = 1]; + string commit_message = 3 [(validate.rules).string.min_len = 1]; + string reason = 4 [(validate.rules).string.min_len = 1]; +} + message NotificationEventApplicationSynced { Application application = 1 [(validate.rules).message.required = true]; string env_name = 2 [(validate.rules).string.min_len = 1];