From 139e57a4769057c45cf686e074d3b315de0cfeb7 Mon Sep 17 00:00:00 2001 From: Mark Pundsack <mpundsack@gitlab.com> Date: Mon, 13 Mar 2017 15:09:21 -0500 Subject: [PATCH 1/5] Create auto-deploy-kubernetes --- Auto-deploy-kubernetes.yml | 250 +++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 Auto-deploy-kubernetes.yml diff --git a/Auto-deploy-kubernetes.yml b/Auto-deploy-kubernetes.yml new file mode 100644 index 0000000..077f2c9 --- /dev/null +++ b/Auto-deploy-kubernetes.yml @@ -0,0 +1,250 @@ +# Explanation on the scripts: +# https://gitlab.com/gitlab-examples/kubernetes-deploy/blob/master/README.md +image: registry.gitlab.com/gitlab-examples/kubernetes-deploy + +variables: + # Application deployment domain + KUBE_DOMAIN: domain.example.com + +stages: + - build + - test + - review + - staging + - production + - cleanup + +# Define some helper functions +.common: &common + | + set -eo pipefail + + [[ "$TRACE" ]] && set -x + + export CI_CONTAINER_NAME="ci_job_build_$CI_BUILD_ID" + export CI_REGISTRY_TAG="$CI_BUILD_REF_NAME" + + create_kubeconfig() { + echo "Generating kubeconfig..." + export KUBECONFIG="$(pwd)/kubeconfig" + export KUBE_CLUSTER_OPTIONS= + if [[ -n "$KUBE_CA_PEM" ]]; then + echo "Using KUBE_CA_PEM..." + echo "$KUBE_CA_PEM" > "$(pwd)/kube.ca.pem" + export KUBE_CLUSTER_OPTIONS=--certificate-authority="$(pwd)/kube.ca.pem" + fi + kubectl config set-cluster gitlab-deploy --server="$KUBE_URL" $KUBE_CLUSTER_OPTIONS + kubectl config set-credentials gitlab-deploy --token="$KUBE_TOKEN" $KUBE_CLUSTER_OPTIONS + kubectl config set-context gitlab-deploy --cluster=gitlab-deploy --user=gitlab-deploy --namespace="$KUBE_NAMESPACE" + kubectl config use-context gitlab-deploy + echo "" + } + + ensure_deploy_variables() { + if [[ -z "$KUBE_URL" ]]; then + echo "Missing KUBE_URL." + exit 1 + fi + + if [[ -z "$KUBE_TOKEN" ]]; then + echo "Missing KUBE_TOKEN." + exit 1 + fi + + if [[ -z "$KUBE_NAMESPACE" ]]; then + echo "Missing KUBE_NAMESPACE." + exit 1 + fi + + if [[ -z "$CI_ENVIRONMENT_SLUG" ]]; then + echo "Missing CI_ENVIRONMENT_SLUG." + exit 1 + fi + + if [[ -z "$CI_ENVIRONMENT_URL" ]]; then + echo "Missing CI_ENVIRONMENT_URL." + exit 1 + fi + } + + ping_kube() { + if kubectl version > /dev/null; then + echo "Kubernetes is online!" + echo "" + else + echo "Cannot connect to Kubernetes." + return 1 + fi + } + +.auto_build: &auto_build + | + echo "Checking docker engine..." + if ! docker info &>/dev/null; then echo "Missing docker engine to build images."; echo "Running docker:dind locally with graph driver pointing to '/cache/docker'" + if ! grep -q overlay /proc/filesystems; then + echo "Missing overlay filesystem. Are you running recent enough kernel?" + exit 1 + fi + if [[ ! -d /cache ]]; then + mkdir -p /cache + mount -t tmpfs tmpfs /cache + fi + dockerd --host=unix:///var/run/docker.sock --storage-driver=overlay --graph=/cache/docker & &>/docker.log + trap 'kill %%' EXIT + + echo "Waiting for docker..." + for i in $(seq 1 60); do + if docker info &> /dev/null; then + break + fi + sleep 1s + done + + if [[ "$i" == 60 ]]; then + echo "Failed to start docker:dind..." + cat /docker.log + exit 1 + fi + echo "" + fi + + docker rm -f "$CI_CONTAINER_NAME" &>/dev/null || true + + echo "Building application..." + + if [[ -f Dockerfile ]]; then + echo "Building Dockerfile-based application..." + # Build Dockerfile + docker build -t "$CI_REGISTRY_IMAGE:$CI_REGISTRY_TAG" . + else + # Build heroku-based application + echo "Building Heroku-based application using gliderlabs/herokuish docker image..." + docker run -i --name="$CI_CONTAINER_NAME" -v "$(pwd):/tmp/app:ro" -v "/cache/herokuish:/tmp/cache" gliderlabs/herokuish /bin/herokuish buildpack build + docker commit "$CI_CONTAINER_NAME" "$CI_REGISTRY_IMAGE:$CI_REGISTRY_TAG" + docker rm "$CI_CONTAINER_NAME" >/dev/null + echo "" + + # Create a start command, start `web` + echo "Configuring $CI_REGISTRY_IMAGE:$CI_REGISTRY_TAG docker image..." + docker create --expose 5000 --env PORT=5000 --name="$CI_CONTAINER_NAME" "$CI_REGISTRY_IMAGE:$CI_REGISTRY_TAG" /bin/herokuish procfile start web + docker commit "$CI_CONTAINER_NAME" "$CI_REGISTRY_IMAGE:$CI_REGISTRY_TAG" + docker rm "$CI_CONTAINER_NAME" >/dev/null + echo "" + fi + + if [[ -n "$CI_BUILD_TOKEN" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY" + echo "" + fi + + echo "Pushing to GitLab Container Registry..." + docker push "$CI_REGISTRY_IMAGE:$CI_REGISTRY_TAG" + echo "" + +.auto_deploy: &auto_deploy + | + CI_ENVIRONMENT_HOSTNAME="${CI_ENVIRONMENT_URL}" + CI_ENVIRONMENT_HOSTNAME="${CI_ENVIRONMENT_HOSTNAME/http:\/\//}" + CI_ENVIRONMENT_HOSTNAME="${CI_ENVIRONMENT_HOSTNAME/https:\/\//}" + + echo ciEnvironmentSlug=$CI_ENVIRONMENT_SLUG,ciPipelineID=\\"$CI_PIPELINE_ID\\",ciBuildID=\\"$CI_BUILD_ID\\",ciEnvironmentHostname=$CI_ENVIRONMENT_HOSTNAME,ciRegistryImage=$CI_REGISTRY_IMAGE,ciRegistryTag=$CI_REGISTRY_TAG + + helm status $CI_PROJECT_NAME-$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG + if [[ $? -ne 0 ]]; then + echo "Creating initial release" + helm install --wait --name $CI_PROJECT_NAME-$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG --namespace $KUBE_NAMESPACE --set ciEnvironmentSlug=$CI_ENVIRONMENT_SLUG,ciPipelineID=\\"$CI_PIPELINE_ID\\",ciBuildID=\\"$CI_BUILD_ID\\",ciEnvironmentHostname=$CI_ENVIRONMENT_HOSTNAME,ciRegistryImage=$CI_REGISTRY_IMAGE,ciRegistryTag=$CI_REGISTRY_TAG gitlab/auto-deploy-app + else + echo "Upgrading release" + helm upgrade --wait $CI_PROJECT_NAME-$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG --namespace $KUBE_NAMESPACE --set ciEnvironmentSlug=$CI_ENVIRONMENT_SLUG,ciPipelineID=\\"$CI_PIPELINE_ID\\",ciBuildID=\\"$CI_BUILD_ID\\",ciEnvironmentHostname=$CI_ENVIRONMENT_HOSTNAME,ciRegistryImage=$CI_REGISTRY_IMAGE,ciRegistryTag=$CI_REGISTRY_TAG gitlab/auto-deploy-app + fi + + echo "Application is accessible at: ${CI_ENVIRONMENT_URL}" + echo "" + +.auto_destroy: &auto_destroy + | + create_kubeconfig + + echo "Removing app..." + helm delete $CI_PROJECT_NAME-$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG + +before_script: + - *common + +build: + stage: build + script: + - *auto_build + only: + - branches + +production: + stage: production + variables: + CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME.$KUBE_DOMAIN + script: + - *auto_deploy + environment: + name: production + url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN + when: manual + only: + - master + +staging: + stage: staging + variables: + CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN + script: + - *auto_deploy + environment: + name: staging + url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN + only: + - master + +review: + stage: review + variables: + CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN + before_script: + - *common + - apk update && apk add curl bash openssl sudo + - curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash + - ensure_deploy_variables + - create_kubeconfig + - helm init --upgrade + - helm repo add gitlab https://charts.gitlab.io + script: + - *auto_deploy + environment: + name: review/$CI_BUILD_REF_SLUG + url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN + on_stop: stop_review + only: + - branches + except: + - master + +stop_review: + stage: cleanup + variables: + GIT_STRATEGY: none + before_script: + - *common + - apk update && apk add curl bash openssl sudo + - curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash + - ensure_deploy_variables + - create_kubeconfig + - helm init --client-only + script: + - *auto_destroy + environment: + name: review/$CI_BUILD_REF_SLUG + action: stop + when: manual + only: + - branches + except: + - master -- GitLab From 928844faec0036e381af5f5346d99e89c559111c Mon Sep 17 00:00:00 2001 From: Mark Pundsack <mpundsack@gitlab.com> Date: Mon, 13 Mar 2017 16:15:14 -0500 Subject: [PATCH 2/5] Refactor CI/CD configuration --- Auto-deploy-kubernetes.yml | 112 ++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 21 deletions(-) diff --git a/Auto-deploy-kubernetes.yml b/Auto-deploy-kubernetes.yml index 077f2c9..7819fd7 100644 --- a/Auto-deploy-kubernetes.yml +++ b/Auto-deploy-kubernetes.yml @@ -1,20 +1,10 @@ # Explanation on the scripts: # https://gitlab.com/gitlab-examples/kubernetes-deploy/blob/master/README.md -image: registry.gitlab.com/gitlab-examples/kubernetes-deploy - -variables: - # Application deployment domain - KUBE_DOMAIN: domain.example.com - -stages: - - build - - test - - review - - staging - - production - - cleanup +############################## # Define some helper functions +############################## + .common: &common | set -eo pipefail @@ -77,6 +67,10 @@ stages: fi } +############################## +# Define auto deploy functions +############################## + .auto_build: &auto_build | echo "Checking docker engine..." @@ -169,17 +163,28 @@ stages: echo "Removing app..." helm delete $CI_PROJECT_NAME-$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG -before_script: - - *common - -build: +############################## +# Define basic job definitions +############################## + +.auto_deploy_kubernetes: &auto_deploy_kubernetes + image: registry.gitlab.com/gitlab-examples/kubernetes-deploy + stages: + - build + - test + - review + - staging + - production + - cleanup + +.build_branches: &build_branches stage: build script: - *auto_build only: - branches -production: +.manual_deploy_to_production: &manual_deploy_to_production stage: production variables: CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME.$KUBE_DOMAIN @@ -192,7 +197,31 @@ production: only: - master -staging: +.auto_deploy_to_production: &manual_deploy_to_production + stage: production + variables: + CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME.$KUBE_DOMAIN + script: + - *auto_deploy + environment: + name: production + url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN + only: + - master + +.auto_deploy_tags_to_production: &manual_deploy_to_production + stage: production + variables: + CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME.$KUBE_DOMAIN + script: + - *auto_deploy + environment: + name: production + url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN + only: + - tags + +.auto_deploy_to_staging: &auto_deploy_to_staging stage: staging variables: CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN @@ -204,7 +233,7 @@ staging: only: - master -review: +.start_review: &start_review stage: review variables: CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN @@ -227,7 +256,7 @@ review: except: - master -stop_review: +.stop_review: &stop_review stage: cleanup variables: GIT_STRATEGY: none @@ -248,3 +277,44 @@ stop_review: - branches except: - master + +############################## +# Define overall pipeline +############################## + +.auto_deploy_kubernetes: &auto_deploy_kubernetes + image: registry.gitlab.com/gitlab-examples/kubernetes-deploy + + stages: + - build + - test + - review + - staging + - production + - cleanup + + before_script: + - *common + + build: + <<: *build_branches + + production: + <<: *manual_deploy_to_production + + staging: + <<: *auto_deploy_to_staging + + review: + <<: *start_review + + stop_review: + <<: *stop_review + +# ----------------------------------------- + +<<: *auto_deploy_kubernetes + +variables: + # Application deployment domain + KUBE_DOMAIN: domain.example.com -- GitLab From cf41b446959df9274c6aff7baf9b44244b6f5ccb Mon Sep 17 00:00:00 2001 From: Mark Pundsack <mpundsack@gitlab.com> Date: Mon, 13 Mar 2017 16:29:17 -0500 Subject: [PATCH 3/5] Refactor --- Auto-deploy-kubernetes.yml | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Auto-deploy-kubernetes.yml b/Auto-deploy-kubernetes.yml index 7819fd7..dd6ae00 100644 --- a/Auto-deploy-kubernetes.yml +++ b/Auto-deploy-kubernetes.yml @@ -167,15 +167,10 @@ # Define basic job definitions ############################## -.auto_deploy_kubernetes: &auto_deploy_kubernetes +.kubernetes-deploy: &kubernetes-deploy image: registry.gitlab.com/gitlab-examples/kubernetes-deploy - stages: - - build - - test - - review - - staging - - production - - cleanup + before_script: + - *common .build_branches: &build_branches stage: build @@ -283,19 +278,15 @@ ############################## .auto_deploy_kubernetes: &auto_deploy_kubernetes - image: registry.gitlab.com/gitlab-examples/kubernetes-deploy + <<: *kubernetes-deploy stages: - build - - test - review - staging - production - cleanup - before_script: - - *common - build: <<: *build_branches -- GitLab From c7d95f72c448af563503d59a0ae187e57e3d8419 Mon Sep 17 00:00:00 2001 From: Mark Pundsack <mpundsack@gitlab.com> Date: Mon, 13 Mar 2017 16:49:26 -0500 Subject: [PATCH 4/5] Small fixes --- Auto-deploy-kubernetes.yml | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Auto-deploy-kubernetes.yml b/Auto-deploy-kubernetes.yml index dd6ae00..0ee597f 100644 --- a/Auto-deploy-kubernetes.yml +++ b/Auto-deploy-kubernetes.yml @@ -1,6 +1,3 @@ -# Explanation on the scripts: -# https://gitlab.com/gitlab-examples/kubernetes-deploy/blob/master/README.md - ############################## # Define some helper functions ############################## @@ -167,11 +164,16 @@ # Define basic job definitions ############################## -.kubernetes-deploy: &kubernetes-deploy +.auto_deploy_image: &auto_deploy_image image: registry.gitlab.com/gitlab-examples/kubernetes-deploy before_script: - *common +# .openshift-deploy: &openshift-deploy +# image: registry.gitlab.com/gitlab-examples/openshift-deploy +# before_script: +# - *common + .build_branches: &build_branches stage: build script: @@ -277,8 +279,8 @@ # Define overall pipeline ############################## -.auto_deploy_kubernetes: &auto_deploy_kubernetes - <<: *kubernetes-deploy +.auto_deploy: &auto_deploy + <<: *auto_deploy_image stages: - build @@ -290,6 +292,10 @@ build: <<: *build_branches + # Choose between: + # *manual_deploy_to_production + # *auto_deploy_to_production + # *auto_deploy_tags_to_production production: <<: *manual_deploy_to_production @@ -302,9 +308,11 @@ stop_review: <<: *stop_review -# ----------------------------------------- +############################## +# Project's `.gitlab-ci.yml` +############################## -<<: *auto_deploy_kubernetes +<<: *auto_deploy variables: # Application deployment domain -- GitLab From 74c3397fa251fbeb750b9c6e6f130127544a8761 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" <git@zjvandeweg.nl> Date: Tue, 14 Mar 2017 08:05:58 +0100 Subject: [PATCH 5/5] Improve fail message for test --- verify_templates.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/verify_templates.rb b/verify_templates.rb index 63e6527..ba0f0df 100644 --- a/verify_templates.rb +++ b/verify_templates.rb @@ -6,7 +6,13 @@ uri = URI.parse 'https://gitlab.com/api/v3/ci/lint' Dir.glob("#{File.dirname(__FILE__)}/**/*.yml").each do |file| response = Net::HTTP.post_form(uri, content: File.read(file)) - file = file.match(/((\w|\+|#)+)\.gitlab-ci/)[1] + match = file.match(/(?<file>(\w|\+|#)+)\.gitlab-ci.yml/) + template_name = match ? match[:file] : nil + + unless template_name + puts "Invalid file format for #{file}" + exit(1) + end if JSON.parse(response.body)['status'] == 'valid' puts "\e[32mvalid\e[0m: #{file}" # Color 'valid' green @@ -17,5 +23,6 @@ Dir.glob("#{File.dirname(__FILE__)}/**/*.yml").each do |file| end # Given we test all the templates, the coverage is 100%, always. To showcase -# how this is done, we print it here. -puts "Coverage: 100%" \ No newline at end of file +# how this is done, we print it here. The regex to parse this would be: +# /Coverage:\s(d+)%/ +puts "Coverage: 100%" -- GitLab