Pārlūkot izejas kodu

Modal now shows up if porter.yaml is not found in create flow (#3544)

Feroze Mohideen 2 gadi atpakaļ
vecāks
revīzija
386f9a086b

+ 28 - 12
dashboard/src/lib/hooks/usePorterYaml.ts

@@ -9,13 +9,15 @@ import { z } from "zod";
 
 type PorterYamlStatus =
   | {
-      loading: true;
-      detectedServices: null;
-    }
+    loading: true;
+    detectedServices: null;
+    porterYamlFound: boolean;
+  }
   | {
-      detectedServices: DetectedServices | null;
-      loading: false;
-    };
+    detectedServices: DetectedServices | null;
+    loading: false;
+    porterYamlFound: boolean;
+  };
 
 /*
  *
@@ -28,7 +30,7 @@ export const usePorterYaml = ({
   source,
   useDefaults = true,
 }: {
-  source: SourceOptions | null;
+  source: SourceOptions & { type: "github" } | null;
   useDefaults?: boolean;
 }): PorterYamlStatus => {
   const { currentProject, currentCluster } = useContext(Context);
@@ -36,6 +38,7 @@ export const usePorterYaml = ({
     detectedServices,
     setDetectedServices,
   ] = useState<DetectedServices | null>(null);
+  const [porterYamlFound, setPorterYamlFound] = useState(false);
 
   const { data, status } = useQuery(
     [
@@ -43,14 +46,16 @@ export const usePorterYaml = ({
       currentProject?.id,
       source?.git_branch,
       source?.git_repo_name,
+      source?.porter_yaml_path,
     ],
     async () => {
-      if (!currentProject) {
-        return;
-      }
-      if (source?.type !== "github") {
+      setPorterYamlFound(false);
+
+      if (!currentProject || !source) {
         return;
       }
+
+
       const res = await api.getPorterYamlContents(
         "<token>",
         {
@@ -66,6 +71,7 @@ export const usePorterYaml = ({
         }
       );
 
+      setPorterYamlFound(true);
       return z.string().parseAsync(res.data);
     },
     {
@@ -73,7 +79,14 @@ export const usePorterYaml = ({
         source?.type === "github" &&
         Boolean(source.git_repo_name) &&
         Boolean(source.git_branch),
-      retry: false,
+      retry: (_failureCount, error) => {
+        if (error.response.data?.error?.includes("404")) {
+          setPorterYamlFound(false);
+          return false;
+        }
+        return true;
+      },
+      refetchOnWindowFocus: false,
     }
   );
 
@@ -144,6 +157,7 @@ export const usePorterYaml = ({
     return {
       loading: false,
       detectedServices: null,
+      porterYamlFound: false,
     };
   }
 
@@ -151,11 +165,13 @@ export const usePorterYaml = ({
     return {
       loading: true,
       detectedServices: null,
+      porterYamlFound: true,
     };
   }
 
   return {
     detectedServices,
     loading: false,
+    porterYamlFound,
   };
 };

+ 1 - 1
dashboard/src/main/home/app-dashboard/app-view/LatestRevisionContext.tsx

@@ -144,7 +144,7 @@ export const LatestRevisionProvider = ({
   }, [porterApp]);
 
   const { loading: porterYamlLoading, detectedServices } = usePorterYaml({
-    source: latestSource,
+    source: latestSource?.type === "github" ? latestSource : null,
     useDefaults: false,
   });
 

+ 25 - 6
dashboard/src/main/home/app-dashboard/create-app/CreateApp.tsx

@@ -43,6 +43,7 @@ import { useAppAnalytics } from "lib/hooks/useAppAnalytics";
 import { useAppValidation } from "lib/hooks/useAppValidation";
 import { useQuery } from "@tanstack/react-query";
 import { z } from "zod";
+import PorterYamlModal from "./PorterYamlModal";
 
 type CreateAppProps = {} & RouteComponentProps;
 
@@ -54,6 +55,7 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {
     count: number;
   }>({ detected: false, count: 0 });
   const [showGHAModal, setShowGHAModal] = React.useState(false);
+  const [userHasSeenNoPorterYamlFoundModal, setUserHasSeenNoPorterYamlFoundModal] = React.useState(false);
 
   const [
     validatedAppProto,
@@ -130,7 +132,7 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {
   const build = watch("app.build");
   const image = watch("source.image");
   const services = watch("app.services");
-  const { detectedServices: servicesFromYaml } = usePorterYaml({ source });
+  const { detectedServices: servicesFromYaml, porterYamlFound } = usePorterYaml({ source: source?.type === "github" ? source : null });
   const deploymentTarget = useDefaultDeploymentTarget();
   const { updateAppStep } = useAppAnalytics(name);
   const { validateApp } = useAppValidation({
@@ -421,11 +423,28 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {
                       <Spacer y={1} />
                       {source?.type ? (
                         source.type === "github" ? (
-                          <RepoSettings
-                            build={build}
-                            source={source}
-                            projectId={currentProject.id}
-                          />
+                          <>
+                            <RepoSettings
+                              build={build}
+                              source={source}
+                              projectId={currentProject.id}
+                            />
+                            {!userHasSeenNoPorterYamlFoundModal && !porterYamlFound &&
+                              <Controller
+                                name="source.porter_yaml_path"
+                                control={control}
+                                render={({ field: { onChange, value } }) => (
+                                  <PorterYamlModal
+                                    close={() => setUserHasSeenNoPorterYamlFoundModal(true)}
+                                    setPorterYamlPath={(porterYamlPath) => {
+                                      onChange(porterYamlPath);
+                                    }}
+                                    porterYamlPath={value}
+                                  />
+                                )}
+                              />
+                            }
+                          </>
                         ) : (
                           <ImageSettings />
                         )

+ 82 - 0
dashboard/src/main/home/app-dashboard/create-app/PorterYamlModal.tsx

@@ -0,0 +1,82 @@
+import React, { useState } from "react";
+import styled from "styled-components";
+
+import Link from "components/porter/Link";
+import Spacer from "components/porter/Spacer";
+import Modal from "components/porter/Modal";
+import Text from "components/porter/Text";
+import Input from "components/porter/Input";
+import Button from "components/porter/Button";
+
+type Props = {
+    close: () => void;
+    setPorterYamlPath: (path: string) => void;
+    porterYamlPath: string;
+}
+
+const PorterYamlModal: React.FC<Props> = ({ close, setPorterYamlPath, porterYamlPath }) => {
+    const [possiblePorterYamlPath, setPossiblePorterYamlPath] = useState<string>("");
+    const [showModal, setShowModal] = useState<boolean>(true);
+
+    return showModal ? (
+        <Modal closeModal={() => setShowModal(false)}>
+            <div>
+                <Text size={16}>No <Code>porter.yaml</Code> detected at <Code>{porterYamlPath}</Code></Text>
+                <Spacer y={0.5} />
+                <span>
+                    <Text color="helper">
+                        We were unable to find a <Code>porter.yaml</Code> file in your repository.
+                    </Text>
+                    <Spacer y={0.5} />
+                    <Text color="helper">
+                        Although not required, we
+                        recommend that you add a <Code>porter.yaml</Code> file to the root of your repository,
+                        or you may specify its path here.
+                    </Text>
+                    <Spacer y={0.5} />
+                    <Link
+                        to="https://docs.porter.run/standard/deploying-applications/writing-porter-yaml"
+                        target="_blank"
+                        hasunderline
+                    >
+                        Using porter.yaml
+                    </Link>
+                </span>
+            </div>
+            <Spacer y={0.5} />
+            <Text color="helper">Path to <Code>porter.yaml</Code> from repository root (i.e. starting with ./):</Text>
+            <Spacer y={0.5} />
+            <Input
+                disabled={false}
+                placeholder="ex: ./subdirectory/porter.yaml"
+                value={possiblePorterYamlPath}
+                width="100%"
+                setValue={setPossiblePorterYamlPath}
+            />
+            <Spacer y={1} />
+            <div style={{ display: "flex", justifyContent: "space-between" }}>
+                <Button
+                    onClick={close}
+                    color="#ffffff11"
+                >
+                    Ignore
+                </Button>
+                <Button
+                    onClick={() => {
+                        setPorterYamlPath(possiblePorterYamlPath);
+                        setShowModal(false);
+                    }}
+                    color="#616fee"
+                >
+                    Update path
+                </Button>
+            </div>
+        </Modal>
+    ) : null;
+};
+
+export default PorterYamlModal;
+
+const Code = styled.span`
+  font-family: monospace;
+`;