Răsfoiți Sursa

Add BuildPacks

Soham Dessai 3 ani în urmă
părinte
comite
eacf2b36a9

+ 32 - 12
dashboard/src/components/repo-selector/ActionConfBranchSelector.tsx

@@ -5,6 +5,8 @@ import { ActionConfigType } from "shared/types";
 
 import RepoList from "./RepoList";
 import BranchList from "./BranchList";
+import ContentsList from "./ContentsList";
+import ActionDetails from "./ActionDetails";
 import InputRow from "../form-components/InputRow";
 
 type Props = {
@@ -12,18 +14,15 @@ type Props = {
   branch: string;
   setActionConfig: (x: ActionConfigType) => void;
   setBranch: (x: string) => void;
+
   setDockerfilePath: (x: string) => void;
+
   setFolderPath: (x: string) => void;
 };
 
-const ActionConfEditorStack: React.FC<Props> = ({
-  actionConfig,
-  setBranch,
-  setActionConfig,
-  branch,
-  setFolderPath,
-  setDockerfilePath,
-}) => {
+const ActionConfEditorStack: React.FC<Props> = (props) => {
+  const { actionConfig, setBranch, setActionConfig, branch } = props;
+
   if (!actionConfig.git_repo) {
     return (
       <ExpandedWrapperAlt>
@@ -35,7 +34,7 @@ const ActionConfEditorStack: React.FC<Props> = ({
       </ExpandedWrapperAlt>
     );
   } else if (!branch) {
-    setFolderPath("./");
+    props.setFolderPath("./");
     return (
       <>
         <ExpandedWrapperAlt>
@@ -55,14 +54,15 @@ const ActionConfEditorStack: React.FC<Props> = ({
         label="Branch"
         type="text"
         width="100%"
-        value={branch}
+        value={props?.branch}
       />
       <BackButton
         width="145px"
         onClick={() => {
-          setFolderPath("");
           setBranch("");
-          setDockerfilePath("");
+          props.setFolderPath("");
+          props.setDockerfilePath("");
+          props.setActionConfig(actionConfig);
         }}
       >
         <i className="material-icons">keyboard_backspace</i>
@@ -79,6 +79,26 @@ const Br = styled.div`
   height: 8px;
 `;
 
+const Flex = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const HeaderButton = styled.div`
+  margin-bottom: 5px;
+  padding: 5px 10px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-weight: 500;
+  margin-right: 10px;
+`;
+
+const RepoHeader = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
 const ExpandedWrapper = styled.div`
   margin-top: 10px;
   width: 100%;

+ 13 - 1
dashboard/src/components/repo-selector/BuildpackStack.tsx

@@ -37,6 +37,7 @@ type DetectedBuildpack = {
   builders: string[];
   detected: Buildpack[];
   others: Buildpack[];
+  buildConfig: BuildConfig;
 };
 
 type DetectBuildpackResponse = DetectedBuildpack[];
@@ -47,7 +48,15 @@ export const BuildpackStack: React.FC<{
   branch: string;
   hide: boolean;
   onChange: (config: BuildConfig) => void;
-}> = ({ actionConfig, folderPath, branch, hide, onChange }) => {
+  defaultBuildConfig: BuildConfig;
+}> = ({
+  actionConfig,
+  folderPath,
+  branch,
+  hide,
+  onChange,
+  defaultBuildConfig,
+}) => {
   const { currentProject } = useContext(Context);
 
   const [builders, setBuilders] = useState<DetectedBuildpack[]>(null);
@@ -106,6 +115,9 @@ export const BuildpackStack: React.FC<{
   };
   useEffect(() => {
     let buildConfig: BuildConfig = {} as BuildConfig;
+    if (defaultBuildConfig) {
+      buildConfig = defaultBuildConfig;
+    }
 
     buildConfig.builder = selectedStack;
     console.log(buildConfig);

+ 4 - 14
dashboard/src/components/repo-selector/DetectContentsList.tsx

@@ -7,7 +7,7 @@ import close from "assets/close.png";
 import Button from "components/porter/Button";
 import api from "../../shared/api";
 import { Context } from "../../shared/Context";
-import { ActionConfigType, FileType } from "../../shared/types";
+import { ActionConfigType, BuildConfig, FileType } from "../../shared/types";
 
 import Loading from "../Loading";
 import Spacer from "components/porter/Spacer";
@@ -26,6 +26,7 @@ type PropsType = {
   dockerfilePath?: string;
   folderPath: string;
   porterYaml?: string;
+  buildConfig: BuildConfig;
   setActionConfig: (x: ActionConfigType) => void;
   setDockerfilePath: (x: string) => void;
   setFolderPath: (x: string) => void;
@@ -105,6 +106,7 @@ const DetectContentsList: React.FC<PropsType> = (props) => {
             dockerfilePath={props.dockerfilePath}
             setDockerfilePath={props.setDockerfilePath}
             setBuildConfig={props.setBuildConfig}
+            buildConfig={props.buildConfig}
             autoBuildPack={autoBuildpack}
             showSettings={false}
             buildView={"docker"}
@@ -203,19 +205,6 @@ const DetectContentsList: React.FC<PropsType> = (props) => {
         }
       );
     }
-
-    return api.detectGitlabBuildpack(
-      "<token>",
-      { dir: currentDir || "." },
-      {
-        project_id: currentProject.id,
-        integration_id: actionConfig.gitlab_integration_id,
-
-        repo_owner: actionConfig.git_repo.split("/")[0],
-        repo_name: actionConfig.git_repo.split("/")[1],
-        branch: branch,
-      }
-    );
   };
 
   const updateContents = async () => {
@@ -268,6 +257,7 @@ const DetectContentsList: React.FC<PropsType> = (props) => {
           actionConfig={props.actionConfig}
           branch={props.branch}
           folderPath={props.folderPath}
+          buildConfig={props.buildConfig}
         />
       ) : (
         <></>

+ 91 - 0
dashboard/src/main/home/app-dashboard/expanded-app/BuildSettingsTabStack.tsx

@@ -0,0 +1,91 @@
+import AnimateHeight from "react-animate-height";
+import React, { Component, Dispatch, useState } from "react";
+import Text from "components/porter/Text";
+import Spacer from "components/porter/Spacer";
+import Input from "components/porter/Input";
+import AdvancedBuildSettings from "../new-app-flow/AdvancedBuildSettings";
+import styled from "styled-components";
+import { SourceType } from "../new-app-flow/SourceSelector";
+import ActionConfEditorStack from "components/repo-selector/ActionConfEditorStack";
+import {
+  ActionConfigType,
+  BuildConfig,
+  GithubActionConfigType,
+} from "shared/types";
+import { RouteComponentProps } from "react-router";
+import { Context } from "shared/Context";
+import ActionConfBranchSelector from "components/repo-selector/ActionConfBranchSelector";
+import DetectContentsList from "components/repo-selector/DetectContentsList";
+import { pushFiltered } from "shared/routing";
+import ImageSelector from "components/image-selector/ImageSelector";
+import SharedBuildSettings from "./SharedBuildSettings";
+import Loading from "components/Loading";
+type Props = {
+  appData: any;
+  setAppData: Dispatch<any>;
+};
+
+const BuildSettingsTabStack: React.FC<Props> = ({ appData, setAppData }) => {
+  const [updated, setUpdated] = useState(null);
+  const [branch, setBranch] = useState(appData.app.git_branch);
+  const defaultActionConfig: GithubActionConfigType = {
+    git_repo: appData.app.repo_name,
+    image_repo_uri: appData.chart.image_uri,
+    git_branch: appData.app.git_branch,
+    git_repo_id: appData.app.repo_id,
+    kind: "github",
+  };
+  const defaultBuildConfig: BuildConfig = {
+    builder: appData.app.builder,
+    buildpacks: appData.app.build_packs?.split(","),
+    config: {},
+  };
+  const [buildConfig, setBuildConfig] = useState<BuildConfig>({
+    ...defaultBuildConfig,
+  });
+  const [actionConfig, setActionConfig] = useState<GithubActionConfigType>({
+    ...defaultActionConfig,
+  });
+
+  return (
+    <SharedBuildSettings
+      actionConfig={actionConfig}
+      branch={branch}
+      dockerfilePath={"./"}
+      folderPath={"./"}
+      setActionConfig={setActionConfig}
+      setDockerfilePath={() => {}}
+      setFolderPath={() => {}}
+      setBuildConfig={setBuildConfig}
+      buildConfig={buildConfig}
+      porterYaml={""}
+      setPorterYaml={() => {}}
+      setBranch={setBranch}
+      imageUrl={""}
+      setImageUrl={() => {}}
+    />
+  );
+};
+
+export default BuildSettingsTabStack;
+
+const SourceSettingsContainer = styled.div``;
+
+const DarkMatter = styled.div<{ antiHeight?: string }>`
+  width: 100%;
+  margin-top: ${(props) => props.antiHeight || "-15px"};
+`;
+
+const Subtitle = styled.div`
+  padding: 11px 0px 16px;
+  font-family: "Work Sans", sans-serif;
+  font-size: 13px;
+  color: #aaaabb;
+  line-height: 1.6em;
+`;
+
+const Required = styled.div`
+  margin-left: 8px;
+  color: #fc4976;
+  display: inline-block;
+`;

+ 5 - 60
dashboard/src/main/home/app-dashboard/expanded-app/ExpandedApp.tsx

@@ -24,6 +24,7 @@ import DeployStatusSection from "main/home/cluster-dashboard/expanded-chart/depl
 import { integrationList } from "shared/common";
 import { ChartType, ResourceType } from "shared/types";
 import RevisionSection from "main/home/cluster-dashboard/expanded-chart/RevisionSection";
+import BuildSettingsTabStack from "./BuildSettingsTabStack";
 
 type Props = RouteComponentProps & {};
 
@@ -90,6 +91,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
       setIsLoading(false);
     }
   };
+
   const renderIcon = (str: string) => {
     let value = str.split(",");
     let buildpack = value[0];
@@ -229,65 +231,6 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
     },
     [appData?.chart]
   );
-
-  // const updateTabs = () => {
-  //   // Collate non-form tabs
-  //   let rightTabOptions = [] as any[];
-  //   let leftTabOptions = [] as any[];
-  //   if (
-  //     appData.chart.chart.metadata.home === "https://getporter.dev/" &&
-  //     (appData.chart.chart.metadata.name === "web" ||
-  //       appData.chart.chart.metadata.name === "worker" ||
-  //       appData.chart.chart.metadata.name === "job") &&
-  //     currentCluster.agent_integration_enabled
-  //   ) {
-  //     leftTabOptions.push({ label: "Events", value: "events" });
-
-  //     if (isAgentInstalled) {
-  //       leftTabOptions.push({ label: "Logs", value: "logs" });
-  //     }
-  //   }
-  //   leftTabOptions.push({ label: "Status", value: "status" });
-  //   leftTabOptions.push({ label: "Metrics", value: "metrics" });
-  //   // if (props.isMetricsInstalled) {
-  //   //   leftTabOptions.push({ label: "Metrics", value: "metrics" });
-  //   // }
-
-  //   rightTabOptions.push({ label: "Chart Overview", value: "graph" });
-
-  //   // if (devOpsMode) {
-  //   //   rightTabOptions.push(
-  //   //     { label: "Manifests", value: "list" },
-  //   //     { label: "Helm Values", value: "values" }
-  //   //   );
-  //   // }
-
-  //   if (appData.chart?.git_action_config?.git_repo) {
-  //     rightTabOptions.push({
-  //       label: "Build Settings",
-  //       value: "build-settings",
-  //     });
-  //   }
-
-  //   // Settings tab is always last
-  //   if (isAuthorized("application", "", ["get", "delete"])) {
-  //     rightTabOptions.push({ label: "Settings", value: "settings" });
-  //   }
-
-  //   // Filter tabs if previewing an old revision or updating the chart version
-  //   if (isPreview) {
-  //     const liveTabs = ["status", "events", "settings", "deploy", "metrics"];
-  //     rightTabOptions = rightTabOptions.filter(
-  //       (tab: any) => !liveTabs.includes(tab.value)
-  //     );
-  //     leftTabOptions = leftTabOptions.filter(
-  //       (tab: any) => !liveTabs.includes(tab.value)
-  //     );
-  //   }
-
-  //   setLeftTabOptions(leftTabOptions);
-  //   setRightTabOptions(rightTabOptions);
-  // };
   useEffect(() => {
     const { appName } = props.match.params as any;
     if (currentCluster && appName && currentProject) {
@@ -309,7 +252,9 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
       case "overview":
         return <div>TODO: service list</div>;
       case "build-settings":
-        return <div>TODO: build settings</div>;
+        return (
+          <BuildSettingsTabStack appData={appData} setAppData={setAppData} />
+        );
       case "settings":
         return <div>TODO: stack deletion</div>;
       default:

+ 144 - 0
dashboard/src/main/home/app-dashboard/expanded-app/SharedBuildSettings.tsx

@@ -0,0 +1,144 @@
+import Input from "components/porter/Input";
+import Spacer from "components/porter/Spacer";
+import Text from "components/porter/Text";
+import ActionConfBranchSelector from "components/repo-selector/ActionConfBranchSelector";
+import ActionConfEditorStack from "components/repo-selector/ActionConfEditorStack";
+import DetectContentsList from "components/repo-selector/DetectContentsList";
+import React, { useEffect, useState } from "react";
+import AnimateHeight from "react-animate-height";
+import { ActionConfigType, BuildConfig } from "shared/types";
+import styled from "styled-components";
+
+type Props = {
+  actionConfig: ActionConfigType;
+  setActionConfig: (
+    x: ActionConfigType | ((prevState: ActionConfigType) => ActionConfigType)
+  ) => void;
+  branch: string;
+  setBranch: (x: string) => void;
+  dockerfilePath: string | null;
+  setDockerfilePath: (x: string) => void;
+  folderPath: string;
+  setFolderPath: (x: string) => void;
+  setBuildConfig: (x: any) => void;
+  buildConfig: BuildConfig;
+  porterYaml: string;
+  setPorterYaml: (x: any) => void;
+  imageUrl: string;
+  setImageUrl: (x: string) => void;
+};
+
+const SharedBuildSettings: React.FC<Props> = ({
+  actionConfig,
+  setActionConfig,
+  buildConfig,
+  branch,
+  setBranch,
+  dockerfilePath,
+  setDockerfilePath,
+  folderPath,
+  setFolderPath,
+  setBuildConfig,
+  porterYaml,
+  setPorterYaml,
+  imageUrl,
+  setImageUrl,
+}) => {
+  const [isExpanded, setIsExpanded] = useState(false);
+
+  return (
+    <>
+      <Text size={16}>Build settings</Text>
+      <Spacer y={0.5} />
+      <Text color="helper">Select your Github repository.</Text>
+      <Spacer y={0.5} />
+      <Subtitle>
+        Provide a repo folder to use as source.
+        <Required>*</Required>
+        <ActionConfEditorStack
+          actionConfig={actionConfig}
+          setActionConfig={(actionConfig: ActionConfigType) => {
+            setActionConfig((currentActionConfig: ActionConfigType) => ({
+              ...currentActionConfig,
+              ...actionConfig,
+            }));
+            setImageUrl(actionConfig.image_repo_uri);
+          }}
+          setBranch={setBranch}
+          setDockerfilePath={setDockerfilePath}
+          setFolderPath={setFolderPath}
+        />
+      </Subtitle>
+      <DarkMatter antiHeight="-4px" />
+      <br />
+      <Spacer y={0.5} />
+      {actionConfig.git_repo && (
+        <>
+          <Text color="helper">Select your branch.</Text>
+          <ActionConfBranchSelector
+            actionConfig={actionConfig}
+            branch={branch}
+            setActionConfig={(actionConfig: ActionConfigType) => {
+              setActionConfig((currentActionConfig: ActionConfigType) => ({
+                ...currentActionConfig,
+                ...actionConfig,
+              }));
+              setImageUrl(actionConfig.image_repo_uri);
+            }}
+            setBranch={setBranch}
+            setDockerfilePath={setDockerfilePath}
+            setFolderPath={setFolderPath}
+          />
+        </>
+      )}
+      <Spacer y={1} />
+      <Text color="helper">Specify your application root path.</Text>
+      <Spacer y={0.5} />
+      <Input
+        disabled={!branch ? true : false}
+        placeholder="ex: ./"
+        value={folderPath}
+        width="100%"
+        setValue={setFolderPath}
+      />
+      {actionConfig.git_repo && branch && buildConfig.builder != "" && (
+        <DetectContentsList
+          actionConfig={actionConfig}
+          branch={branch}
+          dockerfilePath={dockerfilePath}
+          folderPath={folderPath}
+          setActionConfig={setActionConfig}
+          setDockerfilePath={setDockerfilePath}
+          setFolderPath={setFolderPath}
+          buildConfig={buildConfig}
+          setBuildConfig={setBuildConfig}
+          porterYaml={porterYaml}
+          setPorterYaml={setPorterYaml}
+        />
+      )}
+    </>
+  );
+};
+
+export default SharedBuildSettings;
+
+const SourceSettingsContainer = styled.div``;
+
+const DarkMatter = styled.div<{ antiHeight?: string }>`
+  width: 100%;
+  margin-top: ${(props) => props.antiHeight || "-15px"};
+`;
+
+const Subtitle = styled.div`
+  padding: 11px 0px 16px;
+  font-family: "Work Sans", sans-serif;
+  font-size: 13px;
+  color: #aaaabb;
+  line-height: 1.6em;
+`;
+
+const Required = styled.div`
+  margin-left: 8px;
+  color: #fc4976;
+  display: inline-block;
+`;

+ 3 - 1
dashboard/src/main/home/app-dashboard/new-app-flow/AdvancedBuildSettings.tsx

@@ -7,7 +7,7 @@ import Toggle from "components/porter/Toggle";
 import AnimateHeight from "react-animate-height";
 import { DeviconsNameList } from "assets/devicons-name-list";
 import { BuildpackStack } from "components/repo-selector/BuildpackStack";
-import { ActionConfigType } from "shared/types";
+import { ActionConfigType, BuildConfig } from "shared/types";
 import SelectRow from "components/form-components/SelectRow";
 
 interface AutoBuildpack {
@@ -25,6 +25,7 @@ interface AdvancedBuildSettingsProps {
   dockerfilePath?: string;
   setDockerfilePath: (x: string) => void;
   setBuildConfig: (x: any) => void;
+  buildConfig: BuildConfig;
 }
 
 type Buildpack = {
@@ -66,6 +67,7 @@ const AdvancedBuildSettings: React.FC<AdvancedBuildSettingsProps> = (props) => {
         <BuildpackStack
           actionConfig={props.actionConfig}
           branch={props.branch}
+          defaultBuildConfig={props.buildConfig}
           folderPath={props.folderPath}
           onChange={(config) => {
             props.setBuildConfig(config);

+ 45 - 21
dashboard/src/main/home/app-dashboard/new-app-flow/NewAppFlow.tsx

@@ -80,7 +80,7 @@ const Validators: {
 type Detected = {
   detected: boolean;
   message: string;
-}
+};
 
 const NewAppFlow: React.FC<Props> = ({ ...props }) => {
   const [templateName, setTemplateName] = useState("");
@@ -96,11 +96,10 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
     ...defaultActionConfig,
   });
   const [branch, setBranch] = useState("");
-  const [repoType, setRepoType] = useState("");
   const [dockerfilePath, setDockerfilePath] = useState(null);
   const [procfilePath, setProcfilePath] = useState(null);
   const [folderPath, setFolderPath] = useState(null);
-  const [buildConfig, setBuildConfig] = useState();
+  const [buildConfig, setBuildConfig] = useState({});
   const [porterYaml, setPorterYaml] = useState("");
   const [showGHAModal, setShowGHAModal] = useState<boolean>(false);
   const [porterJson, setPorterJson] = useState<
@@ -146,12 +145,23 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
       if (Validators.serviceList(newServiceList)) {
         setCurrentStep(Math.max(currentStep, 4));
       }
-      if (porterYamlToJson &&
+      if (
+        porterYamlToJson &&
         porterYamlToJson.apps &&
-        Object.keys(porterYamlToJson.apps).length > 0) {
-        setDetected({ detected: true, message: `Detected ${Object.keys(porterYamlToJson.apps).length} apps from porter.yaml` });
+        Object.keys(porterYamlToJson.apps).length > 0
+      ) {
+        setDetected({
+          detected: true,
+          message: `Detected ${
+            Object.keys(porterYamlToJson.apps).length
+          } apps from porter.yaml`,
+        });
       } else {
-        setDetected({ detected: false, message: "Could not detect any apps from porter.yaml. Make sure it exists in the root of your repo." });
+        setDetected({
+          detected: false,
+          message:
+            "Could not detect any apps from porter.yaml. Make sure it exists in the root of your repo.",
+        });
       }
     } catch (error) {
       console.log("Error converting porter yaml file to input: " + error);
@@ -186,12 +196,14 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
       const finalPorterYaml = createFinalPorterYaml();
       const yamlString = yaml.dump(finalPorterYaml);
       const base64Encoded = btoa(yamlString);
-      const imageInfo = imageUrl ? {
-        image_info: {
-          repository: imageUrl,
-          tag: imageTag,
-        }
-      } : {}
+      const imageInfo = imageUrl
+        ? {
+            image_info: {
+              repository: imageUrl,
+              tag: imageTag,
+            },
+          }
+        : {};
 
       // only deploy + write to DB if we can create a final porter yaml
       await Promise.all([
@@ -224,7 +236,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
             project_id: currentProject.id,
           }
         ),
-      ])
+      ]);
     } catch (err) {
       console.log(err);
     }
@@ -353,6 +365,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
                   procfilePath={procfilePath}
                   setProcfilePath={setProcfilePath}
                   setBuildConfig={setBuildConfig}
+                  buildConfig={buildConfig}
                   porterYaml={porterYaml}
                   setPorterYaml={(newYaml: string) => {
                     validatePorterYaml(newYaml);
@@ -360,13 +373,24 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
                 />
               </>,
               <>
-                <Text size={16}>Application services {detected && (
-                  <AppearingDiv>
-                    <Text size={16} color={detected.detected ? "green" : "red"}>
-                      {detected.detected ? <i className="material-icons">check</i> : <i className="material-icons">error</i>} {detected.message}
-                    </Text>
-                  </AppearingDiv>
-                )}</Text>
+                <Text size={16}>
+                  Application services{" "}
+                  {detected && (
+                    <AppearingDiv>
+                      <Text
+                        size={16}
+                        color={detected.detected ? "green" : "red"}
+                      >
+                        {detected.detected ? (
+                          <i className="material-icons">check</i>
+                        ) : (
+                          <i className="material-icons">error</i>
+                        )}{" "}
+                        {detected.message}
+                      </Text>
+                    </AppearingDiv>
+                  )}
+                </Text>
                 <Spacer y={0.5} />
 
                 <Services

+ 24 - 78
dashboard/src/main/home/app-dashboard/new-app-flow/SourceSettings.tsx

@@ -7,13 +7,14 @@ import AdvancedBuildSettings from "./AdvancedBuildSettings";
 import styled from "styled-components";
 import { SourceType } from "./SourceSelector";
 import ActionConfEditorStack from "components/repo-selector/ActionConfEditorStack";
-import { ActionConfigType } from "shared/types";
+import { ActionConfigType, BuildConfig } from "shared/types";
 import { RouteComponentProps } from "react-router";
 import { Context } from "shared/Context";
 import ActionConfBranchSelector from "components/repo-selector/ActionConfBranchSelector";
 import DetectContentsList from "components/repo-selector/DetectContentsList";
 import { pushFiltered } from "shared/routing";
 import ImageSelector from "components/image-selector/ImageSelector";
+import SharedBuildSettings from "../expanded-app/SharedBuildSettings";
 type Props = {
   source: SourceType | undefined;
   imageUrl: string;
@@ -32,6 +33,7 @@ type Props = {
   setProcfilePath: (x: string) => void;
   folderPath: string | null;
   setFolderPath: (x: string) => void;
+  buildConfig: BuildConfig;
   setBuildConfig: (x: any) => void;
   porterYaml: string;
   setPorterYaml: (x: any) => void;
@@ -39,6 +41,7 @@ type Props = {
 
 const SourceSettings: React.FC<Props> = ({
   source,
+  buildConfig,
   imageUrl,
   setImageUrl,
   imageTag,
@@ -56,80 +59,6 @@ const SourceSettings: React.FC<Props> = ({
   setPorterYaml,
   ...props
 }) => {
-  const renderGithubSettings = () => {
-    return (
-      <>
-        <Text size={16}>Build settings</Text>
-        <Spacer y={0.5} />
-        <Text color="helper">Select your Github repository.</Text>
-        <Spacer y={0.5} />
-        <Subtitle>
-          Provide a repo folder to use as source.
-          <Required>*</Required>
-          <ActionConfEditorStack
-            actionConfig={actionConfig}
-            setActionConfig={(actionConfig: ActionConfigType) => {
-              setActionConfig((currentActionConfig: ActionConfigType) => ({
-                ...currentActionConfig,
-                ...actionConfig,
-              }));
-              setImageUrl(actionConfig.image_repo_uri);
-            }}
-            setBranch={setBranch}
-            setDockerfilePath={setDockerfilePath}
-            setFolderPath={setFolderPath}
-          />
-        </Subtitle>
-        <DarkMatter antiHeight="-4px" />
-        <br />
-        <Spacer y={0.5} />
-        {actionConfig.git_repo && (
-          <>
-            <Text color="helper">Select your branch.</Text>
-            <ActionConfBranchSelector
-              actionConfig={actionConfig}
-              branch={branch}
-              setActionConfig={(actionConfig: ActionConfigType) => {
-                setActionConfig((currentActionConfig: ActionConfigType) => ({
-                  ...currentActionConfig,
-                  ...actionConfig,
-                }));
-                setImageUrl(actionConfig.image_repo_uri);
-              }}
-              setBranch={setBranch}
-              setDockerfilePath={setDockerfilePath}
-              setFolderPath={setFolderPath}
-            />
-          </>
-        )}
-        <Spacer y={1} />
-        <Text color="helper">Specify your application root path.</Text>
-        <Spacer y={0.5} />
-        <Input
-          disabled={!branch ? true : false}
-          placeholder="ex: ./"
-          value={folderPath}
-          width="100%"
-          setValue={setFolderPath}
-        />
-        {actionConfig.git_repo && branch && (
-          <DetectContentsList
-            actionConfig={actionConfig}
-            branch={branch}
-            dockerfilePath={dockerfilePath}
-            folderPath={folderPath}
-            setActionConfig={setActionConfig}
-            setDockerfilePath={setDockerfilePath}
-            setFolderPath={setFolderPath}
-            setBuildConfig={setBuildConfig}
-            porterYaml={porterYaml}
-            setPorterYaml={setPorterYaml}
-          />
-        )}
-      </>
-    );
-  };
-
   const renderDockerSettings = () => {
     return (
       <>
@@ -187,9 +116,26 @@ const SourceSettings: React.FC<Props> = ({
       {source && <Spacer y={1} />}
       <AnimateHeight height={source ? "auto" : 0}>
         <div>
-          {source === "github"
-            ? renderGithubSettings()
-            : renderDockerSettings()}
+          {source === "github" ? (
+            <SharedBuildSettings
+              buildConfig={buildConfig}
+              actionConfig={actionConfig}
+              branch={branch}
+              dockerfilePath={dockerfilePath}
+              folderPath={folderPath}
+              setActionConfig={setActionConfig}
+              setDockerfilePath={setDockerfilePath}
+              setFolderPath={setFolderPath}
+              setBuildConfig={setBuildConfig}
+              porterYaml={porterYaml}
+              setPorterYaml={setPorterYaml}
+              setBranch={setBranch}
+              imageUrl={imageUrl}
+              setImageUrl={setImageUrl}
+            />
+          ) : (
+            renderDockerSettings()
+          )}
         </div>
       </AnimateHeight>
     </SourceSettingsContainer>