Skip to content

GitLab CI template for bash script validation

This project implements a GitLab CI/CD template to test and analyse your shell code.

Usage

This template can be used both as a CI/CD component or using the legacy include:project syntax.

Use as a CI/CD component

Add the following to your .gitlab-ci.yml:

include:
  # 1: include the component
  - component: $CI_SERVER_FQDN/to-be-continuous/bash/gitlab-ci-bash@3.7.0
    # 2: set/override component inputs
    inputs:
      bats-enabled: true # ⚠ this is only an example

Use as a CI/CD template (legacy)

Add the following to your .gitlab-ci.yml:

include:
  # 1: include the template
  - project: 'to-be-continuous/bash'
    ref: '3.7.0'
    file: '/templates/gitlab-ci-bash.yml'

variables:
  # 2: set/override template variables
  BASH_BATS_ENABLED: "true" # ⚠ this is only an example

Jobs

bash-shellcheck job

This job performs a static analysis of your shell scripts using ShellCheck.

Input / Variable Description Default value
shellcheck-disabled / BASH_SHELLCHECK_DISABLED Set to true to disable ShellCheck none (enabled)
shellcheck-image / BASH_SHELLCHECK_IMAGE The Docker image used to run ShellCheck docker.io/koalaman/shellcheck-alpine:stable
Trivy Badge
shellcheck-files / BASH_SHELLCHECK_FILES Shell file(s) or pattern(s) to analyse **/*.sh
shellcheck-opts / BASH_SHELLCHECK_OPTS ShellCheck options none

bash-bats job

This job performs unit tests based on Bats (Bash Automated Testing System).

The job uses the following variables:

Input / Variable Description Default value
bats-enabled / BASH_BATS_ENABLED Set to true to enable bats tests none (disabled)
bats-image / BASH_BATS_IMAGE The Docker image used to run Bats docker.io/bats/bats:latest
Trivy Badge
bats-tests / BASH_BATS_TESTS The path to a Bats test file, or the path to a directory containing Bats test files tests
bats-opts / BASH_BATS_OPTS Bats options none
bats-libraries / BASH_BATS_LIBRARIES Coma separated list of Bats libraries and add-ons (formatted as lib_name_1@archive_url_1 lib_name_2@archive_url_2 ...) none
coverage-enabled / BASH_COVERAGE_ENABLED Set to true to enable coverage measurement. Using Bashcov false
coverage-formatters / BASH_COVERAGE_FORMATTERS Comma separated list of coverage report formatters and optional library/package name. Formatted as: package-name1@formatter-class1, package-name2@formatter-class2 ... SimpleCov::Formatter::SimpleFormatter
coverage-track-files / BASH_COVERAGE_TRACK_FILES Glob pattern of files to track coverage **/*.sh
coverage-filters / BASH_COVERAGE_FILTERS Comma separated list of files and directories to filter out from your coverage data (e.g. 'tests/*, .tools' ). none

In addition to a textual report in the console, this job produces the following reports, kept for one day:

Report Format Usage
reports/*.bats.xml xUnit test report(s) GitLab integration
reports/bash-coverage.cobertura.xml cobertura code coverage report Gitlab integration

How to manage libraries and add-ons

The Docker image used only contains bats-core. If you wish to used Bats libraries and add-ons, you have two options:

  1. either use the Git submodule technique whenever possible,
  2. or configure the list of libraries to load prior to running tests with the BASH_BATS_LIBRARIES variable. The loaded libraries will then be available in $BATS_LIBRARIES_DIR/$lib_name.

Example of a project using bats-support and bats-assert:

  • BASH_BATS_LIBRARIES: "bats-support@https://github.com/bats-core/bats-support/archive/v0.3.0.zip bats-assert@https://github.com/bats-core/bats-assert/archive/v2.0.0.zip"
  • in test scripts, libraries can be loaded as follows:
    #!/usr/bin/env bats
    load "$BATS_LIBRARIES_DIR/bats-support/load.bash"
    load "$BATS_LIBRARIES_DIR/bats-assert/load.bash"
    
    @test "test something" {
        run echo "Hello there"
        assert_line "Hello there"
    }
    

Manage your own coverage configuration

Code coverage with Bats is based on BashCov which is a wrapper around SimpleCov for Bash.

In order to access advanced configuration features (for example quality gate with minimum line/branch coverage, maximum coverage drop or else) all you have to do is to commit your own .simplecov configuration to the root of your Git repository. Doing so, be aware that the template implementation expects some configuration to be set. Here is a basic .simplecov that you may use as a starting point to build your own:

# /!\ MANDATORY for using bashcov and to-be-continuous
require 'simplecov'
require 'simplecov-cobertura'
# import additional libraries / plugins here (e.g. 'simplecov-csv')

SimpleCov.start do
  # /!\ MANDATORY for to-be-continuous
  coverage_dir 'reports'
  # Can be customized
  track_files '**/*.sh'
  # Can be customized with your own formatters
  # /!\ CoberturaFormatter is MANDATORY for the gitlab reporting of to-be-continuous
  formatter SimpleCov::Formatter::MultiFormatter.new([
    SimpleCov::Formatter::SimpleFormatter,
    SimpleCov::Formatter::CoberturaFormatter
  ])
  # >> Here you can add your extra options <<
end

Extra options can be:

Conditional Configuration

You may implement conditional configuration whether you're using SimpleCov locally or in GitLab CI/CD based on the presence of the $CI variable:

SimpleCov.start do
  ...
  if ENV['CI']
    formatter SimpleCov::Formatter::MultiFormatter.new([
      # /!\ CoberturaFormatter is mandatory for the GitLab coverage reporting
      SimpleCov::Formatter::CoberturaFormatter,
      SimpleCov::Formatter::SimpleFormatter
    ])
  else
    # locally generate html report
    formatter SimpleCov::Formatter::HTMLFormatter
  end
  ...
end