DEV Community

Mohammed Ammer
Mohammed Ammer

Posted on

YAML Buildpack: Auto Validate Configuration Repositories

Git is one of the most common buckets to manage systems/services configurations, which is obvious due to the benefits brought with Git (for example, tracking changes and rolling back).

In my company, we use Git to have a remote configuration for our services and tools. There are over 700 configuration repositories ๐Ÿš€

Keeping in mind that:

Configuration changes are error-prone. Making sure any change in configuration doesnโ€™t break the system is important to avoid critical incidents[1].

So:

As a User, I want to make sure that my changes are in the correct format, so I avoid having system troubles due to wrong configuration files.

CI/CD can be used to apply any kind of checks before merging the change to the *main *branch, however, it comes to a cost to introducing an Action or GitLab-CI (depending on the tool that you use) to make it happen. The big cost here is that you want to update every repository to have the proper CI definitions for that.

YAML Validator

Recently, we migrated from BitBucket to GitLab. In BitBucket, we were using YAML Validator Pre-Receive hook[2] which was doing the job but unfortunately, there is no easy way to have a similar in GitLab.

Alternatives in GitLab

  • ๐Ÿ‘Ž Global server-hook (It is not easy to manage in a Docker container of GitLab Server)

  • ๐Ÿ‘Ž Client side commit hooks (Not practical)

  • ๐Ÿ‘Ž Validation Job through .gitlab-ci.yml to be introduced in every repository (High cost to introduce it for that many configuration repositories, besides requiring config repositories to maintain)

  • ๐Ÿ‘ Auto DevOps! (Centralized setup and easy to maintain ๐Ÿ˜Ž)

GitLab Auto DevOps

GitLab Auto DevOps[4] was a good candidate to be used to solve the problem as it doesnโ€™t require to do any changes to the configuration repositories.

GitLab Auto DevOps is a collection of pre-configured features and integrations that work together to support your software delivery process.

GitLab DevOps is based on buildpacks[5]:

A Buildpack is a set of executables that inspects your app source code and creates a plan to build and run your application.

The existing Buildpacks donโ€™t have a YAML validator in between, hence the default GitLab DevOps doesnโ€™t fit automatically without some customizations[6]

Auto Test: YAML Validator Buildpack

To use GitLab Auto DevOps โ€” Auto Test[7], a Buildpack to validate the configuration files (which are Yaml based) is required. Here the Yamllint-buildpack[8] was introduced to have this job done ๐Ÿ’ป

GitLab Pipeline with Auto-Test job

Detection

For the YAML Buildpack to run, It checks first if the repository is matching. If the repository contains YAML files, it prints the Buildpack name, otherwise, it terminates the script.

#!/usr/bin/env bash
set -eo pipefail

ymlFilesArray=$(find "${1:?}" -maxdepth 1 -regex ".*.[yml|yaml]" | grep -v '^$')

if [ ${#ymlFilesArray[@]} -gt 0 ]; then
  echo "freenow/yamllint"
  exit 0
else
  (>&2 echo "Could not find yaml/yml files")
  exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Test compile

This step is to prepare the repository for the test. As there is no compilation required before running the tests, the test-compile script is empty. The file MUST exist for the Herokuish to successfully run.

Test

This script is to apply the YAML validation using yamllint.

To run the yamllint check:

  1. Download and Install Python
  2. Install Pip
  3. Install yamllint
  4. Run yamllint check

For the complete script:

#!/usr/bin/env bash
# bin/test <build-dir> <env-dir>

set -eo pipefail 

echo "---> yamllint check..."   

# GET ARGS
BP_DIR=$(cd $(dirname $0)/..; pwd) 

# absolute path
BUILD_DIR=$1
ENV_DIR=$2  

# CREATE THE LAYER DIRECTORY
pythonlayer="$ENV_DIR"/python
mkdir -p "$pythonlayer" 

# DOWNLOAD PYTHON
echo "---> Downloading and extracting Python"
python_url=https://s3-external-1.amazonaws.com/heroku-buildpack-python/heroku-18/runtimes/python-3.10.0.tar.gzwget -q -O - "$python_url" | tar -xzf - -C "$pythonlayer" 

# MAKE PYTHON AVAILABLE TO THIS SCRIPT
export PATH="$pythonlayer"/bin:$PATH
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}"$pythonlayer/lib" 

# INSTALL PIP
echo "---> Installing pip"
python -m ensurepip --upgrade 

# INSTALL YAMLLINT
echo "---> Installing yamllint"
pip3 install yamllint 

# RUN YAMLLINT
echo "---> Validating yaml/yml files"
yamllint -c "$BP_DIR/config/yamllint-config" $BUILD_DIR 

echo "---> [success] yaml/yml validation"

Enter fullscreen mode Exit fullscreen mode

Additional configurations

GitLab is by default enabling not needed jobs by default. Due to that, you need to disable these jobs by using GitLab variables and set the below variables as false

  • BUILD_DISABLED

  • CODE_QUALITY_DISABLED

  • CONTAINER_SCANNING_DISABLED

  • SECRET_DETECTION_DISABLED

And the most important variable is the BUILDPACK_URL where you refer to the Buildpack URL :-)

References:

[1] https://surfingcomplexity.blog/2021/05/29/why-do-config-changes-keep-coming-up-in-major-incidents/

[2] https://marketplace.atlassian.com/apps/1213552/yaml-validator-hook

[3] https://docs.gitlab.com/ee/administration/server_hooks.html

[4] https://docs.gitlab.com/ee/topics/autodevops/

[5] https://buildpacks.io/

[6] https://docs.gitlab.com/ee/topics/autodevops/customize.html

[7] https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-test

[8] https://github.com/freenowtech/yamllint-buildpack

Oldest comments (0)