diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000..0609164d73
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+# ignore everything except scm-server.tar.gz
+**
+!scm-server/target/*.tar.gz
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000..781a3e890b
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,20 @@
+FROM openjdk:8u171-alpine3.8
+
+ENV SCM_HOME=/var/lib/scm
+
+RUN set -x \
+ && apk add --no-cache mercurial bash \
+ && addgroup -S -g 1000 scm \
+ && adduser -S -s /bin/false -G scm -h /opt/scm-server -D -H -u 1000 scm \
+ && mkdir ${SCM_HOME} \
+ && chown scm:scm ${SCM_HOME}
+
+ADD scm-server/target/scm-server-app.tar.gz /opt
+RUN chown -R scm:scm /opt/scm-server
+
+WORKDIR /opt/scm-server
+VOLUME [ "${SCM_HOME}", "/opt/scm-server/var/log" ]
+EXPOSE 8080
+USER scm
+
+ENTRYPOINT [ "/opt/scm-server/bin/scm-server" ]
diff --git a/Jenkinsfile b/Jenkinsfile
index 50a2374544..4769a0bd3d 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -4,7 +4,7 @@
@Library('github.com/cloudogu/ces-build-lib@59d3e94')
import com.cloudogu.ces.cesbuildlib.*
-node() { // No specific label
+node('docker') {
// Change this as when we go back to default - necessary for proper SonarQube analysis
mainBranch = "2.0.0-m3"
@@ -44,6 +44,26 @@ node() { // No specific label
currentBuild.result = 'UNSTABLE'
}
}
+
+ def commitHash = getCommitHash()
+ def dockerImageTag = "2.0.0-dev-${commitHash.substring(0,7)}-${BUILD_NUMBER}"
+
+ if (isMainBranch()) {
+ stage('Docker') {
+ def image = docker.build('cloudogu/scm-manager')
+ docker.withRegistry('', 'hub.docker.com-cesmarvin') {
+ image.push(dockerImageTag)
+ image.push('latest')
+ }
+ }
+
+ stage('Deployment') {
+ build job: 'scm-manager/next-scm.cloudogu.com', propagate: false, wait: false, parameters: [
+ string(name: 'changeset', value: commitHash),
+ string(name: 'imageTag', value: dockerImageTag)
+ ]
+ }
+ }
}
// Archive Unit and integration test results, if any
@@ -62,7 +82,7 @@ Maven setupMavenBuild() {
// Keep this version number in sync with .mvn/maven-wrapper.properties
Maven mvn = new MavenInDocker(this, "3.5.2-jdk-8")
- if (mainBranch.equals(env.BRANCH_NAME)) {
+ if (isMainBranch()) {
// Release starts javadoc, which takes very long, so do only for certain branches
mvn.additionalArgs += ' -DperformRelease'
// JDK8 is more strict, we should fix this before the next release. Right now, this is just not the focus, yet.
@@ -89,7 +109,7 @@ void analyzeWith(Maven mvn) {
"-Dsonar.pullrequest.bitbucketcloud.repository=scm-manager "
} else {
mvnArgs += " -Dsonar.branch.name=${env.BRANCH_NAME} "
- if (!mainBranch.equals(env.BRANCH_NAME)) {
+ if (!isMainBranch()) {
// Avoid exception "The main branch must not have a target" on main branch
mvnArgs += " -Dsonar.branch.target=${mainBranch} "
}
@@ -98,6 +118,10 @@ void analyzeWith(Maven mvn) {
}
}
+boolean isMainBranch() {
+ return mainBranch.equals(env.BRANCH_NAME)
+}
+
boolean waitForQualityGateWebhookToBeCalled() {
boolean isQualityGateSucceeded = true
timeout(time: 2, unit: 'MINUTES') { // Needed when there is no webhook for example
@@ -114,6 +138,10 @@ String getCommitAuthorComplete() {
new Sh(this).returnStdOut 'hg log --branch . --limit 1 --template "{author}"'
}
+String getCommitHash() {
+ new Sh(this).returnStdOut 'hg log --branch . --limit 1 --template "{node}"'
+}
+
String getCommitAuthorEmail() {
def matcher = getCommitAuthorComplete() =~ "<(.*?)>"
matcher ? matcher[0][1] : ""
diff --git a/deployments/helm/.helmignore b/deployments/helm/.helmignore
new file mode 100644
index 0000000000..f0c1319444
--- /dev/null
+++ b/deployments/helm/.helmignore
@@ -0,0 +1,21 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
diff --git a/deployments/helm/Chart.yaml b/deployments/helm/Chart.yaml
new file mode 100644
index 0000000000..c5b5fff4cc
--- /dev/null
+++ b/deployments/helm/Chart.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+appVersion: "1.0"
+description: A Helm chart for SCM-Manager
+name: scm-manager
+version: 0.1.0
diff --git a/deployments/helm/templates/NOTES.txt b/deployments/helm/templates/NOTES.txt
new file mode 100644
index 0000000000..a58c8f124a
--- /dev/null
+++ b/deployments/helm/templates/NOTES.txt
@@ -0,0 +1,19 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range .Values.ingress.hosts }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "scm-manager.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get svc -w {{ include "scm-manager.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "scm-manager.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ include "scm-manager.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl port-forward $POD_NAME 8080:80
+{{- end }}
diff --git a/deployments/helm/templates/_helpers.tpl b/deployments/helm/templates/_helpers.tpl
new file mode 100644
index 0000000000..23d4e1b03e
--- /dev/null
+++ b/deployments/helm/templates/_helpers.tpl
@@ -0,0 +1,32 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "scm-manager.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "scm-manager.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "scm-manager.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
diff --git a/deployments/helm/templates/configmap.yaml b/deployments/helm/templates/configmap.yaml
new file mode 100644
index 0000000000..dd52b6fa8c
--- /dev/null
+++ b/deployments/helm/templates/configmap.yaml
@@ -0,0 +1,160 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "scm-manager.fullname" . }}
+ labels:
+ app: {{ include "scm-manager.name" . }}
+ chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+ release: "{{ .Release.Name }}"
+ heritage: "{{ .Release.Service }}"
+data:
+ server-config.xml: |
+
+
+
+
+
+
+ 16384
+ 16384
+
+ {{- if .Values.ingress.enabled -}}
+
+
+
+
+ {{- end }}
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /scm
+
+ /var/webapp/scm-webapp.war
+
+
+ org.eclipse.jetty.servlet.Default.dirAllowed
+ false
+
+
+ /work/scm
+
+
+
+
+ /
+
+
+
+
+ -
+ /var/webapp/docroot
+
+
+
+
+
+ /work/docroot
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+ logging.xml: |
+
+
+
+ <--
+ in a container environment we only need stdout
+ -->
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/deployments/helm/templates/deployment.yaml b/deployments/helm/templates/deployment.yaml
new file mode 100644
index 0000000000..928daa5f06
--- /dev/null
+++ b/deployments/helm/templates/deployment.yaml
@@ -0,0 +1,77 @@
+apiVersion: apps/v1beta2
+kind: Deployment
+metadata:
+ name: {{ include "scm-manager.fullname" . }}
+ labels:
+ app: {{ include "scm-manager.name" . }}
+ chart: {{ include "scm-manager.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+spec:
+ replicas: 1 # could not be scaled
+ strategy:
+ type: Recreate
+ selector:
+ matchLabels:
+ app: {{ include "scm-manager.name" . }}
+ release: {{ .Release.Name }}
+ template:
+ metadata:
+ labels:
+ app: {{ include "scm-manager.name" . }}
+ release: {{ .Release.Name }}
+ spec:
+ initContainers:
+ - name: volume-permissions
+ image: alpine:3.8
+ imagePullPolicy: IfNotPresent
+ command: ['sh', '-c', 'chown 1000:1000 /data']
+ volumeMounts:
+ - name: data
+ mountPath: /data
+ containers:
+ - name: {{ .Chart.Name }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 8080
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /scm
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /scm
+ port: http
+ resources:
+{{ toYaml .Values.resources | indent 12 }}
+ volumeMounts:
+ - name: data
+ mountPath: /var/lib/scm
+ - name: config
+ mountPath: /opt/scm-server/conf
+ volumes:
+ - name: data
+ {{- if .Values.persistence.enabled }}
+ persistentVolumeClaim:
+ claimName: {{ include "scm-manager.fullname" . }}
+ {{- else }}
+ emptyDir: {}
+ {{- end }}
+ - name: config
+ configMap:
+ name: {{ include "scm-manager.fullname" . }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+{{ toYaml . | indent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+{{ toYaml . | indent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+{{ toYaml . | indent 8 }}
+ {{- end }}
diff --git a/deployments/helm/templates/ingress.yaml b/deployments/helm/templates/ingress.yaml
new file mode 100644
index 0000000000..66912c9d96
--- /dev/null
+++ b/deployments/helm/templates/ingress.yaml
@@ -0,0 +1,38 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "scm-manager.fullname" . -}}
+{{- $ingressPath := .Values.ingress.path -}}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ app: {{ include "scm-manager.name" . }}
+ chart: {{ include "scm-manager.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+{{- with .Values.ingress.annotations }}
+ annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+spec:
+{{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+{{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ . | quote }}
+ http:
+ paths:
+ - path: {{ $ingressPath }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: http
+ {{- end }}
+{{- end }}
diff --git a/deployments/helm/templates/pvc.yaml b/deployments/helm/templates/pvc.yaml
new file mode 100644
index 0000000000..0e7d0f6db4
--- /dev/null
+++ b/deployments/helm/templates/pvc.yaml
@@ -0,0 +1,24 @@
+{{- if .Values.persistence.enabled -}}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ include "scm-manager.fullname" . }}
+ labels:
+ app: {{ include "scm-manager.name" . }}
+ chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+ release: "{{ .Release.Name }}"
+ heritage: "{{ .Release.Service }}"
+spec:
+ accessModes:
+ - {{ .Values.persistence.accessMode | quote }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size | quote }}
+{{- if .Values.persistence.storageClass }}
+{{- if (eq "-" .Values.persistence.storageClass) }}
+ storageClassName: ""
+{{- else }}
+ storageClassName: "{{ .Values.persistence.storageClass }}"
+{{- end }}
+{{- end }}
+{{- end -}}
diff --git a/deployments/helm/templates/service.yaml b/deployments/helm/templates/service.yaml
new file mode 100644
index 0000000000..f3a8207908
--- /dev/null
+++ b/deployments/helm/templates/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "scm-manager.fullname" . }}
+ labels:
+ app: {{ include "scm-manager.name" . }}
+ chart: {{ include "scm-manager.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: 8080
+ protocol: TCP
+ name: http
+ selector:
+ app: {{ include "scm-manager.name" . }}
+ release: {{ .Release.Name }}
diff --git a/deployments/helm/values.yaml b/deployments/helm/values.yaml
new file mode 100644
index 0000000000..d54088aa8b
--- /dev/null
+++ b/deployments/helm/values.yaml
@@ -0,0 +1,65 @@
+# Default values for scm-manager.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+# replicaCount: 1
+
+image:
+ repository: cloudogu/scm-manager
+ # TODO change after release, to something more stable
+ tag: latest
+ pullPolicy: Always
+
+nameOverride: ""
+fullnameOverride: ""
+
+service:
+ type: LoadBalancer
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ path: /
+ hosts:
+ - scm-manager.local
+ tls: []
+ # - secretName: scm-manager-tls
+ # hosts:
+ # - scm-manager.local
+
+## Enable persistence using Persistent Volume Claims
+## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
+##
+persistence:
+ enabled: true
+ ## ghost data Persistent Volume Storage Class
+ ## If defined, storageClassName:
+ ## If set to "-", storageClassName: "", which disables dynamic provisioning
+ ## If undefined (the default) or set to null, no storageClassName spec is
+ ## set, choosing the default provisioner. (gp2 on AWS, standard on
+ ## GKE, AWS & OpenStack)
+ ##
+ # storageClass: "-"
+ accessMode: ReadWriteOnce
+ size: 12Gi
+
+resources:
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ limits:
+ cpu: 2000m
+ memory: 2048Mi
+ requests:
+ cpu: 50m
+ memory: 256Mi
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}