Goals

  • Learn about how GitLab's CI/CD works
  • Learn the different stages
  • Understand how jobs are executed


Settings

  • Repository specification that you can customise and manage.
  • CI/CD section:  configure and customise your continuous integration/continuous delivery channel options.
  • Variables: Store information, like passwords and secret keys, that you can use in job scripts
    • Protected: Only exposed to protected branches or protected tags.
    • Masked: Hidden in job logs. Must match masking requirements.
    • Expanded: Variables with $ will be treated as the start of a reference to another variable

Stages

  • Defines the stages of the project construction and deployment process.
  • Each stage represents a specific phase of the workflow, and jobs are grouped into these stages
  • Indicate the order in which they should be executed.
  • Other stages can be created if necessary
.gitlab-ci.yml
stages:
  - build
  - push
  - deploy


Variables

  • used to configure the behaviour of the tools and services used in the CI/CD process.
variables:
  MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"


Build

  • Uses a Maven-based Docker image to compile the Maven project. 
  • The .m2/repository directory is cached to avoid unnecessary downloads of Maven dependencies.
  • After compilation, a WAR file is created as an artifact and stored for later use.
.gitlab-ci.yml
# Build the Maven project.
build-magnolia:
  image: maven:3.6-jdk-11-slim
  stage: build
  cache:
    key: "$CI_JOB_NAME"
    paths:
      - $CI_PROJECT_DIR/.m2/repository
  before_script:
    - mkdir -p $CI_PROJECT_DIR/.m2
  script:
    - mvn $MAVEN_CLI_OPTS package
    - ls -Fahl paas-training-webapp/target
  artifacts:
    expire_in: 30 days
    paths:
      - paas-training-webapp/target/*.war


Push

  • Creates a Docker image based on the artifacts generated in the build stage.
  • Kaniko is used to build and push the image to the GitLab Container Registry.
  • Docker credentials are configured to access the registry.

.gitlab-ci.yml
# Build docker images based on artifacts from the build stage.
push-docker-image:
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  stage: push
  dependencies:
    - build-magnolia
  before_script:
    - export WEBAPP_IMAGE=${CI_REGISTRY_IMAGE}/magnolia-webapp
    - export GIT_TAG=$CI_COMMIT_SHORT_SHA
    - mkdir -p /kaniko/.docker
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
  script:
    - cd paas-training-webapp
    - /kaniko/executor --context . --dockerfile ./Dockerfile --destination "$WEBAPP_IMAGE:$GIT_TAG"



Deploy

  • Two jobs, deploy-dev, and deploy-uat, deploy the application to different environments
  • The jobs use a values.yml file to generate the necessary configuration before using Helm to deploy the application to a Kubernetes cluster
  • Namespace annotation and creation of secrets are performed.
.gitlab-ci.yml
.deploy:
  image: registry.gitlab.com/mironet/helm-kubectl-gomplate:v0.0.5
  stage: deploy
  before_script:
    - export GIT_TAG=$CI_COMMIT_SHORT_SHA
    - helm repo add mironet https://charts.mirohost.ch/
    - export HELM_CHART_VERSION=1.7.0
    - export KUBECONFIG=$KUBE_CONFIG

deploy-dev:
  extends: .deploy
  script:
    - export DEPLOYMENT=dev
    - export LE_ENVIRONMENT=letsencrypt-prod
    - cat values.yml | gomplate > ${DEPLOYMENT}.yml
    - cat ${DEPLOYMENT}.yml
    - helm upgrade -i ${DEPLOYMENT} mironet/magnolia-helm --version ${HELM_CHART_VERSION} -f ${DEPLOYMENT}.yml --create-namespace -n ${DEPLOYMENT}
    - kubectl annotate --overwrite namespace ${DEPLOYMENT} field.cattle.io/projectId=`kubectl get namespace default --output="jsonpath={.metadata.annotations.field\.cattle\.io/projectId}"`
    - kubectl -n default get secret activation-key -o json | jq 'del(.metadata.annotations,.metadata.labels,.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.namespace,.metadata.creationTimestamp)' | kubectl apply -n ${DEPLOYMENT}  -f -
    - kubectl -n default get secret gitlab -o json | jq 'del(.metadata.annotations,.metadata.labels,.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.namespace,.metadata.creationTimestamp)' | kubectl apply -n ${DEPLOYMENT}  -f -
    - kubectl -n default get secret s3-backup-key -o json | jq 'del(.metadata.annotations,.metadata.labels,.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.namespace,.metadata.creationTimestamp)' | kubectl apply -n ${DEPLOYMENT}  -f -
  environment:
    name: dev
  when: manual

deploy-uat:
  extends: .deploy
  script:
    - export DEPLOYMENT=uat
    - export LE_ENVIRONMENT=letsencrypt-prod
    - cat values.yml | gomplate > ${DEPLOYMENT}.yml
    - cat ${DEPLOYMENT}.yml
    - helm upgrade -i ${DEPLOYMENT} mironet/magnolia-helm --version ${HELM_CHART_VERSION} -f ${DEPLOYMENT}.yml --create-namespace -n ${DEPLOYMENT}
    - kubectl annotate --overwrite namespace ${DEPLOYMENT} field.cattle.io/projectId=`kubectl get namespace default --output="jsonpath={.metadata.annotations.field\.cattle\.io/projectId}"`
    - kubectl -n default get secret activation-key -o json | jq 'del(.metadata.annotations,.metadata.labels,.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.namespace,.metadata.creationTimestamp)' | kubectl apply -n ${DEPLOYMENT}  -f -
    - kubectl -n default get secret gitlab -o json | jq 'del(.metadata.annotations,.metadata.labels,.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.namespace,.metadata.creationTimestamp)' | kubectl apply -n ${DEPLOYMENT}  -f -
    - kubectl -n default get secret s3-backup-key -o json | jq 'del(.metadata.annotations,.metadata.labels,.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.namespace,.metadata.creationTimestamp)' | kubectl apply -n ${DEPLOYMENT}  -f -
  environment:
    name: dev
  when: manual


 Jobs

  • Through the CI/CD option in the pipelines section, we can visualise the different Jobs
  • You can run the pipeline manually
  • The stages are defined in the gitlab-ci.yml
  • Status can be:
    • passed
    • passed with warnings
    • canceled
    • running
    • failed
  • Jobs are executed in the defined order and will wait for a manual action when it reach the deploy stage.

Troubleshoot the jobs

  • In case a pipeline has a failure or you want to check the status of what it is doing, it is possible to do troubleshooting on it.

  • By clicking on the stage job it is possible to see a log of the actions that have been performed and the reason why it failed.


  • No labels