diff --git a/.circleci/Dockerfile b/.circleci/Dockerfile new file mode 100644 index 0000000..d06560e --- /dev/null +++ b/.circleci/Dockerfile @@ -0,0 +1,37 @@ +# docker file for the ci +# to build and publish: +# docker buildx build -t molgenis/molgenis-org-ci:v1.0.1 --platform linux/amd64 . +# docker push molgenis/molgenis-org-ci:v1.0.1 + +FROM ubuntu:jammy + +# general deps +RUN apt-get update +RUN apt-get install ruby-full build-essential zlib1g-dev lsb-release curl -y + +# kubectl repo +RUN curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add +RUN echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list +RUN apt-get update +RUN apt-get install kubectl -y + +# +##helm repo +RUN curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | tee /usr/share/keyrings/helm.gpg > /dev/null +RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | tee /etc/apt/sources.list.d/helm-stable-debian.list +RUN apt-get update +RUN apt-get install helm -y +# + +# Azure CLI Tools +RUN mkdir -p /etc/apt/keyrings +RUN curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/keyrings/microsoft.gpg > /dev/null +RUN chmod go+r /etc/apt/keyrings/microsoft.gpg +RUN AZ_DIST=$(lsb_release -cs) && echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $AZ_DIST main" | tee /etc/apt/sources.list.d/azure-cli.list +RUN apt-get update +RUN apt-get install azure-cli + +# jekyll +COPY Gemfile . +RUN gem install bundler jekyll +RUN bundle update \ No newline at end of file diff --git a/.circleci/Gemfile b/.circleci/Gemfile new file mode 100644 index 0000000..1867a59 --- /dev/null +++ b/.circleci/Gemfile @@ -0,0 +1,8 @@ +source 'https://rubygems.org' + +ruby '3.0.2' + +gem "jekyll" +gem "jekyll-feed" +gem "jekyll-target-blank" +gem "html-proofer" diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..592f3cb --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,68 @@ +version: 2.1 + +parameters: + GHA_Actor: + type: string + default: "" + GHA_Event: + type: string + default: "" + GHA_Action: + type: string + default: "" + GHA_Meta: + type: string + default: "" + +orbs: + slack: circleci/slack@4.4.4 + +jobs: + build: + docker: + - image: molgenis/molgenis-org-ci:v1.0.1 + steps: + - checkout + - run: + name: Jekyll build + command: | + bundle exec jekyll doctor + bundle exec jekyll build + - run: + name: prepare azure + command: | + az login --service-principal --tenant ${AZURE_SP_TENANT} -u ${AZURE_CLIENT_ID} -p ${AZURE_SECRET} + az aks get-credentials -g ${RESOURCE_GROUP} -n ${RESOURCE_GROUP} + kubectl config set-cluster ${RESOURCE_GROUP} + kubectl config use-context ${RESOURCE_GROUP} + - run: + name: update preview + command: | + NAME="preview-molgenis-org-pr-${CIRCLE_PULL_REQUEST##*/}" + echo "${NAME}" + kubectl delete namespace $NAME || true + echo ${CERTDEVMOLGENIS_KEY} | base64 --decode >> /tmp/cert_key + echo ${CERTDEVMOLGENIS_PEM} | base64 --decode >> /tmp/cert_pem + kubectl create namespace ${NAME} + kubectl create secret tls "dev.molgenis.org" --key /tmp/cert_key --cert /tmp/cert_pem -n ${NAME} + kubectl create configmap html-files --from-file=_site -n ${NAME} + helm upgrade --install ${NAME} ./helm-chart --namespace ${NAME} \ + --set ingress.hosts[0].host=${NAME}.dev.molgenis.org \ + --set spec.tls[0].hosts[0].host=${NAME}.dev.molgenis.org \ + --set image.tag=latest \ + --set image.repository=nginx \ + --set image.pullPolicy=Always \ + --debug + - run: + name: message slack about preview + command: | + curl -d "token=${SLACK_TOKEN}" \ + -d "text=*<${CIRCLE_PULL_REQUEST}|Circle-CI » Molgenis » Molgenis-org » PR-${CIRCLE_PULL_REQUEST##*/} #${CIRCLE_BUILD_NUM}>* + PR Preview available on https://preview-molgenis-org-${CIRCLE_PULL_REQUEST##*/}.dev.molgenis.org" \ + -d "channel=C02AZDG6QQ7" \ + -X POST https://slack.com/api/chat.postMessage +workflows: + version: 2 + build: + jobs: + - build diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 96ef6b8..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,101 +0,0 @@ -pipeline { - agent { - kubernetes { - inheritFrom "shared" - yamlFile ".jenkins/build-pod.yaml" - } - } - environment { - DOCKER_CONFIG="/root/.docker" - LOCAL_REPOSITORY = "${LOCAL_REGISTRY}/molgenis/website" - CHART_VERSION = '0.5.0' - } - stages { - stage('Retrieve build secrets') { - steps { - container('vault') { - script { - sh "mkdir ${JENKINS_AGENT_WORKDIR}/.rancher" - sh(script: "vault read -field=value secret/ops/jenkins/rancher/cli2.json > ${JENKINS_AGENT_WORKDIR}/.rancher/cli2.json") - env.GITHUB_TOKEN = sh(script: 'vault read -field=value secret/ops/token/github', returnStdout: true) - env.GITHUB_USER = sh(script: 'vault read -field=username secret/ops/token/github', returnStdout: true) - env.NEXUS_AUTH = sh(script: 'vault read -field=base64 secret/ops/account/nexus', returnStdout: true) - env.DOCKERHUB_AUTH = sh(script: 'vault read -field=value secret/gcc/token/dockerhub', returnStdout: true) - } - } - container(name: 'kaniko', shell: '/busybox/sh') { - sh "mkdir -p ${DOCKER_CONFIG}" - sh "set +x && echo '{\"auths\": {\"registry.molgenis.org\": {\"auth\": \"${NEXUS_AUTH}\"}, \"https://index.docker.io/v1/\": {\"auth\": \"${DOCKERHUB_AUTH}\"}}}' > ${DOCKER_CONFIG}/config.json" - } - } - } - stage('Steps [ PR ]') { - when { - changeRequest() - } - environment { - TAG = "PR-${CHANGE_ID}-${BUILD_NUMBER}" - } - stages { - stage('Build [ PR ]') { - steps { - container('jekyll') { - script { - sh "echo version: ${TAG} > _version.yml" - sh 'chown -R jekyll:jekyll $(pwd)' - sh 'jekyll doctor' - sh 'jekyll build --config _version.yml,_config.yml' - } - } - container (name: 'kaniko', shell: '/busybox/sh') { - sh "#!/busybox/sh\n/kaniko/executor --context ${WORKSPACE} --destination ${LOCAL_REPOSITORY}:${TAG}" - } - } - } - stage("Deploy to dev-site [ site.dev.molgenis.org ]") { - steps { - milestone(ordinal: 100, label: 'deploy to site.dev.molgenis.org') - container('rancher') { - sh "rancher context switch dev-molgenis" - sh "rancher apps upgrade --set website.image.tag=${TAG} molgenis-website ${CHART_VERSION}" - } - } - } - } - } - stage('Steps [ master ]') { - when { - branch 'master' - } - environment { - TAG = "$BUILD_NUMBER" - } - stages { - stage('Build [ master ]') { - steps { - container('jekyll') { - script { - sh "echo version: ${TAG} > _version.yml" - sh 'chown -R jekyll:jekyll $(pwd)' - sh 'jekyll doctor' - sh 'jekyll build --config _version.yml,_config.yml' - } - } - container (name: 'kaniko', shell: '/busybox/sh') { - sh "#!/busybox/sh\n/kaniko/executor --context ${WORKSPACE} --destination ${LOCAL_REPOSITORY}:${TAG} --destination ${LOCAL_REPOSITORY}:latest" - } - } - } - stage('Deploy release [ master ]') { - steps { - milestone(ordinal: 200, label: 'deploy to www.molgenis.org') - container('rancher') { - sh "rancher context switch prod-molgenis" - sh "rancher apps upgrade --set website.image.tag=${TAG} website-prod ${CHART_VERSION}" - } - } - } - } - } - } -} diff --git a/README.md b/README.md index c447199..c262a6a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ We produce the website using Jekyl. The master branch is automatically build and can be viewed at http://site.dev.molgenis.org . The admin of the website can then push it into production. - # How to develop Fork this repository and then checkout. On your own machine you should install jekyll. diff --git a/helm-chart/Chart.yaml b/helm-chart/Chart.yaml new file mode 100644 index 0000000..a2d5a3b --- /dev/null +++ b/helm-chart/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: website +version: 0.0.0 +appVersion: "8.x" +icon: https://raw.githubusercontent.com/molgenis/molgenis-ops-helm/master/charts/molgenis/catalogIcon-molgenis.png +description: MOLGENIS website +type: application \ No newline at end of file diff --git a/helm-chart/templates/_helpers.tpl b/helm-chart/templates/_helpers.tpl new file mode 100644 index 0000000..93860a4 --- /dev/null +++ b/helm-chart/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "website.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 "website.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 "website.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "website.labels" -}} +helm.sh/chart: {{ include "website.chart" . }} +{{ include "website.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "website.selectorLabels" -}} +app.kubernetes.io/name: {{ include "website.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "website.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "website.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/helm-chart/templates/deployment.yaml b/helm-chart/templates/deployment.yaml new file mode 100644 index 0000000..d836f56 --- /dev/null +++ b/helm-chart/templates/deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "website.fullname" . }} + labels: + app: {{ template "website.name" . }} + chart: {{ template "website.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "website.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "website.selectorLabels" . | nindent 8 }} + spec: + initContainers: + - name: data-loader + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["sh", "-c", "cp -r /mnt/html-files/. /usr/share/nginx/html"] + volumeMounts: + - name: html-volume + mountPath: /mnt/html-files + containers: + - name: nginx-container + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + ports: + - containerPort: 80 + volumeMounts: + - name: html-volume + mountPath: /usr/share/nginx/html + volumes: + - name: html-volume + persistentVolumeClaim: + claimName: {{ include "website.fullname" . }}-pv diff --git a/helm-chart/templates/ingress.yaml b/helm-chart/templates/ingress.yaml new file mode 100644 index 0000000..cfed5b1 --- /dev/null +++ b/helm-chart/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled }} + {{- $fullName := include "website.fullname" . -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "website.fullname" . }} + labels: + app: {{ template "website.name" . }} + chart: {{ template "website.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/proxy-body-size: "0" + nginx.ingress.kubernetes.io/use-regex: "true" +spec: + tls: + {{- range .Values.ingress.hosts }} + - hosts: + - {{ .host | quote }} + secretName: dev.molgenis.org + + rules: + - host: {{ .host | quote }} + http: + paths: + - path: {{default "/" .path}} + pathType: Prefix + backend: + service: + name: {{$fullName}} + port: + number: 80 + + {{- end }} + {{- end }} diff --git a/helm-chart/templates/pvc.yaml b/helm-chart/templates/pvc.yaml new file mode 100644 index 0000000..0d30620 --- /dev/null +++ b/helm-chart/templates/pvc.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "website.fullname" . }}-pv + labels: + app: {{ template "website.name" . }} + chart: {{ template "website.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1G +status: {} diff --git a/helm-chart/templates/svc.yaml b/helm-chart/templates/svc.yaml new file mode 100644 index 0000000..13149ae --- /dev/null +++ b/helm-chart/templates/svc.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Service + metadata: + name: {{ include "website.fullname" . }} + labels: + app: {{ template "website.name" . }} + chart: {{ template "website.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: 80 + protocol: TCP + selector: + {{- include "website.selectorLabels" . | nindent 8}} + status: + loadBalancer: {} diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml new file mode 100644 index 0000000..5f2b968 --- /dev/null +++ b/helm-chart/values.yaml @@ -0,0 +1,19 @@ +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +adminPassword: admin +image: + repository: "nginx:alpine" + tag: "latest" + pullPolicy: Always + +ingress: + enabled: true + hosts: + - host: www.molgenis.org + path: / + +service: + type: ClusterIP + port: 80 \ No newline at end of file