カテゴリー
Computer Development

gitlab-ci.ymlチェックスクリプト

(Last Updated On: 2018/09/04)

gitlabのCI/CDは他の今時のCI/CDシステムと同じくYAMLファイルで記述します。リポジトリにCI/CD定義を書けるのは便利なのですが、コミット前に定義が正しいかチェックししたい場合がほとんとです。

少なくともgitlab-ci.ymlをコミット前に文法をチェック/テストしたい!

この場合に使えるスクリプトをたまたま見つけて、便利だったので紹介します。

GitLab CI/CD YAMLチェックスクリプト

GitLabサーバーはAPIとしてgitlab-ci.ymlをチェックする機能を持っているのですが、お世辞にも使い易い、とは言えません。

このAPIのページをよく見ると、コメントとしてPythonで書いたクライアントプログラムがありました。

使い方:

usage: validate-ci-file.py [-h] [-l] [-t] [-L] file

positional arguments:
  file           Yaml filename to validate

optional arguments:
  -h, --help     show this help message and exit
  -l, --logging  Log activity and data to syslog
  -t, --trace    Use PDB to debug the execution step by step
  -L, --loghttp  Activate the logging inside the requests lib

コード:

使う前にprivate_token を自分で生成したアクセストークンに、urlを自分のgitlabサーバーのホストに変更する。このままでも何回かは動作しますが、直ぐにブロックされます。

#!/usr/bin/python3
import requests, sys, yaml, json, logging, argparse, pdb
from lxml import html
from urllib.parse import unquote

parser = argparse.ArgumentParser()
parser.add_argument("file", help="Yaml filename to validate")
parser.add_argument("-l", "--logging", help="Log activity and data to syslog", action="store_true")
parser.add_argument("-t", "--trace", help="Use PDB to debug the execution step by step", action="store_true")
parser.add_argument("-L", "--loghttp", help="Activate the logging inside the requests lib", action="store_true")
args = parser.parse_args()

private_token = "YOUR TOKEN GOES HERE"

url = "https://gitlab.com/api/v4/ci/lint?private_token="+private_token
logging.basicConfig(filename="/tmp/validator.log", level=logging.DEBUG)

"""
LOGGING FUNCTION for HTTP
"""

def loghttp():
    import http.client as http_client

    logging.basicConfig(level=logging.INFO)
    logging.getLogger().setLevel(logging.INFO)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.INFO)
    requests_log.propagate = True

try:
    if args.trace: pdb.set_trace()

    if args.loghttp: loghttp()

    if args.logging: logging.debug("File is {}".format(args.file))
    session_requests = requests.session()
    gitlab_ci_yml = open(args.file, 'r')
    yaml = yaml.load(gitlab_ci_yml)
    if args.logging: logging.debug("Yaml read is {}".format(yaml))
    gitlab_ci_yml.close()

    content = json.dumps(json.dumps(yaml))
    if args.logging: logging.debug("JSON double encoded is {}".format(content))
    content = '{"content": ' + content + '}'
    if args.logging: logging.debug("Final content to be sent is {}".format(content))

    result = session_requests.post(
            url,
            data = content,
            headers = {'Content-Type' : "application/json"}
    )
    if args.logging: logging.debug("Headers sent were {}".format(result.request.headers))
    if args.logging: logging.debug("Content sent was {}".format(unquote(result.request.body)))

    print(result)
    print(result.text)

except Exception as e:
    print(e)

いい加減、自分で書こうか、と思いましたがこのスクリプトで十分でした。

gitlabを使っている方にオススメです。

CI Lintでバリデーション

一手間必要なのでスクリプトをインストールした方が便利ですが、各プロジェクトのCI/CDページの右上に「CI Lint」というボタンがあります。これを押すとgitlab-ci.ymlをコピー&ペーストしてバリデーション可能です。