Skip to content

Instantly share code, notes, and snippets.

@ondrejmirtes
Last active April 17, 2019 15:11
Show Gist options
  • Save ondrejmirtes/5ed53cbcf1eb76060a844b54ec6a9dcd to your computer and use it in GitHub Desktop.
Save ondrejmirtes/5ed53cbcf1eb76060a844b54ec6a9dcd to your computer and use it in GitHub Desktop.

PHPStan Pro Beta Instructions

Check out the article on Medium.com on what's PHPStan Pro about.

Prerequisities:

  • Download the API client (current version 0.2.1): https://ondrej.mirtes.cz/download/phpstan-api-client.phar
    • I recommend to commit it as part of the analysed project
  • Install at least PHPStan 0.10.7 (or newer)
  • Set the attached token value as environment variable PHPSTAN_API_CLIENT_TOKEN:
export PHPSTAN_API_CLIENT_TOKEN=abc

Index:

  1. I want to run plain PHPStan
  2. I want to run PHPStan and filter the errors with the baseline
  3. I want to run PHPStan on changed files only
  4. I want to run PHPStan on changed files only and filter the errors with the baseline
  5. I'm using the baseline filtering and I'm upgrading PHPStan to a new version
  6. I'm increasing level, or adding a new rule, and I want to include the new errors in the baseline
  7. I'm adding PHPStan Pro to a new project
  8. I'm removing PHPStan Pro from a project
  9. I want to stop using PHPStan Pro

Use-cases:

1) I want to run plain PHPStan

A.k.a. running PHPStan as usual:

vendor/bin/phpstan analyse

This will work if you have phpstan.neon or phpstan.dist.neon in the root directory of your project and it contains paths and level keys. Otherwise, you can use all the flags as usual - --configuration, --level etc.

Since the API client accepts PHPStan's JSON output in STDIN, it's a good idea to first save the output to a variable and passing it this way:

PHPSTAN_JSON_OUTPUT=$(vendor/bin/phpstan analyse --error-format json)

2) I want to run PHPStan and filter the errors with the baseline

You run PHPStan and pass the JSON-formatted output to phpstan-api-client.phar baseline:filter

PHPSTAN_JSON_OUTPUT=$(vendor/bin/phpstan analyse --error-format json)
echo ${PHPSTAN_JSON_OUTPUT} | ./phpstan-api-client.phar baseline:filter

What it does:

  • Finds out the original branch on which the changes are applied - defaults to master, overridable with --baseBranch.
  • Finds out the current branch - overridable with --branch.
  • Extracts the diff between these two points in history and sends it along with the errors to the API. Only changes in current files are transferred, the API does not need to see deleted or added files.
  • When running for the first time (there's no prior baseline), the current error set is set as the baseline and no new errors are reported.

After a successful run, the current branch (--branch) can be used as --baseBranch in subsequent runs.

If you're running baseline:filter in CI on the main branch, also include the option --publish.

3) I want to run PHPStan on changed files only

./phpstan-api-client.phar analyse:changed --executable vendor/bin/phpstan

In this case, PHPStan needs to be run through the API client because the API client determines on which files the analysis will be performed on.

You can use the usual flags like --level and --configuration. Paths need to be either set in the configuration using the paths key, or passed on the command line like this (repeat the option for multiple paths):

./phpstan-api-client.phar analyse:changed --executable vendor/bin/phpstan --paths src --paths tests

What the command does:

  • Finds out the original branch on which the changes are applied - defaults to master, overridable with --baseBranch.
  • Finds out the current branch - overridable with --branch.
  • Extracts the list of changed files between these two points in history.
  • It asks the API for the list of errors and files to analyse based on the original commit and list of changed files.
  • It runs PHPStan and reports the errors. Please note that it will report errors from the whole project, not just from the analysed files. This is so that this command can be composed with baseline:filter (see the next use case).
  • If the --update-deps flag is passed, the client will run PHPStan's dump-deps command and upload the new set of errors and the dependency tree back to the server. This is recommended to do in the CI environment, but discouraged on the local dev machine for these reasons:
    • You want to have the dependency tree as up-to-date as possible because it makes the list of files to analyse shorter in subsequent runs.
    • Developers can run analyse:changed locally to verify their changes but it'd be wasteful to run dump-deps and upload data to the API each time.

When analyse:changed is running for the first time, it should be run with --update-deps so that the dependencies and list of errors are uploaded to the server. After that, the current branch (--branch) can be used as --baseBranch in subsequent runs.

4) I want to run PHPStan on changed files only and filter the errors with the baseline

This use case represents the strength of PHPStan Pro - you're getting really fast feedback and the errors are filtered with the baseline at the same time!

It combines the scenario #2 and #3:

PHPSTAN_JSON_OUTPUT=$(./phpstan-api-client.phar analyse:changed --executable vendor/bin/phpstan --json)
echo ${PHPSTAN_JSON_OUTPUT} | ./phpstan-api-client.phar baseline:filter

Again, don't forget to include --update-deps when running in CI environment so that the dependencies and list of errors are uploaded to the server.

For example, if you're using GitLab CI, the complex scenario can look like this in your build script:

./phpstan-api-client.phar analyse:changed \
--executable vendor/bin/phpstan \
--branch ${CI_COMMIT_REF_NAME} \
--baseBranch master \
--level 7 \
--configuration phpstan.neon \
--paths src \
--paths tests \
--json \
--no-progress \
--update-deps | \
./phpstan-api-client.phar baseline:filter \
--branch ${CI_COMMIT_REF_NAME} \
--baseBranch master

If you're running baseline:filter in CI on the main branch, also include the option --publish.

5) I'm using the baseline filtering and I'm upgrading PHPStan to a new version

New version typically brings new reported errors. It's worthwhile to see the errors at least once for yourself, so you need to run full PHPStan (without the analysis of only changed files, without the baseline filtering):

vendor/bin/phpstan analyse

You can observe the list of errors and maybe fix the easy ones. If some new errors remain, you need to update the baseline (so that new errors are included in it and not reported):

PHPSTAN_JSON_OUTPUT=$(vendor/bin/phpstan analyse --error-format json)
echo ${PHPSTAN_JSON_OUTPUT} | ./phpstan-api-client.phar baseline:set

In case you're using analyse:changed command, you also need to run it with --force-full and --update-deps so that you upload the new errors and an update dependency tree to the server:

./phpstan-api-client.phar analyse:changed --executable vendor/bin/phpstan --force-full --update-deps

⚠️ Make sure you committed all changes related to the upgrade and that the current Git commit hash is the same that you will eventually push to your Git server before doing these steps (so that the subsequent runs can refer to it).

6) I'm increasing level, or adding a new rule, and I want to include the new errors in the baseline

Same as 5).

7) I'm adding PHPStan Pro to a new project

As part of the beta invitation, you received one secret token. It can be used for a single project/repository. In case you want to start using PHPStan Pro on a second, third etc. project, you need to register new tokens for them:

./phpstan-api-client.phar token:register

This still requires to have a valid token set in the PHPSTAN_API_CLIENT_TOKEN environment variable.

8) I'm removing PHPStan Pro from a project

You can deregister tokens like this:

./phpstan-api-client.phar token:deregister

This still requires to have a valid token set in the PHPSTAN_API_CLIENT_TOKEN environment variable. It cannot be the same as the deregistered one.

9) I want to stop using PHPStan Pro

token:deregister does not allow you to deregister the last token. Contact me please and I will remove the last token from the service and stop sending you invoices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment