Seven Commands to Bulletproof Your Symfony Application CI Build
January 12, 2020 • 5 minutes read • 0 comments • Edit on GitHub
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:
- Checking for security vulnerabilities
- Validating package configuration
- Linting Symfony container
- Linting Twig templates
- Linting YAML files
- Testing Doctrine migrations
- Validating Doctrine mappings
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.
It is provided together with the Symfony binary, 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.
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
SensioLabs/SecurityChecker is what I’ve been using before switching to Symfony CLI. It uses
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:
While the previous two tools work in a similar way, 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.
Composer provides a command to validate your
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:
Makes the command return non-zero code for warnings as well as errors. For example, having overly strict dependency (
requiresection will trigger a warning.
Disables checking for overly strict or unbound dependencies in
requiresection. Even without this switch, it does not check the dependencies defined in
Disables checking whether the lock file is up-to-date.
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.
Introduced with Symfony 4.4, linting the container might help in finding dead services configurations. We found a few in Sylius and decided to add it to the build to prevent us from introducing them anymore.
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, 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.
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.
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
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.
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:
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!