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

Merge pull request #528 from porter-dev/procfile-support

Multi-process procfile support
jusrhee 5 лет назад
Родитель
Сommit
c72aee2011

+ 45 - 0
dashboard/src/components/repo-selector/ActionConfEditor.tsx

@@ -16,7 +16,11 @@ type PropsType = {
   setBranch: (x: string) => void;
   reset: any;
   dockerfilePath: string;
+  procfilePath: string;
+  procfileProcess: string;
   setDockerfilePath: (x: string) => void;
+  setProcfileProcess: (x: string) => void;
+  setProcfilePath: (x: string) => void;
   folderPath: string;
   setFolderPath: (x: string) => void;
   setSelectedRegistry: (x: any) => void;
@@ -84,6 +88,7 @@ export default class ActionConfEditor extends Component<PropsType, StateType> {
               branch={branch}
               setActionConfig={setActionConfig}
               setDockerfilePath={(x: string) => this.props.setDockerfilePath(x)}
+              setProcfilePath={(x: string) => this.props.setProcfilePath(x)}
               setFolderPath={(x: string) => this.props.setFolderPath(x)}
             />
           </ExpandedWrapperAlt>
@@ -100,14 +105,54 @@ export default class ActionConfEditor extends Component<PropsType, StateType> {
         </>
       );
     }
+
+    if (
+      this.props.procfilePath &&
+      this.props.folderPath &&
+      !this.props.dockerfilePath &&
+      !this.props.procfileProcess
+    ) {
+      return (
+        <>
+          <ExpandedWrapperAlt>
+            <ContentsList
+              actionConfig={actionConfig}
+              branch={branch}
+              setActionConfig={setActionConfig}
+              procfilePath={this.props.procfilePath}
+              setDockerfilePath={(x: string) => this.props.setDockerfilePath(x)}
+              setProcfilePath={(x: string) => this.props.setProcfilePath(x)}
+              setProcfileProcess={(x: string) =>
+                this.props.setProcfileProcess(x)
+              }
+              setFolderPath={(x: string) => this.props.setFolderPath(x)}
+            />
+          </ExpandedWrapperAlt>
+          <Br />
+          <BackButton
+            width="145px"
+            onClick={() => {
+              setBranch("");
+            }}
+          >
+            <i className="material-icons">keyboard_backspace</i>
+            Select Branch
+          </BackButton>
+        </>
+      );
+    }
+
     return (
       <ActionDetails
         branch={branch}
         setDockerfilePath={this.props.setDockerfilePath}
         setFolderPath={this.props.setFolderPath}
+        setProcfilePath={this.props.setProcfilePath}
+        setProcfileProcess={this.props.setProcfileProcess}
         actionConfig={actionConfig}
         setActionConfig={setActionConfig}
         dockerfilePath={this.props.dockerfilePath}
+        procfilePath={this.props.procfilePath}
         folderPath={this.props.folderPath}
         setSelectedRegistry={this.props.setSelectedRegistry}
         selectedRegistry={this.props.selectedRegistry}

+ 11 - 7
dashboard/src/components/repo-selector/ActionDetails.tsx

@@ -15,6 +15,9 @@ type PropsType = {
   setActionConfig: (x: ActionConfigType) => void;
   branch: string;
   dockerfilePath: string;
+  procfilePath: string;
+  setProcfilePath: (x: string) => void;
+  setProcfileProcess: (x: string) => void;
   folderPath: string;
   setSelectedRegistry: (x: any) => void;
   selectedRegistry: any;
@@ -29,12 +32,6 @@ type StateType = {
   loading: boolean;
 };
 
-const dummyRegistries = [
-  { id: 1, service: "ecr", url: "https://idfkasdfasdf" },
-  { id: 12, service: "ecr", url: "https://dfasdfidfkasdfasdf" },
-  { id: 11, service: "gcr", url: "https://idfkasdfasdf" },
-] as any[];
-
 export default class ActionDetails extends Component<PropsType, StateType> {
   state = {
     dockerRepo: "",
@@ -165,12 +162,19 @@ export default class ActionDetails extends Component<PropsType, StateType> {
             onClick={() => {
               this.props.setDockerfilePath(null);
               this.props.setFolderPath(null);
+              this.props.setProcfilePath(null);
+              this.props.setProcfileProcess(null);
             }}
           >
             <i className="material-icons">keyboard_backspace</i>
             Select Folder
           </BackButton>
-          {this.props.selectedRegistry ? (
+          {!this.props.procfilePath && !this.props.dockerfilePath ? (
+            <StatusWrapper>
+              <i className="material-icons">error_outline</i>
+              Procfile not detected.
+            </StatusWrapper>
+          ) : this.props.selectedRegistry ? (
             <StatusWrapper successful={true}>
               <i className="material-icons">done</i> Source selected
             </StatusWrapper>

+ 77 - 5
dashboard/src/components/repo-selector/ContentsList.tsx

@@ -14,8 +14,11 @@ import Loading from "../Loading";
 type PropsType = {
   actionConfig: ActionConfigType | null;
   branch: string;
+  procfilePath?: string;
   setActionConfig: (x: ActionConfigType) => void;
+  setProcfileProcess?: (x: string) => void;
   setDockerfilePath: (x: string) => void;
+  setProcfilePath: (x: string) => void;
   setFolderPath: (x: string) => void;
 };
 
@@ -25,10 +28,9 @@ type StateType = {
   contents: FileType[];
   currentDir: string;
   dockerfiles: string[];
+  processes: Record<string, string>;
 };
 
-const dummyDockerfiles = ["dev.Dockerfile", "prod.Dockerfile", "Dockerfile"];
-
 export default class ContentsList extends Component<PropsType, StateType> {
   state = {
     loading: true,
@@ -36,6 +38,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
     contents: [] as FileType[],
     currentDir: "",
     dockerfiles: [] as string[],
+    processes: null as Record<string, string>,
   };
 
   componentDidMount() {
@@ -86,6 +89,26 @@ export default class ContentsList extends Component<PropsType, StateType> {
 
         this.setState({ loading: false, error: true });
       });
+
+    api
+      .getProcfileContents(
+        "<token>",
+        { path: "./Procfile" },
+        {
+          project_id: currentProject.id,
+          git_repo_id: actionConfig.git_repo_id,
+          kind: "github",
+          owner: actionConfig.git_repo.split("/")[0],
+          name: actionConfig.git_repo.split("/")[1],
+          branch: branch,
+        }
+      )
+      .then((res) => {
+        this.setState({ processes: res.data });
+      })
+      .catch((err) => {
+        console.log(err);
+      });
   };
 
   renderContentList = () => {
@@ -130,6 +153,7 @@ export default class ContentsList extends Component<PropsType, StateType> {
           </FileItem>
         );
       }
+
       return (
         <FileItem key={i} lastItem={i === contents.length - 1}>
           <img src={file} />
@@ -173,6 +197,9 @@ export default class ContentsList extends Component<PropsType, StateType> {
       if (fileName.includes("Dockerfile")) {
         dockerfiles.push(fileName);
       }
+      if (fileName.includes("Procfile")) {
+        this.props.setProcfilePath(item.Path);
+      }
     });
     if (dockerfiles.length > 0) {
       this.setState({ dockerfiles });
@@ -186,6 +213,50 @@ export default class ContentsList extends Component<PropsType, StateType> {
   };
 
   renderOverlay = () => {
+    if (this.props.procfilePath) {
+      let processes = Object.keys(this.state.processes);
+      return (
+        <Overlay>
+          <BgOverlay
+            onClick={() =>
+              this.setState({ dockerfiles: [] }, () => {
+                this.props.setFolderPath("");
+                this.props.setProcfilePath("");
+              })
+            }
+          />
+          <CloseButton
+            onClick={() =>
+              this.setState({ dockerfiles: [] }, () => {
+                this.props.setProcfilePath("");
+              })
+            }
+          >
+            <CloseButtonImg src={close} />
+          </CloseButton>
+          <Label>
+            Porter has detected a Procfile in this folder. Which process would
+            you like to run?
+          </Label>
+          <DockerfileList>
+            {processes.map((process: string, i: number) => {
+              return (
+                <Row
+                  key={i}
+                  onClick={() => {
+                    this.props.setProcfileProcess(process);
+                  }}
+                  isLast={processes.length - 1 === i}
+                >
+                  <Indicator selected={false}></Indicator>
+                  {process}
+                </Row>
+              );
+            })}
+          </DockerfileList>
+        </Overlay>
+      );
+    }
     if (this.state.dockerfiles.length > 0) {
       return (
         <Overlay>
@@ -216,9 +287,10 @@ export default class ContentsList extends Component<PropsType, StateType> {
             })}
           </DockerfileList>
           <ConfirmButton
-            onClick={() =>
-              this.props.setFolderPath(this.state.currentDir || "./")
-            }
+            onClick={() => {
+              this.props.setFolderPath(this.state.currentDir || "./");
+              this.props.setProcfilePath("./Procfile");
+            }}
           >
             No, I don't want to use a Dockerfile
           </ConfirmButton>

+ 11 - 0
dashboard/src/components/values-form/ValuesForm.tsx

@@ -23,6 +23,7 @@ type PropsType = {
   disabled?: boolean;
   namespace?: string;
   clusterId?: number;
+  procfileProcess?: string;
 };
 
 type StateType = any;
@@ -43,6 +44,16 @@ export default class ValuesForm extends Component<PropsType, StateType> {
     return section.contents.map((item: FormElement, i: number) => {
       // If no name is assigned use values.yaml variable as identifier
       let key = item.name || item.variable;
+
+      // ugly exception to hide start command option when procfile process is set.
+      if (
+        (item.variable === "container.command" ||
+          (item.type == "subtitle" && item.name == "command_description")) &&
+        this.props.procfileProcess
+      ) {
+        return;
+      }
+
       switch (item.type) {
         case "heading":
           return <Heading key={i}>{item.label}</Heading>;

+ 42 - 1
dashboard/src/main/home/launch/expanded-template/LaunchTemplate.tsx

@@ -50,9 +50,11 @@ type StateType = {
   tabContents: any;
   namespaceOptions: { label: string; value: string }[];
   actionConfig: ActionConfigType;
+  procfileProcess: string;
   branch: string;
   repoType: string;
   dockerfilePath: string | null;
+  procfilePath: string | null;
   folderPath: string | null;
   selectedRegistry: any | null;
   env: any;
@@ -86,6 +88,8 @@ class LaunchTemplate extends Component<PropsType, StateType> {
     branch: "",
     repoType: "",
     dockerfilePath: null as string | null,
+    procfileProcess: null as string | null,
+    procfilePath: null as string | null,
     folderPath: null as string | null,
     selectedRegistry: null as any | null,
     env: {},
@@ -376,8 +380,18 @@ class LaunchTemplate extends Component<PropsType, StateType> {
       sourceType,
       dockerfilePath,
       folderPath,
+      procfilePath,
     } = this.state;
 
+    if (
+      sourceType === "repo" &&
+      !dockerfilePath &&
+      folderPath &&
+      !procfilePath
+    ) {
+      return "Procfile not detected.";
+    }
+
     if (!this.submitIsDisabled()) {
       return this.state.saveValuesStatus;
     }
@@ -415,6 +429,15 @@ class LaunchTemplate extends Component<PropsType, StateType> {
         renderSaveButton={true}
       >
         {(metaState: any, setMetaState: any) => {
+          if (!metaState) {
+            return;
+          }
+
+          // handle when procfileProcess is already specified
+          metaState["container.command"] = this.state.procfileProcess
+            ? this.state.procfileProcess
+            : "";
+
           return this.props.form?.tabs.map((tab: any, i: number) => {
             // If tab is current, render
             if (tab.name === this.state.currentTab) {
@@ -428,6 +451,8 @@ class LaunchTemplate extends Component<PropsType, StateType> {
                   // For env group loader
                   namespace={this.state.selectedNamespace}
                   clusterId={this.state.selectedClusterId}
+                  // For procfile process
+                  procfileProcess={this.state.procfileProcess}
                 />
               );
             }
@@ -587,7 +612,15 @@ class LaunchTemplate extends Component<PropsType, StateType> {
     } else if (this.state.sourceType === "registry") {
       return (
         <StyledSourceBox>
-          <CloseButton onClick={() => this.setState({ sourceType: "" })}>
+          <CloseButton
+            onClick={() =>
+              this.setState({
+                sourceType: "",
+                selectedImageUrl: "",
+                selectedTag: "",
+              })
+            }
+          >
             <CloseButtonImg src={close} />
           </CloseButton>
           <Subtitle>
@@ -663,10 +696,18 @@ class LaunchTemplate extends Component<PropsType, StateType> {
                 );
               })
             }
+            procfileProcess={this.state.procfileProcess}
+            setProcfileProcess={(procfileProcess: string) =>
+              this.setState({ procfileProcess })
+            }
             setBranch={(branch: string) => this.setState({ branch })}
             setDockerfilePath={(x: string) =>
               this.setState({ dockerfilePath: x })
             }
+            setProcfilePath={(x: string) => {
+              this.setState({ procfilePath: x });
+            }}
+            procfilePath={this.state.procfilePath}
             dockerfilePath={this.state.dockerfilePath}
             folderPath={this.state.folderPath}
             setFolderPath={(x: string) => this.setState({ folderPath: x })}