Example how this project: deployctl is Continious and automatic released with Gitlab and deployctl.

CI/CD model

The build-stage compiles the code into executables, we only need the sripts and readme.md, so we copy to the output directory.

For every commit on Gitlab, output will be generate and available for in the review/branchname or master, except on a tag commit of the master.

On a tag commit of the master, the pipeline will generate a staging environment, which can then manually be deployed to the download.deployctl.com

A release badge is generated by deployctl on a tag-build in the production environment, when the tag does not contain the following words, case-insensitive: “BETA”,”TEST”,”RC”,”PRC”,”ALPHA”.

release

coded in Markdown, with a link to latest release download page, as:

[![release](http://downloads.deployctl.com/tag.svg)](http://downloads.deployctl.com)

Building this project is through the Gitlab CI/CD, by defineing the gitlab-ci.yml file. Find below a view of the pipeline:

.gitlab-ci.yml

All files to be included in the release page are copied to the output-directory and which are uploaded as artifacts after each job to Gitlab.

At the review/staging/production, all files should be in the output-directory, which are then moved to the release directory by the script.

The deploy release command, handles moving the data in the right place according to the:

   #Deployment locations
  DEPLOY_RELEASE_PATH: |-
                       [
                       "output/",
                       "output/rpm/",
                       "output/dist/"
                       ]

On a production release, depending on DEPLOY_CONFIG_HTTPS: "True", acme.sh will create an certificate for the site if one wasn’t already availleble, so our site becomes an https-site. See https:// downloads.deployctl.com for the result of the production environment.

Below we will go step by step through the .gitlab-ci.yml-file for the deployctl project:

Defining the stages

stages:
  - build
  - test
  - packaging
  - review
  - staging
  - production

Defining the variables for deployment

variables:
  CI_PROJECT_PATH_SLUG: "deployctl-deployctl"
  DEPLOY_DOMAIN_APP: "gioxapp.com"
  #
  # Prodduction deployment url and https
  DEPLOY_DOMAIN: "downloads.deployctl.com"
  DEPLOY_CONFIG_HTTPS: "True"
  #
   #Deployment locations
  DEPLOY_RELEASE_PATH: |-
                       [
                       "output/",
                       "output/rpm/",
                       "output/dist/"
                       ]
  #
  # Extra links for release page, besides the <*.url> files
  DEPLOY_hrefs: |-
                [
                "repository": "$DEPLOY_REPO_URL",
                "website": "http://www.deployctl.com"
                ]
  #
  # location directory of rpm/deb dir
  DEPLOY_REPO_PATH: "output"
  #
  # depending on master or production, define the repository url
  PRODUCTION_REPO_URL: "https://repo.deployctl.com"
  MASTER_REPO_URL: "https://repo-bleeding.deployctl.com"
  • CI_PROJECT_PATH_SLUG mandatory slug of PROJECT_PATH (name with namespace)
  • DEPLOY_DOMAIN_APP : on which domain we’ll deploy the:
    • review/
      • master
      • staging
  • DEPLOY_DOMAIN: where we deploy the production environment
  • DEPLOY_CONFIG_HTTPS: configure https for a production environment
  • DEPLOY_RELEASE_PATH: ‘[“output/”,”output/rpm/”,”output/dist/”]’

Building the project and distro

build:
  stage: build
  script:
    - ./autogen.sh
    - ./configure
    - make -j$(nproc)
    - cp scripts/*.sh output/
    - cp scripts/*.md output/
    - |
       echo -e "$(git describe --tags --always --abbrev=8)" >
       .GIT_VERSION
  artifacts:
    paths:
      - output/
      - .GIT_VERSION
  tags:
  - centos7

build_dist:
  stage: build
  script:
    - ./autogen.sh
    - ./configure
    - make dist
    - mv deployctl*.tar.gz output/
  artifacts:
    paths:
      - output/
  tags:
  - centos7

Both builds do a checkout from Gitlab project, and places the desired output in output-directory.

  • Build provides the scripts for setup, README.md and the .GIT_VERSION, for use by deployctl.
  • build_dist provides the distro as a .tar.gz -file.

Do the coverage testing

coverage:
  stage: test
  dependencies: []
  script:
    - ./docov
    - rm -rf output && mkdir output
    - mv  tests/deployctl-coverage output/
    - cp tests/coverage.url output/coverage.url
  artifacts:
    when: always
    paths:
      - output
  tags:
    - centos7
  • dependencies: [] : will not download artifacts from previous stages, and speeds up the job.
  • the build provides us a file coverage.url which will turn into a link, with content e.g. deployctl-coverage, 98.9% into a link on the Releases page:
    • with name coverage (filename without .url extension)
    • and hreflink of /deployctl-coverage
    • and a metric-value of 98.9%
    • Remark: metric is optional, if no , in content, no metric will be shown.

packaging into an rpm

rpm:
  stage: packaging
  variables:
    GIT_STRATEGY: none
  script:
  - rm -rf rpmbuild
   - mkdir -pv rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp}
   - cp -v output/dist/deployctl-*.tar.gz rpmbuild/SOURCES/
   - |
     tar -vxzf output/dist/deployctl-*.tar.gz
         deployctl*/distro/rpm/deployctl.spec
         --strip-components=3
   - rm -rf output
   - mkdir -pv output/rpm
   - mv deployctl.spec rpmbuild/SPECS
   - |
     rpmbuild
       --define "_topdir $(pwd)/rpmbuild"
       -ba rpmbuild/SPECS/deployctl.spec
   - cp -v rpmbuild/RPMS/x86_64/* output/rpm/
   - rm -rf rpmbuild
  artifacts:
      paths:
        - output
  tags:
    - centos7
  • GIT_STRATEGY: none => no git checkout
  • so the deployctl-*.tar.gz comes from the distbuild,through the artifacts.

Remark GIT_STRATEGY: none on a shell runner is a bit tricky as previous build info can be present, so we delete and remake the output-directory before copy the rpm.

Review environment:

reviewb:
  stage: review
  variables:
    GIT_STRATEGY: none
  script:
    - deployctl release
  environment:
    name: review/$CI_BUILD_REF_NAME
    url: |-
         http://
         ${CI_ENVIRONMENT_SLUG}.
         ${CI_PROJECT_PATH_SLUG}.
         ${DEPLOY_DOMAIN_APP}
    on_stop: stop_reviewb
  only:
    - branches
  except:
    - tags
    - master
  tags:
   - deployctl-gioxapp.com

stop_reviewb:
  stage: review
  dependencies: []
  script:
    - deployctl delete
  variables:
    GIT_STRATEGY: none
  when: manual
  environment:
    name: review/$CI_BUILD_REF_NAME
    action: stop
  only:
    - branches
  except:
    - tags
    - master
  tags:
    - deployctl-gioxapp.com

On a branch commit, a review environment is created. this can be found on http://$CI_ENVIRONMENT_SLUG.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP

The stop review allow the review to be deleted, manual or when branch is deleted.

master environment

reviewm:
  stage: review
  variables:
    GIT_STRATEGY: none
    # define repository url for master
    DEPLOY_REPO_URL: $MASTER_REPO_URL
  script:
    - deployctl release
    - deployctl repo_add
  environment:
    name: master
    url: |-
         http://
         $CI_ENVIRONMENT_SLUG.
         $CI_PROJECT_PATH_SLUG.
         $DEPLOY_DOMAIN_APP
    on_stop: stop_reviewm
  only:
    - master
  except:
    - tags
  tags:
    - deployctl-gioxapp.com

stop_reviewm:
  stage: review
  dependencies: []
  script:
    - deployctl delete
  variables:
    GIT_STRATEGY: none
  when: manual
  environment:
    name: master
    action: stop
  only:
    - master
  except:
    - tags
  tags:
    - deployctl-gioxapp.com

Same as Review, but creates a master environment, meaning all commits to the master will have a master for review. Besides that, a deployment is also made to a bleeding edge repository

staging environment

Release_Staging:
  stage: staging
  environment:
    name: staging
    url: |-
         http://staging.
         $CI_PROJECT_PATH_SLUG.
         $DEPLOY_DOMAIN_APP
  variables:
    GIT_STRATEGY: none
  script:
    - deployctl release
  only:
    - tags
  except:
    - branches
  tags:
    - deployctl-gioxapp.com

On creation of a new tag of the master branch, a staging environment is created. Ready for review at http://staging.$CI_PROJECT_PATH_SLUG.$DEPLOY_DOMAIN_APP

Production environment

Release_production:
  stage: production
  variables:
    GIT_STRATEGY: none
  environment:
    name: production
    url: http://$DEPLOY_DOMAIN/$CI_BUILD_REF_SLUG
  script:
    - deployctl release
  only:
  - tags
  except:
  - branches
  tags:
    - deployctl-gioxapp.com
  when: manual

The deployctl release creates and update the following:

Here we take the example of a tag-release 0.3.0

And on a clean tag, a tag not containing the words BETA,TEST,RC,PRC or ALPHA:

With DEPLOY_CONFIG_HTTPS set, it will make the production, and only production environment available on https, with a redirect of http to https. To do that if no certificate is available for the domain-name, deployctl will have acme.sh create a new letsencrypt certificate.

Also, on install of deployctl, a crontab-job was created to automatically update the certificates.

REMARK

Release info is only availleble for public projects, see Gitlab-issue #29566