Skip to content

GitLab CI template for GNU Make

This project implements a GitLab CI/CD template for GNU Make.

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/make/gitlab-ci-make@1.4.1
    # 2: set/override component inputs
    inputs:
      image: "image-with-my-build-tools:latest" # ⚠ 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/make'
    ref: '1.4.1'
    file: '/templates/gitlab-ci-make.yml'

variables:
  # 2: set/override template variables
  MAKE_IMAGE: "image-with-my-build-tools:latest" # ⚠ this is only an example

Global configuration

The GNU Make template uses some global configuration used throughout all jobs.

Input / Variable Description Default value
image / MAKE_IMAGE The Docker image used to run GNU Make
⚠ set the image required by your project (see next chapter)
registry.hub.docker.com/alpinelinux/build-base
project-dir / MAKE_PROJECT_DIR The root directory of the Makefile project. .

Which image?

On the contrary to other to-be-continuous templates, the GNU Make template doesn't target any technology / build tool in particular. It only assumes you're using GNU Make as a low-level abstraction to build your project. As a consequence, you will have to use a Docker image that contains all tools required to build & test your project.

The image shall also contain make itself. Otherwise the template takes care of installing it automatically, but this is far from ideal as it will be installed over and over again each time a job is executed.

Cache management

The Make template implements a default cache strategy associated to the .cache/ local folder. So if you need to manage a cache (for installed plugins, dependencies or else), make your best to install those artifacts into the .cache/ directory. This way the default policy will work seamlessly.

Otherwise, you'll have to override the default cache strategy as follows:

.make-base:
  cache:
    # override the cache path
    paths:
      - .my-cache/
      - .xyz/

make-build job

This job is expected to perform build and if possible unit tests all at once.

It uses the following variable:

Input / Variable Description Default value
build-args / MAKE_BUILD_ARGS Make options and goals for the build & test job all test

Build Output

The make-build job is supposed to build the project. Consequently, it will produce binary/executable artifacts, that should be stored as job artifacts.

By default, build/ is defined as the build output directory. If it is not the case in your project, you'll have to override default as follows:

make-build:
  artifacts:
    paths:
      # use 'bin/' as custom binaries output
      - bin/
      # keep default 'reports/' artifacts
      - reports/

Unit Tests

As a good practice, it is often better to run build & unit tests all at once instead of into two separate jobs. Nonetheless if you feel you have good reasons not doing so, you're obviously free to do differently.

If you decide to implement unit tests in this job, here are (optional) requirements to improve your GitLab integration:

Unit Test reports integration

If the unit testing framework you're using is capable of producing JUnit reports, you'll take great benefits from implementing the GitLab integration. Altough you're free to generate the reports wherever you like, to-be-continuous uses a convention to produce them in reports/<tool_name>-test.xunit.xml.

You'll need to declare the reports in your .gitlab-ci.yaml as follows:

make-build:
  artifacts:
    reports:
      # declare the JUnit report
      junit: "reports/xyz-test.xunit.xml"

Code Coverage integration

If the unit testing framework you're using is capable of computing code coverage, you'll take great benefits from implementing one or both of the GitLab integrations:

  1. test coverage results in merge requests
    let GitLab capture the global coverage result (percentage) from the output logs by defining a regular expression with the coverage keyword
  2. Cobertura XML report integration
    provide GitLab with a detailed Cobertura XML report
    Altough you're free to generate the reports wherever you like, to-be-continuous uses a convention to produce them in reports/<tool_name>-coverage.cobertura.xml

Here is what you'll need to declare in your .gitlab-ci.yaml:

make-build:
  # declare the global coverage result pattern
  coverage: '/^Coverage computed by XYZ: (\d+.\d+\%)$/'
  artifacts:
    reports:
      # declare the Cobertura XML report
      coverage_report:
        coverage_format: cobertura
        path: "reports/xyz-coverage.cobertura.xml"

Additional custom jobs

The Make template comes with one single job (make-build) by default. But it is highly probable (and desirable) that you'll need to add other jobs in your CI pipeline (linters, dependency checks, security scanners, ...).

Those additional jobs will have to be partially declared, inherited from the root hidden .make-base job.

Here is an example for a fictive my lint job:

make-my-lint:
  # inherit from base job
  extends: .make-base
  # select the most appropriate stage (build or test)
  stage: test
  script:
    # TODO: execute the right goal(s)
    - mkdir -p -m 777 reports
    - make my-lint
  # capture report(s) as an artifact (if required)
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    when: always
    paths:
      - "reports/my-lint.*"
    # also declare any GitLab supported report if need be
    # see: https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html
  rules:
    # /!\ reference .test-policy rules to implement adaptive pipeline workflow
    - !reference [.test-policy, rules]