Daniel Siepmann - Coding is Art

Blog Post

Integrate TYPO3 Linting with GitLab-CI

Published: , Updated:

Topics: quality assurance, typo3

Introduction

GitLab is the new buzzword for cloud- and self-hosted repository hosting connected to a CI. We are using GitLab-CI in combination with Docker for running tests, linting code and deployments.

In this post I’ll explain how to setup linting TypoScript and YAML for TYPO3 projects using GitLab-CI.

TypoScript linting

Martin Helmich has created a TypoScript parser and TypoScript linter which already provides basic rules. The concepts are inherited from PHP Code Sniffer with different Sniffs which can be configured.

You can install the linter as dev dependency using composer:

composer require --dev helmich/typo3-typoscript-lint

The linter is pre-configured with a default configuration, which can be found at GitHub: https://github.com/martin-helmich/typo3-typoscript-lint/blob/v1.4.6/tslint.dist.yml

Configuration is written as yaml. You can extend the default configuration. Most linters provide the .dist way to provide a distributed configuration which can be overwritten by a more specific configuration. We are using yaml as file extension, which is the preferred accordingly to FAQ of yaml. Our configuration looks like the following tslint.yaml:

paths:
    - localPackages/sitepackage/Configuration/PageTSConfig/
    - localPackages/sitepackage/Configuration/TypoScript/
    - localPackages/sitepackage/Configuration/UserTSConfig/

sniffs:
    - class: Indentation
      parameters:
          indentConditions: true
    - class: RepeatingRValue
      disabled: true

We define paths containing TypoScript to check. Also we adjust the default sniffs a bit. We force indentation of one level inside of conditions, as we do in PHP and JavaScript. Also we disable the RepeatingRValue sniff as we check this rule ourselves.

To actually lint anything, you will call the linter with the configuration:

./vendor/bin/typoscript-lint -c tslint.yaml

Which will generate something like the following if everything is fine:

..................................................   [ 50 / 106,  47%]
..................................................   [100 / 106,  94%]
......                                               [106 / 106, 100%]

Complete without warnings

If errors or warnings exist, the following output will be generated:

...............................W..................   [ 50 / 106,  47%]
........W................................W........   [100 / 106,  94%]
......                                               [106 / 106, 100%]

Completed with 9 issues

CHECKSTYLE REPORT
=> localPackages/cdx_site/Configuration/TypoScript/Setup/Plugins/SearchCore.typoscript.
   7 No whitespace after object accessor.
  10 Accessor should be followed by single space.
  11 Value of object "plugin.tx_searchcore.view.templateRootPaths.10" is overwritten in line 12.

SUMMARY
9 issues in total. (9 warnings)

You can also output in checkstyle format which might be useful for some CI environments and editors.

yaml linting

As we didn’t find any useful yaml linter written in PHP, we use one written in Python. Most php linters just call Symfony yaml parser and catch exceptions, which results in a single parsing error.

So we decided to use yamllint, which is no problem using Docker and GitLab-CI. I’ll not describe how to install locally, refer to GitLab-CI in next section.

As the TypoScript linter, this linter also provides a default of rules to check, which can be found at GitHub: https://github.com/adrienverge/yamllint/blob/v1.10.0/yamllint/conf/default.yaml There is also a “relaxed” version of the configuration. You can “inherit” one of the configurations in your own, which is provided as yamllint.yaml in your project root:

extends: default

rules:
    line-length: disable
    document-start: disable
    braces:
        min-spaces-inside-empty: 1
        max-spaces-inside-empty: 1
    brackets:
        min-spaces-inside-empty: 1
        max-spaces-inside-empty: 1
    comments:
        level: error
        min-spaces-from-content: 1
    comments-indentation:
        level: error
    empty-lines:
        max: 1
    empty-values:
        forbid-in-block-mappings: true
        forbid-in-flow-mappings: true
    indentation:
        spaces: 4

We adjust some rules, some become more strict, some are disabled completely.

You can call the linter using the following command:

yamllint -c yamllint.yaml localPackages/ yamllint.yaml .gitlab-ci.yml tslint.yaml

Nothing will be printed if everything is fine. Errors and warnings are reported like:

localPackages/cdx_site/Configuration/Forms/Base.yaml
  7:21      error    duplication of key "10" in mapping  (key-duplicates)

tslint.yaml
  10:28     error    empty value in block mapping  (empty-values)

Integrate linting in GitLab-CI

As we now know how to configure the linter and how to execute them, we need to integrate them into our GitLab-CI through our .gitlab-ci.yml. Poorly GitLab does not allow yaml as file extension for that file.

The task for TypoScript looks like the following:

lint:typoscriptcgl:
    image: composer:1.6
    stage: lint
    script:
        - composer install --no-progress --no-ansi --no-interaction
        - ./vendor/bin/typoscript-lint -c tslint.yaml

The task for Yaml looks like the following:

lint:yaml:
    image: python:alpine3.7
    stage: lint
    before_script:
        - pip install yamllint==1.10.0
    script:
        - yamllint -c yamllint.yaml localPackages/ yamllint.yaml .gitlab-ci.yml tslint.yaml

As both linter will provide proper exit codes, we are finished. Output is generated in a human friendly way, so everyone can take a look right into the log what goes wrong and can fix the issues.

By default, both tools will return an exit code 0 if only warnings were found, which is considered best practice, as warnings are just warnings and those okay.

typoscript-lint will return an exit code 2 if an issue was found. This is only true for errors, not warnings. To enable exit code 2 also if warnings were found, add the option --fail-on-warnings.

yamllint will return 1 if errors were found, 0 otherwise. To return 2 if an warning was found, enable strict mode via --strict. For further information see Errors and warnings.

Acknowledgements

Updated on 20 Apr, 2019

Added further details about exit codes for TypoScript linter by Martin Helmich.

Thanks Twitter user spooner_web for a hint that these information might be helpful.

Further reading