Explorar el Código

merge docker build context fix

Alexander Belanger hace 4 años
padre
commit
527dc6917f

+ 4 - 1
Makefile

@@ -11,4 +11,7 @@ setup-env-files:
 	bash ./scripts/dev-environment/CreateDefaultEnvFiles.sh
 
 build-cli: 
-	go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd.Version=${VERSION}'" -a -tags cli -o $(BINDIR)/porter ./cli
+	go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd.Version=${VERSION}'" -a -tags cli -o $(BINDIR)/porter ./cli
+
+build-cli-dev:
+	go build -tags cli -o $(BINDIR)/porter ./cli

+ 1 - 1
cli/cmd/create.go

@@ -93,7 +93,7 @@ func init() {
 		&localPath,
 		"path",
 		"p",
-		".",
+		"",
 		"if local build, the path to the build directory",
 	)
 

+ 1 - 1
cli/cmd/deploy.go

@@ -235,7 +235,7 @@ func init() {
 		&localPath,
 		"path",
 		"p",
-		".",
+		"",
 		"If local build, the path to the build directory. If remote build, the relative path from the repository root to the build directory.",
 	)
 

+ 1 - 1
cli/cmd/deploy/create.go

@@ -281,7 +281,7 @@ func (c *CreateAgent) CreateFromDocker(
 	}
 
 	if opts.Method == DeployBuildTypeDocker {
-		err = buildAgent.BuildDocker(agent, opts.LocalPath, ".", opts.LocalDockerfile, "latest")
+		err = buildAgent.BuildDocker(agent, opts.LocalPath, opts.LocalPath, opts.LocalDockerfile, "latest")
 	} else {
 		err = buildAgent.BuildPack(agent, opts.LocalPath, "latest")
 	}

+ 1 - 0
cli/cmd/deploy/deploy.go

@@ -132,6 +132,7 @@ func NewDeployAgent(client *client.Client, app string, opts *DeployOpts) (*Deplo
 		deployAgent.dockerfilePath = deployAgent.opts.LocalDockerfile
 	} else {
 		deployAgent.imageRepo = release.GitActionConfig.ImageRepoURI
+		deployAgent.opts.LocalPath = release.GitActionConfig.FolderPath
 	}
 
 	deployAgent.tag = opts.OverrideTag

+ 15 - 6
cli/cmd/pack/pack.go

@@ -3,6 +3,7 @@ package pack
 import (
 	"context"
 	"fmt"
+	"path/filepath"
 
 	"github.com/buildpacks/pack"
 	"github.com/porter-dev/porter/cli/cmd/docker"
@@ -16,16 +17,24 @@ func (a *Agent) Build(opts *docker.BuildOpts) error {
 
 	//initialize a pack client
 	client, err := pack.NewClient()
+
+	if err != nil {
+		return err
+	}
+
+	absPath, err := filepath.Abs(opts.BuildContext)
+
 	if err != nil {
-		panic(err)
+		return err
 	}
 
 	buildOpts := pack.BuildOptions{
-		Image:        fmt.Sprintf("%s:%s", opts.ImageRepo, opts.Tag),
-		Builder:      "heroku/buildpacks:18",
-		AppPath:      opts.BuildContext,
-		TrustBuilder: true,
-		Env:          opts.Env,
+		RelativeBaseDir: filepath.Dir(absPath),
+		Image:           fmt.Sprintf("%s:%s", opts.ImageRepo, opts.Tag),
+		Builder:         "heroku/buildpacks:18",
+		AppPath:         opts.BuildContext,
+		TrustBuilder:    true,
+		Env:             opts.Env,
 	}
 
 	return client.Build(context, buildOpts)

+ 17 - 10
dashboard/src/components/porter-form/field-components/KeyValueArray.tsx

@@ -12,6 +12,7 @@ import Modal from "../../../main/home/modals/Modal";
 import LoadEnvGroupModal from "../../../main/home/modals/LoadEnvGroupModal";
 import EnvEditorModal from "../../../main/home/modals/EnvEditorModal";
 import { hasSetValue } from "../utils";
+import _ from "lodash";
 
 interface Props extends KeyValueArrayField {
   id: string;
@@ -166,17 +167,23 @@ const KeyValueArray: React.FC<Props> = (props) => {
             }
             setValues={(values) => {
               setState((prev) => {
+                // Transform array to object similar on what we receive from setValues
+                const prevValues = prev.values.reduce((acc, currentValue) => {
+                  acc[currentValue.key] = currentValue.value;
+                  return acc;
+                }, {} as Record<string, string>)
+
+                // Deconstruct the two records/objects inside one to merge their values (this will override the old duped vars too)
+                // and convert the new object back to an array usable for the component
+                const newValues = Object.entries({...prevValues, ...values})?.map(([k, v]) => {
+                  return {
+                    key: k,
+                    value: v,
+                  };
+                });
+
                 return {
-                  // might be broken
-                  values: [
-                    ...prev.values,
-                    ...Object.entries(values)?.map(([k, v]) => {
-                      return {
-                        key: k,
-                        value: v,
-                      };
-                    }),
-                  ],
+                  values: [...newValues]
                 };
               });
             }}

+ 14 - 31
dashboard/src/components/repo-selector/ActionConfEditor.tsx

@@ -67,44 +67,26 @@ const ActionConfEditor: React.FC<Props> = (props) => {
         </BackButton>
       </>
     );
-  } else if (!props.dockerfilePath && !props.folderPath) {
-    return (
-      <>
-        <ContentsList
-          actionConfig={actionConfig}
-          branch={branch}
-          setActionConfig={setActionConfig}
-          setDockerfilePath={(x: string) => props.setDockerfilePath(x)}
-          setProcfilePath={(x: string) => props.setProcfilePath(x)}
-          setFolderPath={(x: string) => props.setFolderPath(x)}
-        />
-        <Br />
-        <BackButton
-          width="145px"
-          onClick={() => {
-            setBranch("");
-          }}
-        >
-          <i className="material-icons">keyboard_backspace</i>
-          Select Branch
-        </BackButton>
-      </>
-    );
-  }
-
-  if (
-    props.procfilePath &&
-    props.folderPath &&
-    !props.dockerfilePath &&
-    !props.procfileProcess
+  } else if (
+    // select dockerfile or buildpack build context
+    (!props.dockerfilePath && !props.folderPath) ||
+    // select procfile process
+    (props.procfilePath &&
+      props.folderPath &&
+      !props.dockerfilePath &&
+      !props.procfileProcess) ||
+    // select docker build context
+    (props.dockerfilePath && !props.folderPath)
   ) {
     return (
       <>
         <ContentsList
           actionConfig={actionConfig}
           branch={branch}
-          setActionConfig={setActionConfig}
+          dockerfilePath={props.dockerfilePath}
           procfilePath={props.procfilePath}
+          folderPath={props.folderPath}
+          setActionConfig={setActionConfig}
           setDockerfilePath={(x: string) => props.setDockerfilePath(x)}
           setProcfilePath={(x: string) => props.setProcfilePath(x)}
           setProcfileProcess={(x: string) => props.setProcfileProcess(x)}
@@ -115,6 +97,7 @@ const ActionConfEditor: React.FC<Props> = (props) => {
           width="145px"
           onClick={() => {
             setBranch("");
+            props.setDockerfilePath("");
           }}
         >
           <i className="material-icons">keyboard_backspace</i>

+ 12 - 9
dashboard/src/components/repo-selector/ActionDetails.tsx

@@ -124,7 +124,7 @@ export default class ActionDetails extends Component<PropsType, StateType> {
           width="100%"
           value={this.props.branch}
         />
-        {this.props.dockerfilePath ? (
+        {this.props.dockerfilePath && (
           <InputRow
             disabled={true}
             label="Dockerfile Path"
@@ -132,15 +132,18 @@ export default class ActionDetails extends Component<PropsType, StateType> {
             width="100%"
             value={this.props.dockerfilePath}
           />
-        ) : (
-          <InputRow
-            disabled={true}
-            label="Folder Path"
-            type="text"
-            width="100%"
-            value={this.props.folderPath}
-          />
         )}
+        <InputRow
+          disabled={true}
+          label={
+            this.props.dockerfilePath
+              ? "Docker Build Context"
+              : "Application Folder"
+          }
+          type="text"
+          width="100%"
+          value={this.props.folderPath}
+        />
         {this.renderRegistrySection()}
         <Br />
 

+ 61 - 4
dashboard/src/components/repo-selector/ContentsList.tsx

@@ -19,6 +19,8 @@ interface AutoBuildpack {
 type PropsType = {
   actionConfig: ActionConfigType | null;
   branch: string;
+  dockerfilePath?: string;
+  folderPath: string;
   procfilePath?: string;
   setActionConfig: (x: ActionConfigType) => void;
   setProcfileProcess?: (x: string) => void;
@@ -35,6 +37,7 @@ type StateType = {
   dockerfiles: string[];
   processes: Record<string, string>;
   autoBuildpack: AutoBuildpack;
+  showingBuildContextPrompt: boolean;
 };
 
 export default class ContentsList extends Component<PropsType, StateType> {
@@ -49,6 +52,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
       valid: false,
       name: "",
     },
+    showingBuildContextPrompt: true,
   };
 
   componentDidMount() {
@@ -183,7 +187,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
         );
       }
 
-      if (fileName.includes("Dockerfile")) {
+      if (fileName.includes("Dockerfile") && !this.props.dockerfilePath) {
         return (
           <FileItem
             key={i}
@@ -227,12 +231,20 @@ export default class ContentsList extends Component<PropsType, StateType> {
     return (
       <FileItem lastItem={false}>
         <img src={info} />
-        Select Application Folder
+        Select{" "}
+        {this.props.dockerfilePath
+          ? "Docker Build Context"
+          : "Application Folder"}
       </FileItem>
     );
   };
 
   handleContinue = () => {
+    if (this.props.dockerfilePath) {
+      this.props.setFolderPath(this.state.currentDir || "./");
+      return;
+    }
+
     let dockerfiles = [] as string[];
     this.state.contents.forEach((item: FileType, i: number) => {
       let splits = item.path.split("/");
@@ -318,7 +330,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
         </Overlay>
       );
     }
-    if (this.state.dockerfiles.length > 0) {
+    if (this.state.dockerfiles.length > 0 && !this.props.dockerfilePath) {
       return (
         <Overlay>
           <BgOverlay onClick={() => this.setState({ dockerfiles: [] })} />
@@ -363,6 +375,45 @@ export default class ContentsList extends Component<PropsType, StateType> {
         </Overlay>
       );
     }
+    if (
+      this.props.dockerfilePath &&
+      !this.props.folderPath &&
+      this.state.showingBuildContextPrompt
+    ) {
+      return (
+        <Overlay>
+          <BgOverlay onClick={() => this.props.setDockerfilePath("")} />
+          <CloseButton
+            onClick={() =>
+              this.props.setFolderPath(this.state.currentDir || "./")
+            }
+          >
+            <CloseButtonImg src={close} />
+          </CloseButton>
+          <Label>
+            Would you like to set the Docker build context to a different
+            directory?
+          </Label>
+          <MultiSelectRow>
+            <ConfirmButton
+              onClick={() => {
+                this.setState({ showingBuildContextPrompt: false });
+                this.setSubdirectory("");
+              }}
+            >
+              Yes
+            </ConfirmButton>
+            <ConfirmButton
+              onClick={() =>
+                this.props.setFolderPath(this.state.currentDir || "./")
+              }
+            >
+              No
+            </ConfirmButton>
+          </MultiSelectRow>
+        </Overlay>
+      );
+    }
   };
 
   render() {
@@ -476,12 +527,18 @@ const Indicator = styled.div<{ selected: boolean }>`
 `;
 
 const Label = styled.div`
-  max-width: 420px;
+  max-width: 500px;
   line-height: 1.5em;
   text-align: center;
   font-size: 14px;
 `;
 
+const MultiSelectRow = styled.div`
+  display: flex;
+  min-width: 150px;
+  justify-content: space-between;
+`;
+
 const DockerfileList = styled.div`
   border-radius: 3px;
   margin-top: 20px;

+ 14 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/SettingsSection.tsx

@@ -287,6 +287,19 @@ const SettingsSection: React.FC<PropsType> = ({
     return false;
   };
 
+  const canBeCloned = () => {
+    if(chartWasDeployedWithGithub()) {
+      return false;
+    }
+
+    // If its not web worker or job it means is an addon, and for now it's not supported
+    if (!["web", "worker", "job"].includes(currentChart?.chart?.metadata?.name)) {
+      return false
+    }
+
+    return true
+  }
+
   return (
     <Wrapper>
       {!loadingWebhookToken ? (
@@ -294,7 +307,7 @@ const SettingsSection: React.FC<PropsType> = ({
           {renderWebhookSection()}
           <NotificationSettingsSection currentChart={currentChart} />
           {/* Prevent the clone button to be rendered in github deployed charts */}
-          {!chartWasDeployedWithGithub() && (
+          {canBeCloned() && (
             <>
               <Heading>Clone deployment</Heading>
               <Helper>

+ 8 - 0
dashboard/src/main/home/launch/Launch.tsx

@@ -125,6 +125,14 @@ class Templates extends Component<PropsType, StateType> {
           this.props.history.push("/dashboard");
           return;
         }
+        // If its not web worker or job it means is an addon, and for now it's not supported
+        if (!["web", "worker", "job"].includes(release?.chart?.metadata?.name)) {
+          this.context.setCurrentError(
+            "Addons don't support cloning yet!"
+          );
+          this.props.history.push("/dashboard");
+          return;
+        }
       }
 
       this.setState(

+ 1 - 1
dashboard/src/main/home/launch/launch-flow/LaunchFlow.tsx

@@ -335,7 +335,7 @@ const LaunchFlow: React.FC<PropsType> = (props) => {
       );
     }
 
-    if (!templateName && !props.isCloning) {
+    if (!templateName && !props.isCloning && currentTab === "porter") {
       const newTemplateName = generateRandomName();
       setTemplateName(newTemplateName);
     }

+ 9 - 1
dashboard/src/main/home/launch/launch-flow/SourcePage.tsx

@@ -147,7 +147,15 @@ class SourcePage extends Component<PropsType, StateType> {
     } = this.props;
     return (
       <StyledSourceBox>
-        <CloseButton onClick={() => setSourceType("")}>
+        <CloseButton
+          onClick={() => {
+            setSourceType("");
+            setDockerfilePath("");
+            setFolderPath("");
+            setProcfilePath("");
+            setProcfileProcess("");
+          }}
+        >
           <CloseButtonImg src={close} />
         </CloseButton>
         <Subtitle>