GitLab CI/CD Script Improvement

Viewed 192

Below is my first gitlab-ci.yml script for a static website. It does exactly what I need. It does not require a build process per Angular or React. Does anyone see room for improvement? Any glaring newbie mistakes? Are the exit commands necessary or will it automatically log off when the script terminates? Also, is it necessary to remove the deployment keys at the end of each deployment section?

  - build
  - deploy_staging
  - deploy_production

build:
  image: alpine
  stage: build
  before_script:
    - apk add zip
  script:  
    - zip -r website.zip * -x "composer.json" -x "composer.lock" -x "gruntfile.js" -x "package-lock.json" -x "package.json" -x "Read Me" -x "_/" -x "deploy_production.sh" -x "deploy_staging.sh" -x "README.md" -x "Read Me Custom.txt" -x "gitlab-ci.yml"
  artifacts:
    paths:
     - website.zip

deploy_to_staging:
  image: alpine
  stage: deploy_staging
  before_script:
  - apk add unzip openssh-client
  - eval $(ssh-agent -s)
  - echo "$DEPLOYMENT_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - ssh-keyscan -H "$DEPLOYMENT_SERVER" >> ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts
  script:
    - scp website.zip "$DEPLOYMENT_LOGIN":"$DEPLOYMENT_PATH"
    - ssh -p 2222 "$DEPLOYMENT_LOGIN" "
      cd temp;
      rm website.zip;
      cd ../staging;
      bash -O extglob -c 'rm -rf !(website.zip)';
      unzip website.zip;
      "cp website.zip ../../temp/";
      rm website.zip;
      exit; "
      rm -f ~/.ssh/id_rsa
  only:
    - main

deploy_to_production:
  image: alpine
  stage: deploy_production
  before_script:
    - apk add unzip openssh-client
    - eval $(ssh-agent -s)
    - echo "$DEPLOYMENT_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan -H "$DEPLOYMENT_SERVER" >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - ssh -p 2222 "$DEPLOYMENT_LOGIN" "
      cp temp/website.zip portal/;
      cd portal;
      bash -O extglob -c 'rm -rf !(website.zip)';
      unzip website.zip;
      rm website.zip;
      exit; "
      rm -f ~/.ssh/id_rsa
  when: manual
  only:
    - main
1 Answers

The scripts looks pretty straight forward, and it does what it should do. But there are some things you should consider.

  1. you rely on the fact that NO deployment pipeline is run before you execute your life deployment. But theoretically there is the chance, that the zip on the server in the temp folder is not coming from the same pipeline. When eg. Another pipeline executed the staging call already. This way you would deploy the newer package, although you execute the old pipeline. Hence that i recommend to upload again, for safety.

  2. your script contains some duplication, which results in errors, when you need to adapt those duplicated code. I added an example of inheritance for you.

  3. Use environments. GitLab has a pretty nice feature called environments, where you have an overview of existing environments and what is deployed to which environment, by which pipeline. https://docs.gitlab.com/ee/ci/yaml/#environment

  4. Use resourcegroups to prevent parallel job executions to the same environment. https://docs.gitlab.com/ee/ci/yaml/#resource_group

  5. Additionally something to consider on a later stage is adding real releases and tagging to your project - but this is an own topic overall :)

Disclaimer: i am not a pro either, but those are the changes and considerations i would take into account :)

stages:
  - build
  - deploy_staging
  - deploy_production

build:
  image: alpine
  stage: build
  before_script:
    - apk add zip
  script:  
    - zip -r website.zip * -x "composer.json" -x "composer.lock" -x "gruntfile.js" -x "package-lock.json" -x "package.json" -x "Read Me" -x "_/" -x "deploy_production.sh" -x "deploy_staging.sh" -x "README.md" -x "Read Me Custom.txt" -x "gitlab-ci.yml"
  artifacts:
    paths:
     - website.zip

.deploy:
  image: alpine
  before_script:
  - apk add unzip openssh-client
  - eval $(ssh-agent -s)
  - echo "$DEPLOYMENT_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - ssh-keyscan -H "$DEPLOYMENT_SERVER" >> ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts
  script:
    - scp website.zip "$DEPLOYMENT_LOGIN":"$DEPLOYMENT_PATH"
    - ssh -p 2222 "$DEPLOYMENT_LOGIN" "
      cd $DEPLOYMENT_PATH;
      bash -O extglob -c 'rm -rf !(website.zip)';
      unzip website.zip;
      rm website.zip;
      exit; "
  after_script:
  - rm -f ~/.ssh/id_rsa
  only:
    - main

deploy_to_staging:
  stage: deploy_staging
  variables:
    DEPLOYMENT_PATH: "../staging"
  extends: .deploy # inheritance to reduce duplicated code
  environment: 
    name: staging
  resource_group: staging

deploy_to_production:
  stage: deploy_production
  variables:
    DEPLOYMENT_PATH: "portal"
  extends: .deploy # inheritance to reduce duplicated code
  environment: 
    name: production
  resource_group: production
  when: manual
Related