ソースを参照

Revert "Image Settings for Porter Apps V1 (#3731)" (#3734)

ianedwards 2 年 前
コミット
25e1e5045b

+ 41 - 43
dashboard/src/main/home/app-dashboard/app-view/tabs/ImageSettingsTab.tsx

@@ -5,19 +5,18 @@ import { useLatestRevision } from "../LatestRevisionContext";
 import Spacer from "components/porter/Spacer";
 import Button from "components/porter/Button";
 import Error from "components/porter/Error";
+import { match } from "ts-pattern";
 import styled from "styled-components";
 import copy from "assets/copy-left.svg"
 import CopyToClipboard from "components/CopyToClipboard";
 import Link from "components/porter/Link";
 import Text from "components/porter/Text";
 import ImageSettings from "../../image-settings/ImageSettings";
-import { match } from "ts-pattern";
 
 const ImageSettingsTab: React.FC = () => {
     const {
         watch,
         formState: { isSubmitting, errors },
-        setValue,
     } = useFormContext<PorterAppFormData>();
     const { projectId, latestRevision, latestProto } = useLatestRevision();
 
@@ -35,47 +34,46 @@ const ImageSettingsTab: React.FC = () => {
         return "";
     }, [isSubmitting, errors]);
 
-    return match(source)
-        .with({ type: "docker-registry" }, (source) => (
-            <>
-                <ImageSettings
-                    projectId={projectId}
-                    imageUri={source.image?.repository ?? ""}
-                    setImageUri={(uri: string) => setValue("source.image", { ...(source?.image ?? {}), repository: uri })}
-                    imageTag={source.image?.tag ?? ""}
-                    setImageTag={(tag: string) => setValue("source.image", { ...(source?.image ?? {}), tag })}
-                    resetImageInfo={() => setValue("source.image", { repository: "", tag: "" })}
-                />
-                <Spacer y={1} />
-                <Button
-                    type="submit"
-                    status={buttonStatus}
-                    disabled={
-                        isSubmitting
-                        || latestRevision.status === "CREATED"
-                        || latestRevision.status === "AWAITING_BUILD_ARTIFACT"
-                        || !source.image?.repository
-                        || !source.image?.tag
-                    }
-                >
-                    Save image settings
-                </Button>
-                <Spacer y={1} />
-                <Text size={16}>Update command</Text>
-                <Spacer y={0.5} />
-                <Text color="helper">If you have the <Link to="https://docs.porter.run/standard/cli/command-reference/porter-update" target="_blank"><Text>Porter CLI</Text></Link> installed, you can update your application image tag by running the following command: </Text>
-                <Spacer y={0.5} />
-                <IdContainer>
-                    <Code>{`$ porter app update-tag ${latestProto.name} --tag latest`}</Code>
-                    <CopyContainer>
-                        <CopyToClipboard text={`porter app update-tag ${latestProto.name} --tag latest`}>
-                            <CopyIcon src={copy} alt="copy" />
-                        </CopyToClipboard>
-                    </CopyContainer>
-                </IdContainer>
-            </>
-        ))
-        .otherwise(() => null);
+    return (
+        <>
+            {match(source)
+                .with({ type: "docker-registry" }, (source) => (
+                    <>
+                        <ImageSettings
+                            projectId={projectId}
+                            source={source}
+                        />
+                        <Spacer y={1} />
+                        <Button
+                            type="submit"
+                            status={buttonStatus}
+                            disabled={
+                                isSubmitting ||
+                                latestRevision.status === "CREATED" ||
+                                latestRevision.status === "AWAITING_BUILD_ARTIFACT"
+                            }
+                        >
+                            Save image settings
+                        </Button>
+                        <Spacer y={1} />
+                        <Text size={16}>Update command</Text>
+                        <Spacer y={0.5} />
+                        <Text color="helper">If you have the <Link to="https://docs.porter.run/standard/cli/command-reference/porter-update" target="_blank"><Text>Porter CLI</Text></Link> installed, you can update your application image tag by running the following command: </Text>
+                        <Spacer y={0.5} />
+                        <IdContainer>
+                            <Code>{`$ porter app update-tag ${latestProto.name} --tag latest`}</Code>
+                            <CopyContainer>
+                                <CopyToClipboard text={`porter app update-tag ${latestProto.name} --tag latest`}>
+                                    <CopyIcon src={copy} alt="copy" />
+                                </CopyToClipboard>
+                            </CopyContainer>
+                        </IdContainer>
+                    </>
+                ))
+                .otherwise(() => null)
+            }
+        </>
+    );
 };
 
 export default ImageSettingsTab;

+ 1 - 8
dashboard/src/main/home/app-dashboard/create-app/CreateApp.tsx

@@ -582,14 +582,7 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {
                               )} */}
                           </>
                         ) : (
-                          <ImageSettings
-                            projectId={currentProject.id}
-                            imageUri={image?.repository ?? ""}
-                            setImageUri={(uri: string) => setValue("source.image", { ...image, repository: uri })}
-                            imageTag={image?.tag ?? ""}
-                            setImageTag={(tag: string) => setValue("source.image", { ...image, tag })}
-                            resetImageInfo={() => setValue("source.image", { ...image, repository: "", tag: "" })}
-                          />
+                          <ImageSettings projectId={currentProject.id} source={source} />
                         )
                       ) : null}
                     </AnimateHeight>

+ 7 - 27
dashboard/src/main/home/app-dashboard/expanded-app/ExpandedApp.tsx

@@ -49,7 +49,6 @@ import EventFocusView from "./activity-feed/events/focus-views/EventFocusView";
 import HelmValuesTab from "./HelmValuesTab";
 import SettingsTab from "./SettingsTab";
 import PorterAppRevisionSection from "./PorterAppRevisionSection";
-import ImageSettingsTab from "./ImageSettingsTab";
 
 type Props = RouteComponentProps & {};
 
@@ -70,7 +69,6 @@ const validTabs = [
   "debug",
   "environment",
   "build-settings",
-  "image-settings",
   "settings",
   "helm-values",
   "job-history",
@@ -232,17 +230,8 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
       setSyncedEnvGroups(filteredEnvGroups || []);
       setPorterJson(porterJson);
       setAppData(newAppData);
-      const globalImage = resChartData.data.config?.global?.image
-      const hasBuiltImage = globalImage != null &&
-        globalImage.repository != null &&
-        globalImage.tag != null &&
-        !(globalImage.repository === ImageInfo.BASE_IMAGE.repository &&
-          globalImage.tag === ImageInfo.BASE_IMAGE.tag)
       // annoying that we have to parse buildpacks like this but alas
       const parsedPorterApp = { ...resPorterApp?.data, buildpacks: newAppData.app.buildpacks?.split(",") ?? [] };
-      if (parsedPorterApp.image_repo_uri && hasBuiltImage) {
-        parsedPorterApp.image_info = { repository: globalImage.repository, tag: globalImage.tag };
-      }
       setPorterApp(parsedPorterApp);
       setTempPorterApp(parsedPorterApp);
       setBuildView(!_.isEmpty(parsedPorterApp.dockerfile) ? "docker" : "buildpacks")
@@ -260,6 +249,12 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
       );
       setPorterYaml(finalPorterYaml);
       // Only check GHA status if no built image is set
+      const globalImage = resChartData.data.config?.global?.image
+      const hasBuiltImage = globalImage != null &&
+        globalImage.repository != null &&
+        globalImage.tag != null &&
+        globalImage.repository !== ImageInfo.BASE_IMAGE.repository &&
+        globalImage.tag !== ImageInfo.BASE_IMAGE.tag
       if (hasBuiltImage || !resPorterApp.data.repo_name) {
         setWorkflowCheckPassed(true);
         setHasBuiltImage(true);
@@ -407,7 +402,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
         );
         const yamlString = yaml.dump(finalPorterYaml);
         const base64Encoded = btoa(yamlString);
-        let updatedPorterApp = {
+        const updatedPorterApp = {
           porter_yaml: base64Encoded,
           override_release: true,
           ...PorterApp.empty(),
@@ -428,9 +423,6 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
           updatedPorterApp.buildpacks = tempPorterApp.buildpacks.join(",");
           updatedPorterApp.dockerfile = "null";
         }
-        if (tempPorterApp.image_info?.repository && tempPorterApp.image_info?.tag) {
-          updatedPorterApp = { ...updatedPorterApp, image_info: tempPorterApp.image_info, image_repo_uri: tempPorterApp.image_info.repository }
-        }
 
         await api.createPorterApp(
           "<token>",
@@ -686,14 +678,6 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
             setBuildView={setBuildView}
           />
         );
-      case "image-settings":
-        return (
-          <ImageSettingsTab
-            porterApp={tempPorterApp}
-            setTempPorterApp={(attrs: Partial<PorterApp>) => setTempPorterApp(PorterApp.setAttributes(tempPorterApp, attrs))}
-            updatePorterApp={updatePorterApp}
-          />
-        )
       case "settings":
         return <SettingsTab
           appName={appData.app.name}
@@ -951,10 +935,6 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
                     label: "Build settings",
                     value: "build-settings",
                   },
-                  hasBuiltImage && !appData.app.git_repo_id && {
-                    label: "Image settings",
-                    value: "image-settings",
-                  },
                   { label: "Settings", value: "settings" },
                   (user.email.endsWith("porter.run") || currentProject.helm_values_enabled) && { label: "Helm values", value: "helm-values" },
                 ].filter((x) => x)}

+ 0 - 119
dashboard/src/main/home/app-dashboard/expanded-app/ImageSettingsTab.tsx

@@ -1,119 +0,0 @@
-import React, { useContext, useState } from "react";
-import Spacer from "components/porter/Spacer";
-import Button from "components/porter/Button";
-import Error from "components/porter/Error";
-import styled from "styled-components";
-import copy from "assets/copy-left.svg"
-import CopyToClipboard from "components/CopyToClipboard";
-import Link from "components/porter/Link";
-import Text from "components/porter/Text";
-import ImageSettings from "../image-settings/ImageSettings";
-import { Context } from "shared/Context";
-import { CreateUpdatePorterAppOptions } from "shared/types";
-import { PorterApp } from "../types/porterApp";
-
-type Props = {
-    porterApp: PorterApp;
-    updatePorterApp: (options: Partial<CreateUpdatePorterAppOptions>) => Promise<void>;
-    setTempPorterApp: (app: PorterApp) => void;
-}
-const ImageSettingsTab: React.FC<Props> = ({
-    porterApp,
-    updatePorterApp,
-    setTempPorterApp,
-}) => {
-    const { currentProject } = useContext(Context);
-
-    const [buttonStatus, setButtonStatus] = useState<
-        "loading" | "success" | string
-    >("");
-
-    const saveConfig = async () => {
-        try {
-            await updatePorterApp({});
-        } catch (err) {
-            console.log(err);
-        }
-    };
-
-    const handleSave = async () => {
-        setButtonStatus("loading");
-
-        try {
-            await saveConfig();
-            setButtonStatus("success");
-        } catch (error) {
-            setButtonStatus("Something went wrong");
-            console.log(error);
-        }
-    };
-
-    return (
-        <>
-            <ImageSettings
-                projectId={currentProject?.id ?? 0}
-                imageUri={porterApp.image_info?.repository ?? ""}
-                setImageUri={(uri: string) => setTempPorterApp({ ...porterApp, image_info: { ...porterApp.image_info, repository: uri } })}
-                imageTag={porterApp.image_info?.tag ?? ""}
-                setImageTag={(tag: string) => setTempPorterApp({ ...porterApp, image_info: { ...porterApp.image_info, tag: tag } })}
-                resetImageInfo={() => setTempPorterApp({ ...porterApp, image_info: { ...porterApp.image_info, repository: "", tag: "" } })}
-            />
-            <Spacer y={1} />
-            <Button
-                type="button"
-                status={buttonStatus}
-                disabled={!porterApp.image_info?.repository || !porterApp.image_info?.tag}
-                onClick={handleSave}
-            >
-                Save image settings
-            </Button>
-            <Spacer y={1} />
-            <Text size={16}>Update command</Text>
-            <Spacer y={0.5} />
-            <Text color="helper">If you have the <Link to="https://docs.porter.run/standard/cli/command-reference/porter-update" target="_blank"><Text>Porter CLI</Text></Link> installed, you can update your application image tag by running the following command: </Text>
-            <Spacer y={0.5} />
-            <IdContainer>
-                <Code>{`$ porter app update-tag ${porterApp.name} --tag latest`}</Code>
-                <CopyContainer>
-                    <CopyToClipboard text={`porter app update-tag ${porterApp.name} --tag latest`}>
-                        <CopyIcon src={copy} alt="copy" />
-                    </CopyToClipboard>
-                </CopyContainer>
-            </IdContainer>
-        </>
-    );
-};
-
-export default ImageSettingsTab;
-
-const Code = styled.span`
-  font-family: monospace;
-`;
-
-const IdContainer = styled.div`
-    background: #000000;  
-    border-radius: 5px;
-    padding: 10px;
-    display: flex;
-    width: 100%;
-    border-radius: 5px;
-    border: 1px solid ${({ theme }) => theme.border};
-    align-items: center;
-`;
-
-const CopyContainer = styled.div`
-  display: flex;
-  align-items: center;
-  margin-left: auto;
-`;
-
-const CopyIcon = styled.img`
-  cursor: pointer;
-  margin-left: 5px;
-  margin-right: 5px;
-  width: 15px;
-  height: 15px;
-  :hover {
-    opacity: 0.8;
-  }
-`;

+ 65 - 47
dashboard/src/main/home/app-dashboard/image-settings/ImageSettings.tsx

@@ -1,32 +1,27 @@
 import React, { useEffect, useState } from "react";
 import { useQuery } from "@tanstack/react-query";
 import api from "shared/api";
+import { Controller, useFormContext } from "react-hook-form";
 import Text from "components/porter/Text";
 import Spacer from "components/porter/Spacer";
 import styled from "styled-components";
 import Input from "components/porter/Input";
 import { z } from "zod";
+import { PorterAppFormData, SourceOptions } from "lib/porter-apps";
 import ImageList from "./ImageList";
 import TagList from "./TagList";
 import { ImageType } from "./types";
 
 type Props = {
     projectId: number;
-    imageUri: string;
-    imageTag: string;
-    setImageUri: (uri: string) => void;
-    setImageTag: (tag: string) => void;
-    resetImageInfo: () => void;
+    source: SourceOptions & { type: "docker-registry" };
 };
 
 const ImageSettings: React.FC<Props> = ({
     projectId,
-    imageUri,
-    imageTag,
-    setImageUri,
-    setImageTag,
-    resetImageInfo,
+    source,
 }) => {
+    const { control, setValue } = useFormContext<PorterAppFormData>();
     const [images, setImages] = useState<ImageType[]>([]);
     const [selectedImage, setSelectedImage] = useState<ImageType | undefined>(undefined);
     const { data: registries, isLoading: isLoadingRegistries } = useQuery(
@@ -41,7 +36,7 @@ const ImageSettings: React.FC<Props> = ({
     )
 
     const { data: imageResp, isLoading: isLoadingImages } = useQuery(
-        ["getImages", projectId, imageTag, imageUri],
+        ["getImages", projectId, source],
         async () => {
             if (registries == null) {
                 return [];
@@ -67,8 +62,8 @@ const ImageSettings: React.FC<Props> = ({
     useEffect(() => {
         if (imageResp) {
             setImages(imageResp);
-            if (imageUri) {
-                setSelectedImage(imageResp.find((image) => image.uri === imageUri));
+            if (source.image && source.image.repository) {
+                setSelectedImage(imageResp.find((image) => image.uri === source.image.repository));
             }
         }
     }, [imageResp]);
@@ -80,36 +75,49 @@ const ImageSettings: React.FC<Props> = ({
             <Text color="helper">Specify your image URL.</Text>
             <Spacer y={0.5} />
 
-            {!imageUri && (
-                <>
-                    <ExpandedWrapper>
-                        <ImageList
-                            setSelectedImage={(image: ImageType) => {
-                                setSelectedImage(image);
-                                setImageUri(image.uri);
-                            }}
-                            images={images}
-                            loading={isLoadingImages || isLoadingRegistries}
-                        />
-                    </ExpandedWrapper>
-                    <DarkMatter antiHeight="-4px" />
-                    <Spacer y={0.3} />
-                </>
+            {(!source.image || !source.image.repository) && (
+                <Controller
+                    name="source.image"
+                    control={control}
+                    render={({ field: { onChange } }) => (
+                        <>
+                            <ExpandedWrapper>
+                                <ImageList
+                                    setSelectedImage={(image: ImageType) => {
+                                        setSelectedImage(image);
+                                        onChange({
+                                            repository: image.uri,
+                                        });
+                                    }}
+                                    images={images}
+                                    loading={isLoadingImages || isLoadingRegistries}
+                                />
+                            </ExpandedWrapper>
+                            <DarkMatter antiHeight="-4px" />
+                            <Spacer y={0.3} />
+                        </>
+                    )}
+                />
             )}
 
-            {imageUri && (
+            {source.image && source.image.repository && (
                 <>
                     <Input
                         disabled={true}
                         label="Image URL:"
                         width="100%"
-                        value={selectedImage?.uri ?? imageUri}
+                        value={selectedImage?.uri ?? source.image.repository}
                         setValue={() => { }}
                         placeholder=""
                     />
                     <BackButton
                         width="170px"
-                        onClick={resetImageInfo}
+                        onClick={() => {
+                            setValue("source.image", {
+                                repository: "",
+                                tag: "",
+                            });
+                        }}
                     >
                         <i className="material-icons">keyboard_backspace</i>
                         Select image URL
@@ -117,36 +125,46 @@ const ImageSettings: React.FC<Props> = ({
                     <Spacer y={1} />
                     <Text color="helper">Specify your image tag.</Text>
                     <Spacer y={0.5} />
-                    {!imageTag && (
-                        <>
-                            <ExpandedWrapper>
-                                <TagList
-                                    selectedImage={selectedImage}
-                                    projectId={projectId}
-                                    setSelectedTag={
-                                        (tag: string) => {
-                                            setImageTag(tag);
+                    {!source.image.tag && (
+                        <Controller
+                            name="source.image"
+                            control={control}
+                            render={({ field: { onChange } }) => (
+                                <ExpandedWrapper>
+                                    <TagList
+                                        selectedImage={selectedImage}
+                                        projectId={projectId}
+                                        setSelectedTag={
+                                            (tag: string) => {
+                                                onChange({
+                                                    repository: source.image.repository,
+                                                    tag,
+                                                });
+                                            }
                                         }
-                                    }
-                                />
-                            </ExpandedWrapper>
-                        </>
+                                    />
+                                </ExpandedWrapper>
+                            )}
+                        />
                     )}
-                    {imageTag && (
+                    {source.image.tag && (
                         <>
                             <Input
                                 disabled={true}
                                 label="Image tag:"
                                 type="text"
                                 width="100%"
-                                value={imageTag}
+                                value={source.image.tag}
                                 setValue={() => { }}
                                 placeholder=""
                             />
                             <BackButton
                                 width="170px"
                                 onClick={() => {
-                                    setImageTag("")
+                                    setValue("source.image", {
+                                        repository: source.image.repository,
+                                        tag: "",
+                                    });
                                 }}
                             >
                                 <i className="material-icons">keyboard_backspace</i>

+ 1 - 6
dashboard/src/main/home/app-dashboard/new-app-flow/NewAppFlow.tsx

@@ -77,7 +77,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
   const [porterApp, setPorterApp] = useState<PorterApp>(PorterApp.empty());
   const [hovered, setHovered] = useState(false);
 
-  const [imageTag, setImageTag] = useState("");
+  const [imageTag, setImageTag] = useState("latest");
   const { currentCluster, currentProject } = useContext(Context);
   const [deploying, setDeploying] = useState<boolean>(false);
   const [deploymentError, setDeploymentError] = useState<string | undefined>(undefined);
@@ -470,11 +470,6 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
                   setImageTag={setImageTag}
                   buildView={buildView}
                   setBuildView={setBuildView}
-                  projectId={currentProject?.id ?? 0}
-                  resetImageInfo={() => {
-                    setPorterApp(PorterApp.setAttribute(porterApp, "image_repo_uri", ""));
-                    setImageTag("");
-                  }}
                 />
               </>,
               <>

+ 30 - 14
dashboard/src/main/home/app-dashboard/new-app-flow/SourceSettings.tsx

@@ -4,9 +4,11 @@ import Spacer from "components/porter/Spacer";
 import styled from "styled-components";
 import { SourceType } from "./SourceSelector";
 import { RouteComponentProps, withRouter } from "react-router";
+import { pushFiltered } from "shared/routing";
+import ImageSelector from "components/image-selector/ImageSelector";
 import SharedBuildSettings from "../build-settings/SharedBuildSettings";
+import Link from "components/porter/Link";
 import { BuildMethod, PorterApp } from "../types/porterApp";
-import ImageSettings from "../image-settings/ImageSettings";
 
 type Props = RouteComponentProps & {
   source: SourceType | undefined;
@@ -19,8 +21,6 @@ type Props = RouteComponentProps & {
   setPorterApp: (x: PorterApp) => void;
   buildView: BuildMethod;
   setBuildView: (buildView: BuildMethod) => void;
-  projectId: number;
-  resetImageInfo: () => void;
 };
 
 const SourceSettings: React.FC<Props> = ({
@@ -34,8 +34,8 @@ const SourceSettings: React.FC<Props> = ({
   setPorterApp,
   buildView,
   setBuildView,
-  projectId,
-  resetImageInfo,
+  location,
+  history,
 }) => {
   return (
     <SourceSettingsContainer>
@@ -51,15 +51,31 @@ const SourceSettings: React.FC<Props> = ({
             buildView={buildView}
             setBuildView={setBuildView}
           />
-        ) :
-          <ImageSettings
-            projectId={projectId}
-            imageTag={imageTag}
-            setImageTag={setImageTag}
-            imageUri={imageUrl}
-            setImageUri={setImageUrl}
-            resetImageInfo={resetImageInfo}
-          />
+        ) : (
+          <StyledSourceBox>
+            <Subtitle>
+              Specify the container image you would like to connect to this
+              template.
+              <Spacer inline width="5px" />
+              <Link
+                hasunderline
+                onClick={() =>
+                  pushFiltered({ location, history }, "/integrations/registry", ["project_id"])
+                }
+              >
+                Manage Docker registries
+              </Link>
+            </Subtitle>
+            <DarkMatter antiHeight="-4px" />
+            <ImageSelector
+              selectedTag={imageTag}
+              selectedImageUrl={imageUrl}
+              setSelectedImageUrl={setImageUrl}
+              setSelectedTag={setImageTag}
+              forceExpanded={true}
+            />
+            <br />
+          </StyledSourceBox>)
         }
       </AnimateHeight>
     </SourceSettingsContainer>

+ 0 - 8
dashboard/src/main/home/app-dashboard/types/porterApp.ts

@@ -9,10 +9,6 @@ export interface PorterApp {
     dockerfile: string;
     image_repo_uri: string;
     porter_yaml_path: string;
-    image_info?: {
-        repository: string;
-        tag: string;
-    }
 }
 
 export const PorterApp = {
@@ -27,10 +23,6 @@ export const PorterApp = {
         dockerfile: "",
         image_repo_uri: "",
         porter_yaml_path: "",
-        image_info: {
-            repository: "",
-            tag: "",
-        }
     }),
 
     setAttribute: <K extends keyof PorterApp>(