Image with the GitLab and PHPStan logos

Running static analysis on your code saves time by uncovering hidden issues. PHPStan is a static analysis tool for PHP that helps you increase the quality of your codebase. Here’s how to run PHPStan within your GitLab CI pipelines.

It’s good to run PHPStan regularly while you’re building out new features. Using it locally only takes you so far though. You’re reliant on your other team members being as disciplined as you are. Integrating static analysis into a CI/CD workflow ensures code can’t be merged if it would break your project’s main branch.

Getting Setup with PHPStan

You first need to add PHPStan into your project. We’ve already got a detailed guide on installing and configuring PHPStan, so we’ll only cover the basics here.

First, use Composer to install PHPStan:

composer require --dev phpstan/phpstan

Next, create a basic phpstan.neon configuration file in your project:

  level: max
    - src
    - tests
  tmpDir: .tmp

The temporary directory is overridden to assist GitLab CI’s caching, setup below.

You can now run PHPStan locally to check your configuration works:

vendor/bin/phpstan analyse

At this stage, it doesn’t matter whether the tests pass.

Configuring GitLab for CI

Make sure you’ve pushed your code to a project on your GitLab server. You’ll need to check the Pipelines feature is enabled for your project – if you see “CI / CD” in the left sidebar, you’re good to go.

image of Pipelines menu item in GitLab

To enable your project’s CI system, click the “Settings” button in the sidebar. Expand the “Visibility, project features, permissions” section and enable the “Pipelines” feature.

image of enabling Pipelines in GitLab

If you use GitLab’s Merge Requests (MRs) in a disciplined manner, you can now configure GitLab to prevent MRs from getting merged unless they have a successful pipeline. Expand the “Merge requests” settings section and check the “Pipelines must succeed” toggle button. Click “Save” to confirm. This will stop you accidentally merging an MR when PHPStan fails against its changes.

image of enabling GitLab's MR required pipelines

To use GitLab CI, you’ll need to have a GitLab Runner defined at the instance, group or project level. Runners are responsible for executing the CI jobs created by the GitLab system.

We’re going to use the PHPStan Docker image to run PHPStan in our CI pipeline. This requires the use of a GitLab Runner using the Docker executor. If you’re on a self-managed instance and need to configure a new Runner, follow the guidance in our article on setting up GitLab CI.

Creating a GitLab CI Pipeline

GitLab CI is configured using a .gitlab-ci.yml file at the root of your project. CI pipelines support multiple sequential stages. Each stage’s jobs run in parallel. For our purposes of running PHPStan, we need a single stage which runs one job.

  - phpstan

    - .tmp/
    - vendor/

  stage: phpstan
    - analyse --no-progress --error-format gitlab > phpstan.json
    when: always
      codequality: phpstan.json

This GitLab CI file contains all we need to run PHPStan within our pipeline. We define a stage, phpstan, containing a job that’s also called phpstan. The job uses the official PHPStan Docker image from the GitHub container registry.

The GitLab CI cache is configured to cache the .tmp and vendor directories. This will improve the performance of subsequent runs on the same branch. The cache will get restored automatically. Back in our phpstan.neon, we set the tmpDir to .tmp for this reason – it means we can now confidently reference it in the CI pipeline’s caching configuration.

We also cache vendor to avoid needlessly reinstalling Composer dependencies on each run. Note that you don’t need to run composer install manually – the official PHPStan Docker image invokes it automatically.

The --error-format flag is passed to PHPStan’s analyse command. This configures PHPStan to create a JSON file in the format accepted by GitLab’s code quality report. Down in the artifacts section, this file gets uploaded to GitLab after the job completes.

Using the Pipeline

Commit your .gitlab-ci.yml and push to your GitLab server. The CI system should now kick in and create your first pipeline. Use the “CI / CD” link in the left navigation to view the pipeline’s progress.

image of PHPStan GitLab CI pipelines

If you get a green tick, PHPStan’s tests passed! Your branch is in a good state and it’s ready to merge. If a red cross appears, you’ve got more work to do. PHPStan and GitLab CI just stopped you merging potentially broken code.

You can get the list of errors by clicking the download icon to the right of the pipeline. Select the PHPStan code quality artifact to obtain the JSON report of errors which PHPStan found.

Using with Merge Requests

Reading the JSON manually doesn’t make for a great experience. However, GitLab’s Merge Requests expose the contents of the report automatically. Because the report is tagged as a GitLab code quality artifact, GitLab knows how to present the information within.

image of GitLab Code Quality Merge Request widget

Merge requests with a failing pipeline should display an expandable “Code quality” section. This indicates the number of errors encountered. Expand the section to view a complete list of problems found by PHPStan.

Once you’ve addressed the issues, push your changes up to GitLab. The pipeline will run again. Once it’s completed, you’ll see the new status on the Pipelines screen and in your merge request’s code quality widget.


PHPStan helps you write better PHP that’s less susceptible to hidden problems. To get the most from it, the tool must be incorporated into your development workflow in such a way that it can’t be ignored or circumvented.

Using PHPStan with GitLab CI gives you the consistency you need to be confident in your code. Configuring GitLab to block MRs with a failed pipeline means changes can’t enter your main branch without passing a PHPStan run. PHPStan’s full support for GitLab’s code quality reports make it easy to assess errors without leaving the web UI, helping you rapidly fix any problems which are uncovered.

Profile Photo for James Walker James Walker
James Walker is a contributor to How-To Geek DevOps. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes.
Read Full Bio »