Browse Source

changes to support new app revision statuses on front end (#4050)

Feroze Mohideen 2 years ago
parent
commit
d0816dc332

+ 20 - 12
api/server/handlers/porter_app/create_and_update_events.go

@@ -86,7 +86,7 @@ func (p *CreateUpdatePorterAppEventHandler) ServeHTTP(w http.ResponseWriter, r *
 				return
 			}
 		} else {
-			event, err = p.createNewAppEvent(ctx, *cluster, appName, request.DeploymentTargetID, request.Status, string(request.Type), request.TypeExternalSource, request.Metadata)
+			event, err = p.createNewAppEvent(ctx, *project, *cluster, appName, request.DeploymentTargetID, request.Status, string(request.Type), request.TypeExternalSource, request.Metadata)
 			if err != nil {
 				e := telemetry.Error(ctx, span, err, "error creating new app event")
 				p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusBadRequest))
@@ -138,7 +138,7 @@ func reportBuildStatus(ctx context.Context, request *types.CreateOrUpdatePorterA
 }
 
 // createNewAppEvent will create a new app event for the given porter app name. If the app event is an agent event, then it will be created only if there is no existing event which has the agent ID. In the case that an existing event is found, that will be returned instead
-func (p *CreateUpdatePorterAppEventHandler) createNewAppEvent(ctx context.Context, cluster models.Cluster, porterAppName string, deploymentTargetID string, status types.PorterAppEventStatus, eventType string, externalSource string, requestMetadata map[string]any) (types.PorterAppEvent, error) {
+func (p *CreateUpdatePorterAppEventHandler) createNewAppEvent(ctx context.Context, project models.Project, cluster models.Cluster, porterAppName string, deploymentTargetID string, status types.PorterAppEventStatus, eventType string, externalSource string, requestMetadata map[string]any) (types.PorterAppEvent, error) {
 	ctx, span := telemetry.NewSpan(ctx, "create-porter-app-event")
 	defer span.End()
 
@@ -193,17 +193,25 @@ func (p *CreateUpdatePorterAppEventHandler) createNewAppEvent(ctx context.Contex
 				}
 				return event, nil
 			} else {
-				err := p.updateDeployEventV2(ctx, updateDeployEventV2Input{
-					projectID:             cluster.ProjectID,
-					appName:               porterAppName,
-					appID:                 app.ID,
-					deploymentTargetID:    deploymentTargetID,
-					updatedStatusMetadata: requestMetadata,
-				})
-				if err != nil {
-					return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error updating v2 deploy event")
+				betaFeaturesEnabled := project.GetFeatureFlag(models.BetaFeaturesEnabled, p.Config().LaunchDarklyClient)
+				telemetry.WithAttributes(span,
+					telemetry.AttributeKV{Key: "beta_features_enabled", Value: betaFeaturesEnabled},
+				)
+				// if beta features are not enabled, then porter makes a request to ccp to update the deploy status
+				// if beta features are enabled, ccp is checking the deploy status, so this request is not necessary
+				// TODO remove this entire branch once beta features are enabled by default
+				if !betaFeaturesEnabled {
+					err := p.updateDeployEventV2(ctx, updateDeployEventV2Input{
+						projectID:             cluster.ProjectID,
+						appName:               porterAppName,
+						appID:                 app.ID,
+						deploymentTargetID:    deploymentTargetID,
+						updatedStatusMetadata: requestMetadata,
+					})
+					if err != nil {
+						return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error updating v2 deploy event")
+					}
 				}
-				// v2 method calls ccp and will not return an event, so we just return an empty event
 				return types.PorterAppEvent{}, nil
 			}
 		}

+ 2 - 2
api/server/handlers/porter_app/report_status.go

@@ -242,9 +242,9 @@ func writePRComment(ctx context.Context, inp writePRCommentInput) error {
 	switch inp.revision.Status {
 	case models.AppRevisionStatus_BuildFailed:
 		body = fmt.Sprintf("%s❌ The latest deploy failed to build. Check the [Porter Dashboard](%s) or [action logs](https://github.com/%s/actions/runs/) for more information.", body, porterURL, inp.porterApp.RepoName)
-	case models.AppRevisionStatus_DeployFailed:
+	case models.AppRevisionStatus_InstallFailed:
 		body = fmt.Sprintf("%s❌ The latest SHA ([`%s`](https://github.com/%s/%s/commit/%s)) failed to deploy.\nCheck the [Porter Dashboard](%s) or [action logs](https://github.com/%s/actions/runs/) for more information.\nContact Porter Support if the errors persists", body, inp.commitSha, repoDetails[0], repoDetails[1], inp.commitSha, porterURL, inp.porterApp.RepoName)
-	case models.AppRevisionStatus_Deployed:
+	case models.AppRevisionStatus_InstallSuccessful:
 		body = fmt.Sprintf("%s✅ The latest SHA ([`%s`](https://github.com/%s/%s/commit/%s)) has been successfully deployed.\nApp details available in the [Porter Dashboard](%s)", body, inp.commitSha, repoDetails[0], repoDetails[1], inp.commitSha, porterURL)
 	default:
 		return nil

+ 1 - 1
api/server/handlers/porter_app/update_app_revision_status.go

@@ -78,7 +78,7 @@ func (c *UpdateAppRevisionStatusHandler) ServeHTTP(w http.ResponseWriter, r *htt
 	switch request.Status {
 	case models.AppRevisionStatus_BuildFailed:
 		statusProto = porterv1.EnumRevisionStatus_ENUM_REVISION_STATUS_BUILD_FAILED
-	case models.AppRevisionStatus_DeployFailed:
+	case models.AppRevisionStatus_InstallFailed:
 		statusProto = porterv1.EnumRevisionStatus_ENUM_REVISION_STATUS_DEPLOY_FAILED
 	case models.AppRevisionStatus_PredeployFailed:
 		statusProto = porterv1.EnumRevisionStatus_ENUM_REVISION_STATUS_PREDEPLOY_FAILED

+ 7 - 2
cli/cmd/v2/update.go

@@ -215,7 +215,12 @@ func Update(ctx context.Context, inp UpdateInput) error {
 		}
 		status = revision.AppRevision.Status
 
-		if status == models.AppRevisionStatus_DeployFailed || status == models.AppRevisionStatus_PredeployFailed || status == models.AppRevisionStatus_Deployed {
+		if status == models.AppRevisionStatus_PredeployFailed ||
+			status == models.AppRevisionStatus_InstallFailed ||
+			status == models.AppRevisionStatus_InstallSuccessful ||
+			status == models.AppRevisionStatus_DeploymentSuccessful ||
+			status == models.AppRevisionStatus_DeploymentProgressing ||
+			status == models.AppRevisionStatus_DeploymentFailed {
 			break
 		}
 		if status == models.AppRevisionStatus_AwaitingPredeploy {
@@ -234,7 +239,7 @@ func Update(ctx context.Context, inp UpdateInput) error {
 		CommitSHA:     commitSHA,
 	})
 
-	if status == models.AppRevisionStatus_DeployFailed {
+	if status == models.AppRevisionStatus_InstallFailed {
 		return errors.New("app failed to deploy")
 	}
 	if status == models.AppRevisionStatus_PredeployFailed {

+ 3 - 0
dashboard/src/lib/revisions/types.ts

@@ -19,6 +19,9 @@ export const appRevisionValidator = z.object({
     "DEPLOY_FAILED",
     "APPLY_FAILED",
     "UPDATE_FAILED",
+    "DEPLOYMENT_PROGRESSING",
+    "DEPLOYMENT_SUCCESSFUL",
+    "DEPLOYMENT_FAILED",
   ]),
   b64_app_proto: z.string(),
   revision_number: z.number(),

+ 7 - 1
dashboard/src/main/home/app-dashboard/validate-apply/revisions-list/GHStatusBanner.tsx

@@ -62,7 +62,10 @@ const GHStatusBanner: React.FC = () => {
   const previouslyBuilt = useMemo(() => {
     if (revisions.length === 1) {
       if (
-        revisions[0].status === "DEPLOYED" &&
+        // TODO: remove checking for DEPLOYED status once update flow is released,
+        // because once that happens, the new terminal status will be DEPLOYMENT_SUCCESSFUL
+        (revisions[0].status === "DEPLOYMENT_SUCCESSFUL" ||
+          revisions[0].status === "DEPLOYED") &&
         latestProto.image?.tag === HELLO_PORTER_PLACEHOLDER_TAG
       ) {
         return false;
@@ -76,6 +79,9 @@ const GHStatusBanner: React.FC = () => {
           "DEPLOY_FAILED",
           "BUILD_FAILED",
           "IMAGE_AVAILABLE",
+          "DEPLOYMENT_PROGRESSING",
+          "DEPLOYMENT_SUCCESSFUL",
+          "DEPLOYMENT_FAILED",
           () => true
         )
         .otherwise(() => false)

+ 18 - 14
internal/models/app_revision.go

@@ -17,30 +17,34 @@ const (
 	AppRevisionStatus_ImageAvailable AppRevisionStatus = "IMAGE_AVAILABLE"
 	// AppRevisionStatus_AwaitingBuild is the status for a revision that still needs to be built
 	AppRevisionStatus_AwaitingBuild AppRevisionStatus = "AWAITING_BUILD_ARTIFACT"
-	// AppRevisionStatus_AwaitingPredeploy is the status for a revision that is waiting for a predeploy to be run
-	AppRevisionStatus_AwaitingPredeploy AppRevisionStatus = "AWAITING_PREDEPLOY"
-	// AppRevisionStatus_AwaitingDeploy is the status for a revision that is waiting to be deployed
-	AppRevisionStatus_AwaitingDeploy AppRevisionStatus = "AWAITING_DEPLOY"
-	// AppRevisionStatus_PredeployProgressing is the status for a revision that is currently running a predeploy
-	AppRevisionStatus_PredeployProgressing AppRevisionStatus = "PREDEPLOY_PROGRESSING"
-	// AppRevisionStatus_Deployed is the status for a revision that has been deployed
-	AppRevisionStatus_Deployed AppRevisionStatus = "DEPLOYED"
-	// AppRevisionStatus_Deploying is the status for a revision that is currently deploying
-	AppRevisionStatus_Deploying AppRevisionStatus = "DEPLOYING"
-
 	// AppRevisionStatus_BuildCanceled is the status for a revision that was canceled during the build process
 	AppRevisionStatus_BuildCanceled AppRevisionStatus = "BUILD_CANCELED"
 	// AppRevisionStatus_BuildFailed is the status for a revision that failed to build
 	AppRevisionStatus_BuildFailed AppRevisionStatus = "BUILD_FAILED"
 	// AppRevisionStatus_BuildSuccessful is the status for a revision that successfully built
 	AppRevisionStatus_BuildSuccessful AppRevisionStatus = "BUILD_SUCCESSFUL"
+	// AppRevisionStatus_AwaitingPredeploy is the status for a revision that is waiting for a predeploy to be run
+	AppRevisionStatus_AwaitingPredeploy AppRevisionStatus = "AWAITING_PREDEPLOY"
+	// AppRevisionStatus_PredeployProgressing is the status for a revision that is currently running a predeploy
+	AppRevisionStatus_PredeployProgressing AppRevisionStatus = "PREDEPLOY_PROGRESSING"
 	// AppRevisionStatus_PredeployFailed is the status for a revision that failed to predeploy
 	AppRevisionStatus_PredeployFailed AppRevisionStatus = "PREDEPLOY_FAILED"
 	// AppRevisionStatus_PredeploySuccessful is the status for a revision that successfully ran a predeploy
 	AppRevisionStatus_PredeploySuccessful AppRevisionStatus = "PREDEPLOY_SUCCESSFUL"
-	// AppRevisionStatus_DeployFailed is the status for a revision that failed to deploy
-	AppRevisionStatus_DeployFailed AppRevisionStatus = "DEPLOY_FAILED"
-
+	// AppRevisionStatus_AwaitingInstall is the status for a revision that is waiting to be installed
+	AppRevisionStatus_AwaitingInstall AppRevisionStatus = "AWAITING_DEPLOY"
+	// AppRevisionStatus_InstallProgressing is the status for a revision that is currently installing
+	AppRevisionStatus_InstallProgressing AppRevisionStatus = "DEPLOYING"
+	// AppRevisionStatus_InstallSuccessful is the status for a revision that has been installed
+	AppRevisionStatus_InstallSuccessful AppRevisionStatus = "DEPLOYED"
+	// AppRevisionStatus_InstallFailed is the status for a revision that failed to install
+	AppRevisionStatus_InstallFailed AppRevisionStatus = "DEPLOY_FAILED"
+	// AppRevisionStatus_DeploymentProgressing is the status for a revision that is currently deploying
+	AppRevisionStatus_DeploymentProgressing AppRevisionStatus = "DEPLOYMENT_PROGRESSING"
+	// AppRevisionStatus_DeploymentSuccessful is the status for a revision that successfully deployed
+	AppRevisionStatus_DeploymentSuccessful AppRevisionStatus = "DEPLOYMENT_SUCCESSFUL"
+	// AppRevisionStatus_DeploymentFailed is the status for a revision that failed to deploy
+	AppRevisionStatus_DeploymentFailed AppRevisionStatus = "DEPLOYMENT_FAILED"
 	// AppRevisionStatus_ApplyFailed is the status for a revision that failed due to an internal system error
 	AppRevisionStatus_ApplyFailed AppRevisionStatus = "APPLY_FAILED"
 	// AppRevisionStatus_UpdateFailed is the status for a revision that failed due to an internal system error

+ 14 - 9
internal/porter_app/revisions.go

@@ -217,12 +217,12 @@ func appRevisionStatusFromProto(status string) (models.AppRevisionStatus, error)
 		appRevisionStatus = models.AppRevisionStatus_AwaitingBuild
 	case string(models.AppRevisionStatus_AwaitingPredeploy):
 		appRevisionStatus = models.AppRevisionStatus_AwaitingPredeploy
-	case string(models.AppRevisionStatus_Deployed):
-		appRevisionStatus = models.AppRevisionStatus_Deployed
-	case string(models.AppRevisionStatus_Deploying):
-		appRevisionStatus = models.AppRevisionStatus_Deploying
-	case string(models.AppRevisionStatus_AwaitingDeploy):
-		appRevisionStatus = models.AppRevisionStatus_AwaitingDeploy
+	case string(models.AppRevisionStatus_InstallSuccessful):
+		appRevisionStatus = models.AppRevisionStatus_InstallSuccessful
+	case string(models.AppRevisionStatus_InstallProgressing):
+		appRevisionStatus = models.AppRevisionStatus_InstallProgressing
+	case string(models.AppRevisionStatus_AwaitingInstall):
+		appRevisionStatus = models.AppRevisionStatus_AwaitingInstall
 	case string(models.AppRevisionStatus_BuildCanceled):
 		appRevisionStatus = models.AppRevisionStatus_BuildCanceled
 	case string(models.AppRevisionStatus_BuildFailed):
@@ -233,8 +233,8 @@ func appRevisionStatusFromProto(status string) (models.AppRevisionStatus, error)
 		appRevisionStatus = models.AppRevisionStatus_PredeploySuccessful
 	case string(models.AppRevisionStatus_PredeployProgressing):
 		appRevisionStatus = models.AppRevisionStatus_PredeployProgressing
-	case string(models.AppRevisionStatus_DeployFailed):
-		appRevisionStatus = models.AppRevisionStatus_DeployFailed
+	case string(models.AppRevisionStatus_InstallFailed):
+		appRevisionStatus = models.AppRevisionStatus_InstallFailed
 	case string(models.AppRevisionStatus_Created):
 		appRevisionStatus = models.AppRevisionStatus_Created
 	case string(models.AppRevisionStatus_BuildSuccessful):
@@ -243,7 +243,12 @@ func appRevisionStatusFromProto(status string) (models.AppRevisionStatus, error)
 		appRevisionStatus = models.AppRevisionStatus_ApplyFailed
 	case string(models.AppRevisionStatus_UpdateFailed):
 		appRevisionStatus = models.AppRevisionStatus_UpdateFailed
-
+	case string(models.AppRevisionStatus_DeploymentProgressing):
+		appRevisionStatus = models.AppRevisionStatus_DeploymentProgressing
+	case string(models.AppRevisionStatus_DeploymentSuccessful):
+		appRevisionStatus = models.AppRevisionStatus_DeploymentSuccessful
+	case string(models.AppRevisionStatus_DeploymentFailed):
+		appRevisionStatus = models.AppRevisionStatus_DeploymentFailed
 	default:
 		return appRevisionStatus, errors.New("unknown app revision status")
 	}