Просмотр исходного кода

Merge pull request #1931 from porter-dev/nico/implement-rerun-workflow-on-preview-envs

[Improvement] Implement re run workflow behaviour on preview envs
abelanger5 4 лет назад
Родитель
Сommit
e0e2c94afc

+ 77 - 23
dashboard/src/main/home/cluster-dashboard/preview-environments/deployments/DeploymentCard.tsx

@@ -1,8 +1,7 @@
 import React, { useState } from "react";
 import styled, { keyframes } from "styled-components";
-import { PRDeployment } from "../types";
+import { DeploymentStatus, PRDeployment } from "../types";
 import pr_icon from "assets/pull_request_icon.svg";
-import { useRouteMatch } from "react-router";
 import DynamicLink from "components/DynamicLink";
 import { capitalize, readableDate } from "shared/string_utils";
 import api from "shared/api";
@@ -11,12 +10,14 @@ import { Context } from "shared/Context";
 import Loading from "components/Loading";
 import { ActionButton } from "../components/ActionButton";
 import { EllipsisTextWrapper, RepoLink } from "../components/styled";
+import MaterialTooltip from "@material-ui/core/Tooltip";
 
 const DeploymentCard: React.FC<{
   deployment: PRDeployment;
   onDelete: () => void;
   onReEnable: () => void;
-}> = ({ deployment, onDelete, onReEnable }) => {
+  onReRun: () => void;
+}> = ({ deployment, onDelete, onReEnable, onReRun }) => {
   const {
     setCurrentOverlay,
     currentProject,
@@ -27,6 +28,8 @@ const DeploymentCard: React.FC<{
   const [isLoading, setIsLoading] = useState(false);
   const [hasErrorOnReEnabling, setHasErrorOnReEnabling] = useState(false);
   const [showMergeInfoTooltip, setShowMergeInfoTooltip] = useState(false);
+  const [isReRunningWorkflow, setIsReRunningWorkflow] = useState(false);
+  const [hasErrorOnReRun, setHasErrorOnReRun] = useState(false);
 
   const deleteDeployment = () => {
     setIsDeleting(true);
@@ -51,11 +54,10 @@ const DeploymentCard: React.FC<{
       });
   };
 
-  const reEnablePreviewEnvironment = () => {
+  const reEnablePreviewEnvironment = async () => {
     setIsLoading(true);
-
-    api
-      .reenablePreviewEnvironmentDeployment(
+    try {
+      await api.reenablePreviewEnvironmentDeployment(
         "<token>",
         {},
         {
@@ -63,19 +65,42 @@ const DeploymentCard: React.FC<{
           project_id: currentProject.id,
           deployment_id: deployment.id,
         }
-      )
-      .then(() => {
-        setIsLoading(false);
-        onReEnable();
-      })
-      .catch((err) => {
-        setHasErrorOnReEnabling(true);
-        setIsLoading(false);
-        setCurrentError(err?.response?.data?.error || err);
-        setTimeout(() => {
-          setHasErrorOnReEnabling(false);
-        }, 500);
-      });
+      );
+
+      setIsLoading(false);
+      onReEnable();
+    } catch (err) {
+      setHasErrorOnReEnabling(true);
+      setIsLoading(false);
+      setCurrentError(err?.response?.data?.error || err);
+      setTimeout(() => {
+        setHasErrorOnReEnabling(false);
+      }, 500);
+    }
+  };
+
+  const reRunWorkflow = async () => {
+    setIsReRunningWorkflow(true);
+    try {
+      await api.triggerPreviewEnvWorkflow(
+        "<token>",
+        {},
+        {
+          project_id: currentProject.id,
+          cluster_id: currentCluster.id,
+          deployment_id: deployment.id,
+        }
+      );
+      setIsReRunningWorkflow(false);
+      onReEnable();
+    } catch (error) {
+      setHasErrorOnReRun(true);
+      setIsReRunningWorkflow(false);
+      setCurrentError(error);
+      setTimeout(() => {
+        setHasErrorOnReRun(false);
+      }, 500);
+    }
   };
 
   return (
@@ -111,6 +136,12 @@ const DeploymentCard: React.FC<{
             <i className="material-icons">open_in_new</i>
             View PR
           </RepoLink>
+          {deployment.last_workflow_run_url ? (
+            <RepoLink to={deployment.last_workflow_run_url} target="_blank">
+              <i className="material-icons">open_in_new</i>
+              View last workflow
+            </RepoLink>
+          ) : null}
         </PRName>
 
         <Flex>
@@ -133,8 +164,23 @@ const DeploymentCard: React.FC<{
       <Flex>
         {!isDeleting ? (
           <>
-            {deployment.status !== "creating" &&
-              deployment.status !== "inactive" && (
+            {deployment.status === DeploymentStatus.Failed ||
+            deployment.status === DeploymentStatus.TimedOut ? (
+              <>
+                <MaterialTooltip title="Re run last github workflow">
+                  <ReRunButton
+                    onClick={() => reRunWorkflow()}
+                    disabled={isReRunningWorkflow}
+                    hasError={hasErrorOnReRun}
+                  >
+                    <i className="material-icons-outlined">loop</i>
+                  </ReRunButton>
+                </MaterialTooltip>
+              </>
+            ) : null}
+
+            {deployment.status !== DeploymentStatus.Creating &&
+              deployment.status !== DeploymentStatus.Inactive && (
                 <>
                   <RowButton
                     to={`/preview-environments/details/${deployment.namespace}?environment_id=${deployment.environment_id}`}
@@ -153,7 +199,7 @@ const DeploymentCard: React.FC<{
                   </RowButton>
                 </>
               )}
-            {deployment.status === "inactive" ? (
+            {deployment.status === DeploymentStatus.Inactive ? (
               <ActionButton
                 onClick={reEnablePreviewEnvironment}
                 disabled={isLoading}
@@ -198,6 +244,14 @@ const DeploymentCard: React.FC<{
 
 export default DeploymentCard;
 
+const ReRunButton = styled(ActionButton)`
+  min-width: unset;
+
+  > i {
+    margin-right: unset;
+  }
+`;
+
 const SepDot = styled.div`
   color: #aaaabb66;
 `;

+ 1 - 0
dashboard/src/main/home/cluster-dashboard/preview-environments/deployments/DeploymentList.tsx

@@ -219,6 +219,7 @@ const DeploymentList = () => {
               deployment={d}
               onDelete={handleRefresh}
               onReEnable={handleRefresh}
+              onReRun={handleRefresh}
             />
           );
         })}

+ 19 - 7
dashboard/src/main/home/cluster-dashboard/preview-environments/mocks.ts

@@ -1,3 +1,5 @@
+import { PRDeployment } from "./types";
+
 export const environments = [
   {
     id: 29,
@@ -102,54 +104,64 @@ export const environments = [
   },
 ];
 
-export const deployments = [
+export const deployments: PRDeployment[] = [
   {
     gh_deployment_id: 534980099,
-    gh_pr_name: "Update porter.yaml",
+    gh_pr_name: "Update porter.yaml to enable preview environments on porter",
+    gh_pr_branch_from: "some-branch-name",
+    gh_pr_branch_into: "master",
     gh_repo_name: "preview",
     gh_repo_owner: "porter-dev",
     gh_commit_sha: "74a1191",
     id: 43,
     created_at: "2022-03-28T19:28:11.012729Z",
     updated_at: "2022-03-28T19:31:53.871666Z",
-    git_installation_id: 0,
+    gh_installation_id: 0,
     environment_id: 43,
     namespace: "pr-3-preview",
     status: "failed",
     subdomain: "",
     pull_request_id: 3,
+    last_workflow_run_url: "https://something.com",
   },
   {
     gh_deployment_id: 532608734,
     gh_pr_name: "Testing pr preview",
+    gh_pr_branch_from: "some-branch-name",
+    gh_pr_branch_into: "master",
     gh_repo_name: "porter-docs",
     gh_repo_owner: "jnfrati",
     gh_commit_sha: "6a4b67e",
     id: 41,
     created_at: "2022-03-24T20:24:17.103471Z",
     updated_at: "2022-03-24T20:45:06.684096Z",
-    git_installation_id: 0,
+    gh_installation_id: 0,
     environment_id: 37,
     namespace: "pr-1-porter-docs",
     status: "inactive",
-    subdomain: "https://docs-web-7b93751b98e68139.staging-onporter.run",
+    subdomain: "",
     pull_request_id: 1,
+    last_workflow_run_url: "",
   },
   {
     gh_deployment_id: 514002155,
-    gh_pr_name: "Testing PR with job run",
+    gh_pr_name:
+      "Testing PR with job run and a really long name to explain what's going on over this pull request",
+    gh_pr_branch_from: "some-branch-name",
+    gh_pr_branch_into: "master",
     gh_repo_name: "porter-docs",
     gh_repo_owner: "porter-dev",
     gh_commit_sha: "443d930",
     id: 32,
     created_at: "2022-01-30T11:04:14.496147Z",
     updated_at: "2022-02-24T22:02:27.17928Z",
-    git_installation_id: 0,
+    gh_installation_id: 0,
     environment_id: 29,
     namespace: "pr-20-porter-docs",
     status: "created",
     subdomain: "https://docs-web-78a048205ac7869b.staging-onporter.run",
     pull_request_id: 20,
+    last_workflow_run_url: "https://something.com",
   },
 ];
 

+ 16 - 3
dashboard/src/main/home/cluster-dashboard/preview-environments/types.ts

@@ -1,19 +1,32 @@
+export enum DeploymentStatus {
+  Failed = "failed",
+  Created = "created",
+  Creating = "creating",
+  Inactive = "inactive",
+  TimedOut = "timed_out",
+  Updating = "updating",
+}
+
+export type DeploymentStatusUnion = `${DeploymentStatus}`;
+
 export type PRDeployment = {
   id: number;
   created_at: string;
   updated_at: string;
   subdomain: string;
-  status: "creating" | "failed" | "created" | "inactive";
+  status: DeploymentStatusUnion;
   environment_id: number;
   pull_request_id: number;
   namespace: string;
+  last_workflow_run_url: string;
+  gh_installation_id: number;
+  gh_deployment_id: number;
   gh_pr_name: string;
   gh_repo_owner: string;
   gh_repo_name: string;
   gh_commit_sha: string;
   gh_pr_branch_from?: string;
   gh_pr_branch_into?: string;
-  last_workflow_run_url: string;
 };
 
 export type Environment = {
@@ -24,7 +37,7 @@ export type Environment = {
   name: string;
   git_repo_owner: string;
   git_repo_name: string;
-  last_deployment_status: "failed" | "created" | "inactive" | "disabled";
+  last_deployment_status: DeploymentStatusUnion;
   deployment_count: number;
   mode: "manual" | "auto";
 };

+ 27 - 0
dashboard/src/shared/api.tsx

@@ -1699,6 +1699,31 @@ const upgradePorterAgent = baseApi<
     `/api/projects/${project_id}/clusters/${cluster_id}/agent/upgrade`
 );
 
+const reRunGHWorkflow = baseApi<
+  {},
+  {
+    project_id: number;
+    cluster_id: number;
+    git_installation_id: number;
+    owner: string;
+    name: string;
+    filename: string;
+  }
+>(
+  "POST",
+  ({ project_id, git_installation_id, owner, name, cluster_id, filename }) =>
+    `/api/projects/${project_id}/gitrepos/${git_installation_id}/${owner}/${name}/clusters/${cluster_id}/rerun_workflow?filename=${filename}`
+);
+
+const triggerPreviewEnvWorkflow = baseApi<
+  {},
+  { project_id: number; cluster_id: number; deployment_id: number }
+>(
+  "POST",
+  ({ project_id, cluster_id, deployment_id }) =>
+    `/api/projects/${project_id}/clusters/${cluster_id}/deployments/${deployment_id}/trigger_workflow`
+);
+
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
   checkAuth,
@@ -1860,4 +1885,6 @@ export default {
   getIncidentLogsByLogId,
   upgradePorterAgent,
   deletePRDeployment,
+  reRunGHWorkflow,
+  triggerPreviewEnvWorkflow,
 };