otgs/diff-checks

Run static code analysis against the changed code (applicable) or files

1.0.0 2019-06-10 14:41 UTC

This package is auto-updated.

Last update: 2024-06-15 01:31:29 UTC


README

This tool is meant to run some checks mainly based on the changes between the current commit (or unstaged changes) and the target branch (or parent ancestor).

Depending on where it's used, it tries its best to limit the differences to only the changed lines or files.

This tool as also a few extra features which are explained in this document.

At the moment of writing, all features runs hard-coded in otgs-checks-php.
There is some level of configuration which can allow controlling the behavior.

Below is each feature in the order they are executed.

The tool exists with a non-zero code as soon as any of the feature fails.

Features

WordPress Plugins: validate the version (only non-CI environment)

This feature is unrelated to the changed files, but runs before any other feature.

Due to the fact that GitLab-CI does not clone the whole repository when running jobs, this feature is ignored if a CI environment variable is set. However, if a CI_COMMIT_TAG environment variable is set, the feature won't be ignored.

  1. It starts by searching the most recent tag of the current repository (using git describe --abbrev=0)
  2. It tries to find the main plugins file
  3. It tries to find where the version number is defined in the main plugin file
  4. It compares these values with the value found at #1: if #1 is greater, it fails the check

The rules to extract the version number from the main plugin file are hard-coded in \OTGS\DiffChecks\WP\Plugins::__construct.
However, they can be extended in two ways.

Environment variable

If the script finds an environment variable called either OTGS_CI_REPLACEMENTS or OTGS_CHECKS_VERSION_PATTERNS, it will use them.

OTGS_CI_REPLACEMENTS replaces OTGS_CHECKS_VERSION_PATTERNS.

OTGS_CHECKS_VERSION_PATTERNS is a variable which is normally used in the CI.

The variable must contain a JSON object. The JSON object must be an array of objects. Each element of the array must have:

  • A searchPattern key: a groups regular expression to match the version number.
  • An optional matchingGroup key: if provided, the tool will use the this value to identify the version number (zero-based).

If matchingGroup is not provided or set to "last", the tool will look for the last match from preg_match.

An excerpt of a OTGS_CI_REPLACEMENTS used in WPML projects:

[
  {
    "searchPattern": "(Version:\\s*)(\\d*.*)",
    "replacePattern": "%1{{tag}}",
    "matchingGroup": 2
  },
  {
    "searchPattern": "(GRAVITYFORMS_MULTILINGUAL_VERSION\\',\\s*\\')(\\d*.*)(\\')",
    "replacePattern": "%1{{tag}}%3",
    "extractSemVer": true,
    "matchingGroup": 2
  },
  {
    "searchPattern": "(wpml.org\\/version\\/wpml-)([\\d\\-*]*)(\\/\">WPML )([\\d\\.*]*)( release notes)",
    "replacePattern": "%1{{tag-slug}}%3{{tag}}%5",
    "matchingGroup": 2
  },

Call to \OTGS\DiffChecks\WP\Plugins::checkVersion

If this library is used in a custom script (that is, not by calling otgs-checks-php), you can use \OTGS\DiffChecks\WP\Plugins::checkVersion to customize the patterns.

In this case, hard-coded patterns and environment variables will be ignored.

\OTGS\DiffChecks\WP\Plugins::checkVersion accepts two arguments:

  • The "valid version" to use
  • (optional) the array of patterns: same specifictation of the JSON form, but as an array of associative arrays

Static code analysis

  1. A list of modified PHP files is generated in memory
  2. A diff file is generated in a temporary directory
  3. A check on all the modified files is made to find duplicated code (phpcbf)
  4. A basic linting is checked on each modified file (php -l -d)
  5. Coding standards are checked against the modified lines (phpcs --standard=./phpcs.xml)
  6. Code compatibility is checked against the modified lines (phpcs --standard=./phpcs.compatibility,xml)

Installation

Run composer require --dev otgs/diff-checks.

Usage

The most straight-forwards usage is by calling ./vendor/bin/otgs-check-php after you've made some changes in your code.

It's recommended to add this call to your GIT pre-commit hook.

In addition, you may want to run this call in your CI before any other test.

However, at the moment of writing this, the only way to build a decent diff, was to provide a target branch.

In GitLab, this can only be achieved if the CI job as at least merge_requests in the only array.

When a job of this type runs, the following two environment variables are provided:

  • CI_MERGE_REQUEST_TARGET_BRANCH_NAME
  • CI_MERGE_REQUEST_SOURCE_BRANCH_NAME

(contribution to improve the building of the diff file are welcome)

Here is an excerpt of a gitlab-ci.yml used in WPML:

Prepare <Cache>:
    stage: pre-flight
    cache: &cache-commit
        untracked: true
        key: "${CI_COMMIT_SHA}"
        paths:
            - node_modules/
            - vendor/
        policy: push
    when: always
    image: registry.otgs.work/infrastructure/docker-images/phpunit:7.3
    script:
        - composer install
        - npm install

Diff <PHP>:
    stage: quality
    cache:
        <<: *cache-commit
        policy: pull
    when: on_success
    image: registry.otgs.work/infrastructure/docker-images/phpunit:7.3
    tags:
        - autoscale
    script:
        - composer install
        - ./vendor/bin/otgs-check-php
    only:
        - merge_requests

Caching

Though not required, the cache key is very useful for speeding up a bit the pipeline.

In Prepare <Cache>, the cache is generated with a push policy (that is, the CI won't try to read it, but it will save it in the cache).

In Diff <PHP> (and all other jobs), the cache is defined with a pull policy (the CI will try to fetch it, gracefully failing if the cache is not available).

The cache-commit is just an anchor name which allows to apply some DRY and it uses the commit ref name as a key.