Seven Commands to Bulletproof Your Symfony Application CI Build
Tags: php, symfony, travis, ci
Published: 2020-01-14 17:13:48

---
title: Seven Commands to Bulletproof Your Symfony Application CI Build
published: true
date: 2020-01-12 00:00:00 UTC
tags: [php, symfony, travis, ci]
canonical_url: https://kamilkokot.com/seven-commands-to-bulletproof-your-symfony-application-ci-build/
---

This blogpost has been originally published on [kamilkokot.com](https://kamilkokot.com/seven-commands-to-bulletproof-your-symfony-application-ci-build/).

Over the course of years, I noticed there are more and more checks that are usually performed in our Symfony applications’ CI environment. This is my attempt at writing down the most useful ones.

Table of contents:

1. Checking for security vulnerabilities
2. Validating package configuration
3. Linting Symfony container
4. Linting Twig templates
5. Linting YAML files
6. Testing Doctrine migrations
7. Validating Doctrine mappings

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>1. Checking for security vulnerabilities

Security should be the most critical concern while developing any application. It should come as no surprise that there are multiple solutions for ensuring that our application does not rely on dependencies with known vulnerabilities. Although they differ in usage, they are all based on the same source - [FriendsOfPHP/security-advisories](https://github.com/FriendsOfPHP/security-advisories).

#### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Symfony CLI

It is provided together with [the Symfony binary](https://symfony.com/download), which is a recommended way to create new Symfony projects and includes a convenient local web server, which comes handy during development.

If you already use it as a web server in your CI build, I would recommend using it also for security checks.

```
symfony security:check
```

If you do not have it in your CI build yet, the following `.travis.yml` configuration does the job:

```
cache:
    directories:
        - ~/.symfony

before_install:
    - |
        if [! -f ~/.symfony/bin/symfony]; then
            wget https://get.symfony.com/cli/installer -O - | bash
        fi

script:
    - ~/.symfony/bin/symfony security:check
```

#### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>SensioLabs Security Checker

[SensioLabs/SecurityChecker](https://github.com/sensiolabs/security-checker) is what I’ve been using before switching to Symfony CLI. It uses `security.symfony.com` API to perform the check, which means your `composer.lock` will be uploaded there.

To use it, add `sensiolabs/security-checker` to your `require-dev` section in `composer.json` and then run the following command:

```
vendor/bin/security-checker security:check
```

#### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Roave Security Advisories

While the previous two tools work in a similar way, [Roave/SecurityAdvisories](https://github.com/Roave/SecurityAdvisories) takes a different approach.

It is a Composer package which defines vulnerable packages as its conflicts, preventing them from being installed and resulting in irresolvable dependencies. This behaviour is a double-edged sword - it does not trigger when packages dependencies are installed from the lock file.

My recommendation is to require this package only in the CI build:

```
composer install
composer require --dev roave/security-advisories
```

However, resolving dependencies in complex projects takes a lot of time, which makes me prefer the other solutions.

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>2. Validating package configuration

Composer provides a command to validate your `composer.json` and `composer.lock` files. It checks whether your lock file is up-to-date, whether used constraints are not too loose or too strict and whether the package is valid to be published on Packagist.

```
composer validate --strict
```

There are a few switches available for this command:

- 

`--strict`

Makes the command return non-zero code for warnings as well as errors. For example, having overly strict dependency (`1.0.0` instead of `^1.0`) in `require` section will trigger a warning.

- 

`--no-check-all`

Disables checking for overly strict or unbound dependencies in `require` section. Even without this switch, it does not check the dependencies defined in `require-dev` section.

- 

`--no-check-lock`

Disables checking whether the lock file is up-to-date.

- 

`--no-check-publish`

Ignores errors which prevent the package from be published on Packagist. Useful for internal applications that will not be published, but required for open source packages.

I would recommend you starting with the most strict check and ignoring some parts later if needed.

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>3. Linting Symfony container

[Introduced with Symfony 4.4](https://symfony.com/blog/new-in-symfony-4-4-service-container-linter), linting the container might help in finding dead services configurations. We found [a few in Sylius](https://github.com/Sylius/Sylius/pull/10926) and decided to add it to the build to prevent us from introducing them anymore.

```
bin/console lint:container
```

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>4. Linting Twig templates

Linting your Twig templates checks their syntax and might detect unused templates if an unexisting filter or function is used in those.[After running it on Sylius codebase](https://github.com/Sylius/Sylius/pull/8056), it has found a template calling parent blocks while not extending any template itself and another template calling an unexisting filter.

```
bin/console lint:twig templates
```

Starting from Symfony 4.4, this command also includes a way to report usages of deprecated Twig features. It helped greatly with [the upgrade to Twig 3](https://github.com/Sylius/Sylius/pull/10955).

```
bin/console lint:twig templates--show-deprecations
```

I would not recommend adding deprecation checks to your CI build as it would make it more unstable - any deprecation in next Twig version would make it fail.

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>5. Linting YAML files

It is easy to make errors writing YAML files compared to XML. Therefore, it is essential to get feedback on those as fast as possible.

```
bin/console lint:yaml config src translations
```

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>6. Testing Doctrine migrations

If you provide Doctrine migrations in your application, it is desirable to test them. Most applications include the following line in their CI builds:

```
bin/console doctrine:migrations:migrate --no-interaction
```

While this covers the most common path, it does not test reverting these migrations.

```
bin/console doctrine:migrations:migrate --no-interaction
bin/console doctrine:migrations:migrate first --no-interaction
bin/console doctrine:migrations:migrate --no-interaction
```

These three commands will first create the schema in the database, then revert the changes and create it once again.

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>7. Validating Doctrine mappings

After the migrations have been run or the database schema has been synchronised in any other way, it’s worth to validate your Doctrine mappings and whether they’re correctly synchronised with the database schema.

It can be done with the following command:

```
bin/console doctrine:schema:validate
```

### <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Conclusion

Surely, this list is non-exhaustive: it completely misses static analysers, testing frameworks, coding standard fixers and automation tools, which I would like to include in another blog post in this series.

What it mainly focuses on are commands that can be added with little effort but might be often overlooked. If you use one of those, but it wasn’t mentioned above, let me know in the comments!