فهرست منبع

Merge pull request #496 from porter-dev/master

Webhook Toggle
sunguroku 5 سال پیش
والد
کامیت
8d1d479ce7

+ 5 - 0
dashboard/src/components/values-form/ValuesWrapper.tsx

@@ -38,12 +38,17 @@ export default class ValuesWrapper extends Component<PropsType, StateType> {
           section.contents.forEach((item: FormElement, i: number) => {
           section.contents.forEach((item: FormElement, i: number) => {
             // If no name is assigned use values.yaml variable as identifier
             // If no name is assigned use values.yaml variable as identifier
             let key = item.name || item.variable;
             let key = item.name || item.variable;
+            
             let def =
             let def =
               item.settings && item.settings.unit
               item.settings && item.settings.unit
                 ? `${item.settings.default}${item.settings.unit}`
                 ? `${item.settings.default}${item.settings.unit}`
                 : item.settings.default;
                 : item.settings.default;
             def = (item.value && item.value[0]) || def;
             def = (item.value && item.value[0]) || def;
 
 
+            if (item.type === 'checkbox') {
+              def = item.value[0]
+            }
+
             // Handle add to list of required fields
             // Handle add to list of required fields
             if (item.required) {
             if (item.required) {
               key && this.requiredFields.push(key);
               key && this.requiredFields.push(key);

+ 4 - 3
dashboard/src/main/home/launch/Launch.tsx

@@ -61,9 +61,10 @@ export default class Templates extends Component<PropsType, StateType> {
       )
       )
       .then((res) => {
       .then((res) => {
         this.setState({ applicationTemplates: res.data, error: false }, () => {
         this.setState({ applicationTemplates: res.data, error: false }, () => {
-          this.state.applicationTemplates.sort((a, b) =>
-            a.version > b.version ? 1 : -1
-          );
+          let preferredOrder = ['web', 'worker', 'job']
+          this.state.applicationTemplates.sort((a, b) => {
+            return preferredOrder.indexOf(a.name) - preferredOrder.indexOf(b.name)
+          });
           this.setState({
           this.setState({
             loading: false,
             loading: false,
           });
           });

+ 9 - 0
server/api/release_handler.go

@@ -677,6 +677,15 @@ func (app *App) HandleReleaseDeployWebhook(w http.ResponseWriter, r *http.Reques
 	rel, err := agent.GetRelease(form.Name, 0)
 	rel, err := agent.GetRelease(form.Name, 0)
 	rel.Config["image"] = image
 	rel.Config["image"] = image
 
 
+	if rel.Config["auto_deploy"] == false {
+		app.sendExternalError(err, http.StatusInternalServerError, HTTPError{
+			Code:   ErrReleaseDeploy,
+			Errors: []string{"Deploy webhook is disabled for this deployment."},
+		}, w)
+
+		return
+	} 
+
 	registries, err := app.Repo.Registry.ListRegistriesByProjectID(uint(form.ReleaseForm.Cluster.ProjectID))
 	registries, err := app.Repo.Registry.ListRegistriesByProjectID(uint(form.ReleaseForm.Cluster.ProjectID))
 
 
 	if err != nil {
 	if err != nil {

+ 11 - 0
services/deploy_init_container/Dockerfile

@@ -1,3 +1,14 @@
+FROM golang:1.15-alpine as builder
+
+WORKDIR /init-backend
+COPY main.go .
+
+RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -o main main.go
+
 FROM alpine
 FROM alpine
+
+COPY --from=builder /init-backend/main /
+COPY assets/init.html /assets/
+COPY assets/porter.png /assets/
 ADD start.sh /
 ADD start.sh /
 CMD ["sh", "/start.sh"]
 CMD ["sh", "/start.sh"]

+ 116 - 0
services/deploy_init_container/assets/init.html

@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Porter | Butler</title>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="HandheldFriendly" content="true">
+  <link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;600&display=swap" rel="stylesheet">
+  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400&display=swap" rel="stylesheet">
+  <style type="text/css">
+    .center-me {
+      margin: 0 auto;
+      min-width: 25%;
+      text-align: center;
+    }
+
+    body {
+      background: #e3e5e8;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      margin-top: calc(50vh - 220px);
+    }
+
+    h1 {
+      font-family: 'Work Sans', sans-serif;
+      font-size: 40px;
+      font-weight: 400;
+      color: #46484a;
+      user-select: none;
+      text-align: center;
+      opacity: 0;
+      animation: fadeIn 0.8s 0.2s;
+      animation-fill-mode: forwards;
+    }
+
+    h2 {
+      font-family: 'Work Sans', sans-serif;
+      font-size: 18px;
+      font-weight: 400;
+      color: #787878;
+      margin-top: 0px;
+      width: 80%;
+      max-width: 660px;
+      opacity: 0;
+      text-align: center;
+      line-height: 1.8em;
+      user-select: none;
+      animation: fadeIn 0.5s 0.3s;
+      animation-fill-mode: forwards;
+    }
+
+    img {
+      width: 120px;
+      margin-bottom: 20px;
+      animation: floatIn 1s;
+    }
+
+    @keyframes floatIn {
+      from { opacity: 0; transform: translateY(80px) }
+      to { opacity: 1; transform: translateY(0px) }
+    }
+
+    @keyframes fadeIn {
+      from { opacity: 0 }
+      to { opacity: 1 }
+    }
+
+    div {
+      box-sizing: border-box;
+      border-top-right-radius: 5px;
+      border-bottom-right-radius: 5px;
+      height: 100%;
+      background: #5c93ed;
+      display: flex;
+      align-items: center;
+      font-family: 'Open Sans', sans-serif;
+      justify-content: center;
+      cursor: pointer;
+      color: white;
+      border: 0;
+      width: 130px;
+      height: 50px;
+      margin-top: 45px;
+      font-size: 15px;
+      border-radius: 5px;
+      box-shadow: 0 0 2px 4px #6da4fe77;
+      z-index: 999;
+      user-select: none;
+      animation: pulsate 2s infinite;
+    }
+
+    div:hover {
+      background: #4b82dc;
+    }
+
+    @keyframes pulsate {
+      from { box-shadow: 0 0 0px 0px #6da4fe77; }
+      to { box-shadow: 0 0 3px 15px #6da4fe00; }
+    }
+      
+  </style>
+</head>
+
+<body>
+  <img src='https://i.ibb.co/y64zfm5/porter.png'></img>
+  <h1>One moment, please</h1>
+  <h2>
+    Your application is currently being built and will be ready soon. This page will disappear once your application is live. To view build logs, navigate to your connected GitHub repo and select the Actions tab.
+  </h2>
+  <div onclick="location.reload();">Refresh Page</div>
+</body>
+
+</html>

BIN
services/deploy_init_container/assets/porter.png


+ 22 - 0
services/deploy_init_container/default-backend-deployment.yaml

@@ -0,0 +1,22 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: nginx-errors
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: nginx-errors
+    spec:
+      containers:
+      - name: nginx-errors
+        image: gcr.io/porter-dev-273614/error-backend:latest
+        imagePullPolicy: Always
+        resources:
+          limits:
+            cpu: 20m
+            memory: 40Mi
+          requests:
+            cpu: 10m
+            memory: 20Mi      

+ 11 - 0
services/deploy_init_container/default-backend-service.yaml

@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: nginx-errors
+spec:
+  selector:
+    app: nginx-errors
+  ports:
+    - protocol: TCP
+      port: 80
+      targetPort: 9090

+ 40 - 0
services/deploy_init_container/main.go

@@ -0,0 +1,40 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+)
+
+func main() {
+	port := os.Getenv("PORT")
+
+	if port == "" {
+		port = "80"
+	}
+
+	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusOK)
+		w.Header().Set("Content-Type", "text/html; charset=utf-8")
+		file, err := ioutil.ReadFile("./assets/init.html")
+
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			log.Fatal("Can't find error html page")
+		}
+
+		w.Write(file)
+	})
+
+	// return 200 on healthz path
+	http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte("healthy!"))
+	})
+
+	if err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil); err != nil {
+		panic(err)
+	}
+}

+ 1 - 1
services/deploy_init_container/start.sh

@@ -16,4 +16,4 @@ https://docs.getporter.dev/docs/setting-up-cicd-1
 -------------------------------------------------------------------
 -------------------------------------------------------------------
 EOF
 EOF
 
 
-sleep infinity
+/main