Przeglądaj źródła

Merge branch 'simplified-view' of github.com:porter-dev/porter into simplified-view

Feroze Mohideen 3 lat temu
rodzic
commit
b95b87ee1f

+ 16 - 8
api/server/handlers/stacks/create_porter_app.go

@@ -1,7 +1,6 @@
 package stacks
 
 import (
-	"fmt"
 	"net/http"
 
 	"github.com/porter-dev/porter/api/server/authz"
@@ -31,21 +30,30 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
 	ctx := r.Context()
 	project, _ := ctx.Value(types.ProjectScope).(*models.Project)
 	cluster, _ := ctx.Value(types.ClusterScope).(*models.Cluster)
-	fmt.Println("congrats on making it!", cluster.ID, project.ID)
+
+	request := &types.CreatePorterAppRequest{}
+
+	ok := c.DecodeAndValidate(w, r, request)
+
+	if !ok {
+		return
+	}
 
 	app := &models.PorterApp{
-		Name:      "test",
+		Name:      request.Name,
 		ClusterID: cluster.ID,
 		ProjectID: project.ID,
-		GitBranch: "main",
+		RepoName:  request.RepoName,
+		GitBranch: request.GitBranch,
 
-		BuildContext: "./",
-		Builder:      "heroku/buildpacks:18",
-		Buildpacks:   "nodejs",
-		Dockerfile:   "",
+		BuildContext: request.BuildContext,
+		Builder:      request.Builder,
+		Buildpacks:   request.Buildpacks,
+		Dockerfile:   request.Dockerfile,
 	}
 
 	_, err := c.Repo().PorterApp().CreatePorterApp(app)
+
 	if err != nil {
 		return
 	}

+ 13 - 0
api/types/stacks.go

@@ -22,6 +22,19 @@ type CreateStackRequest struct {
 	EnvGroups []*CreateStackEnvGroupRequest `json:"env_groups,omitempty" form:"required,dive,required"`
 }
 
+// swagger:model
+type CreatePorterAppRequest struct {
+	Name         string `json:"name" form:"required"`
+	ClusterID    uint   `json:"cluster_id"`
+	ProjectID    uint   `json:"project_id"`
+	RepoName     string `json:"repo_name" form:"required"`
+	GitBranch    string `json:"git_branch" form:"required"`
+	BuildContext string `json:"build_context" form:"required"`
+	Builder      string `json:"builder"`
+	Buildpacks   string `json:"buildpacks"`
+	Dockerfile   string `json:"dockerfile"`
+}
+
 // swagger:model
 type PutStackSourceConfigRequest struct {
 	SourceConfigs []*CreateStackSourceConfigRequest `json:"source_configs,omitempty" form:"required,dive,required"`

+ 37 - 14
dashboard/src/main/home/app-dashboard/new-app-flow/NewAppFlow.tsx

@@ -84,6 +84,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
   const { currentCluster, currentProject } = useContext(Context);
   const [isLoading, setIsLoading] = useState<boolean>(true);
   const [currentStep, setCurrentStep] = useState<number>(0);
+  const [existingStep, setExistingStep] = useState<number>(0);
   const [formState, setFormState] = useState<FormState>(INITIAL_STATE);
   const [actionConfig, setActionConfig] = useState<GithubActionConfigType>({
     ...defaultActionConfig,
@@ -143,21 +144,48 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
   }
 
   // Deploys a Helm chart and writes build settings to the DB
+  const isAppNameValid = (name: string) => {
+    const regex = /^[a-z0-9-]+$/;
+    return regex.test(name);
+  };
+
+  const handleAppNameChange = (name: string) => {
+    setCurrentStep(currentStep);
+    setFormState({ ...formState, applicationName: name });
+    if (isAppNameValid(name) && Validators.applicationName(name)) {
+      setCurrentStep(Math.max(Math.max(currentStep, 1), existingStep));
+    } else {
+      setExistingStep(Math.max(currentStep, existingStep));
+      setCurrentStep(0);
+    }
+  };
+
+  const shouldHighlightAppNameInput = () => {
+    return (
+      formState.applicationName !== "" &&
+      !isAppNameValid(formState.applicationName)
+    );
+  };
   const deployPorterApp = async () => {
     try {
-
       // Write build settings to the DB
       const res = await api.createPorterApp(
         "<token>",
         {
           name: formState.applicationName,
+          repo_name: actionConfig.git_repo,
+          git_branch: branch,
+          build_context: folderPath,
+          builder: "heroku",
+          buildpacks: "nodejs,ruby",
+          dockerfile: "",
+
         },
         {
           cluster_id: currentCluster.id,
           project_id: currentProject.id,
         }
       );
-      alert("ok")
     } catch (err) {
       console.log(err);
     }
@@ -169,14 +197,7 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
     <CenterWrapper>
       <Div>
         <StyledConfigureTemplate>
-          <Back to="/apps" />
-          <DashboardHeader
-            prefix={<Icon src={web} />}
-            title="Deploy a new application"
-            capitalize={false}
-            disableLineBreak
-          />
-          <DarkMatter />
+          {/* ... */}
           <VerticalSteps
             currentStep={currentStep}
             steps={[
@@ -191,13 +212,15 @@ const NewAppFlow: React.FC<Props> = ({ ...props }) => {
                   placeholder="ex: academic-sophon"
                   value={formState.applicationName}
                   width="300px"
+                  error={
+                    shouldHighlightAppNameInput() &&
+                    'Lowercase letters, numbers, and "-" only.'
+                  }
                   setValue={(e) => {
-                    setFormState({ ...formState, applicationName: e });
-                    if (Validators.applicationName(e)) {
-                      setCurrentStep(Math.max(currentStep, 1));
-                    }
+                    handleAppNameChange(e);
                   }}
                 />
+                {shouldHighlightAppNameInput()}
               </>,
               <>
                 <Text size={16}>Deployment method</Text>

+ 50 - 32
dashboard/src/main/home/app-dashboard/new-app-flow/Services.tsx

@@ -1,4 +1,4 @@
-import React, { useState } from "react"
+import React, { useState } from "react";
 import ServiceContainer from "./ServiceContainer";
 import styled from "styled-components";
 import Spacer from "components/porter/Spacer";
@@ -19,32 +19,41 @@ interface ServicesProps {
   setServices: (services: Service[]) => void;
 }
 
-const Services: React.FC<ServicesProps> = ({
-  services,
-  setServices,
-}) => {
-  const [showAddServiceModal, setShowAddServiceModal] = useState<boolean>(false);
-  const [serviceName, setServiceName] = useState<string>('');
-  const [serviceType, setServiceType] = useState<ServiceType>('web');
+const Services: React.FC<ServicesProps> = ({ services, setServices }) => {
+  const [showAddServiceModal, setShowAddServiceModal] = useState<boolean>(
+    false
+  );
+  const [serviceName, setServiceName] = useState<string>("");
+  const [serviceType, setServiceType] = useState<ServiceType>("web");
+  const isServiceNameValid = (name: string) => {
+    const regex = /^[a-z0-9-]+$/;
+    return regex.test(name);
+  };
 
   return (
     <>
-      {services.length > 0 &&
+      {services.length > 0 && (
         <>
           <ServicesContainer>
             {services.map((service, index) => {
               return (
                 <ServiceContainer
                   service={service}
-                  editService={(newService: Service) => setServices(services.map((s, i) => i === index ? newService : s))}
-                  deleteService={() => setServices(services.filter((_, i) => i !== index))}
+                  editService={(newService: Service) =>
+                    setServices(
+                      services.map((s, i) => (i === index ? newService : s))
+                    )
+                  }
+                  deleteService={() =>
+                    setServices(services.filter((_, i) => i !== index))
+                  }
                 />
-              )
+              );
             })}
           </ServicesContainer>
           <Spacer y={0.5} />
         </>
-      }
+      )}
       <AddServiceButton onClick={() => setShowAddServiceModal(true)}>
         <i className="material-icons add-icon">add_icon</i>
         Add a new service
@@ -57,18 +66,18 @@ const Services: React.FC<ServicesProps> = ({
           <Spacer y={0.5} />
           <Container row>
             <ServiceIcon>
-              {serviceType === 'web' && <img src={web} />}
-              {serviceType === 'worker' && <img src={worker} />}
-              {serviceType === 'job' && <img src={job} />}
+              {serviceType === "web" && <img src={web} />}
+              {serviceType === "worker" && <img src={worker} />}
+              {serviceType === "job" && <img src={job} />}
             </ServiceIcon>
             <Select
               value={serviceType}
               // this is ugly
               setValue={(value: string) => setServiceType(value as ServiceType)}
               options={[
-                { label: 'Web', value: 'web' },
-                { label: 'Worker', value: 'worker' },
-                { label: 'Job', value: 'job' }
+                { label: "Web", value: "web" },
+                { label: "Worker", value: "worker" },
+                { label: "Job", value: "job" },
               ]}
             />
           </Container>
@@ -79,24 +88,34 @@ const Services: React.FC<ServicesProps> = ({
             placeholder="ex: my-service"
             width="300px"
             value={serviceName}
+            error={
+              !isServiceNameValid(serviceName) &&
+              'Lowercase letters, numbers, and "-" only.'
+            }
             setValue={setServiceName}
           />
           <Spacer y={1} />
-          <Button onClick={() => {
-            setServices([...services, createDefaultService(serviceName, serviceType)]);
-            setShowAddServiceModal(false);
-            setServiceName('');
-            setServiceType('web');
-          }}>
+          <Button
+            onClick={() => {
+              setServices([
+                ...services,
+                createDefaultService(serviceName, serviceType),
+              ]);
+              setShowAddServiceModal(false);
+              setServiceName("");
+              setServiceType("web");
+            }}
+            disabled={!isServiceNameValid(serviceName)}
+          >
             <I className="material-icons">add</I> Add service
           </Button>
         </Modal>
       )}
     </>
-  )
-}
+  );
+};
 
-export default Services
+export default Services;
 
 const ServiceIcon = styled.div`
   border: 1px solid #494b4f;
@@ -133,11 +152,10 @@ const I = styled.i`
   justify-content: center;
 `;
 
-const ServicesContainer = styled.div`
-`;
+const ServicesContainer = styled.div``;
 
 const AddServiceButton = styled.div`
-  color:  #aaaabb;
+  color: #aaaabb;
   background: #26292e;
   border: 1px solid #494b4f;
   :hover {
@@ -156,4 +174,4 @@ const AddServiceButton = styled.div`
     width: 30px;
     font-size: 20px;
   }
-`;
+`;

+ 6 - 0
dashboard/src/shared/api.tsx

@@ -167,6 +167,12 @@ const createEmailVerification = baseApi<{}, {}>("POST", (pathParams) => {
 const createPorterApp = baseApi<
   {
     name: string;
+    repo_name: string;
+    git_branch: string;
+    build_context: string;
+    builder: string;
+    buildpacks: string;
+    dockerfile: string;
   },
   {
     project_id: number;