Анализируем код PHP проекта c помощью Psalm

2 апр. 2021 г.

Всем привет! Сегодня хотел бы рассказать о настройке анализа кода PHP(Symfony) проекта c помощью Psalm. А также генерацию html отчета и последующую интеграцию с Github Actions.

Psalm - инструмент для статического анализа и поиска ошибок в PHP проектах. Пример работы можно посмотреть на на официальном сайте.

Изначально настраивал для этого блога. Но затем, для большей наглядности, также настроил для одного из открытых проектов - placeholder-service.

Установка

Установка Psalm описана в документации.

composer require --dev vimeo/psalm
./vendor/bin/psalm --init

После установки будет создан файл psalm.xml.

Запуск

Для запуска проверки всего проекта выполним команду:

./vendor/bin/psalm

Также можно проверить определенные файлы:

./vendor/bin/psalm src/Controller

И сохранить результаты в XML:

./vendor/bin/psalm --report=checkstyle.xml

Генерация html отчета

Для создания html отчета можно использовать библиотеку psalm-html-output. Для генерации отчета используется xsltproc. Сначала нужно установить библиотеку.

composer require --dev roave/psalm-html-output

Затем установить системный пакет xsltproc

apt install xsltproc

Отчет создается такой командой:

vendor/bin/psalm --output-format=xml | xsltproc vendor/roave/psalm-html-output/psalm-html-output.xsl - > psalm-report.html

Для более удобного запуска можно добавить скрипты в composer composer.json. И запускать таким образом: composer psalm и composer psalm-report-html.

{
    ...
    "scripts": {
        ...
        "psalm": [
            "vendor/bin/psalm --report=checkstyle.xml"
        ],
        "psalm-report-html": [
            "vendor/bin/psalm --output-format=xml | xsltproc vendor/roave/psalm-html-output/psalm-html-output.xsl - > psalm-report.html"
        ],
        ...
    }
    ...
}

Подключение к Github Actions

Настройка github actions и настройка отображения html отчетов в pull request описана в предыдущих постах. Нам нужно будет добавить генерацию html отчета и загрузку на сторонний web-сервер. Для этого создадим новое workflow .github/workflows/psalm.yml. Для private репозитория нужно обязательно защитить Web-сервер с помощью basic auth или другим способом!

## —— Upload tests coverage report to remote server
- name: Extract branch name
  shell: bash
  run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
  id: extract_branch
- name: Print branch name
  shell: bash
  run: echo ${{ steps.extract_branch.outputs.branch }}
- name: Create directories for reports
  uses: appleboy/ssh-action@master
  env:
    BRANCH: ${{ steps.extract_branch.outputs.branch }}
    FILES_PATH: ${{ secrets.GA_FILES_PATH }}
  with:
    envs: BRANCH,FILES_PATH
    host: ${{ secrets.REMOTE_HOST }}
    username: ${{ secrets.REMOTE_USER }}
    key: ${{ secrets.SERVER_SSH_KEY }}
    passphrase: ''
    script: mkdir -p $FILES_PATH/$BRANCH
- name: Uploads reports to server
  uses: appleboy/scp-action@master
  with:
    host: ${{ secrets.REMOTE_HOST }}
    username: ${{ secrets.REMOTE_USER }}
    key: ${{ secrets.SERVER_SSH_KEY }}
    passphrase: ''
    rm: true
    source: "coverage"
    target: ${{ secrets.GA_FILES_PATH }}/${{ steps.extract_branch.outputs.branch }}

Затем добавить создание комментария со ссылкой на отчет в workflow .github/workflows/pull_request_comments.yml.

name: Pull request comments
on:
  pull_request:
jobs:
  pull_request_comments:
    runs-on: ubuntu-20.04
    steps:
      - name: Extract branch name
        shell: bash
        run: echo "##[set-output name=branch;]$(echo ${GITHUB_HEAD_REF})"
        id: extract_branch
      - name: Print branch name
        shell: bash
        run: echo ${{ steps.extract_branch.outputs.branch }}
      - name: Add psalm code static analysis report comment
        uses: mshick/add-pr-comment@v1
        with:
          message: |
            Psalm static analysis report: [http://files.antonshell.me/github-actions/placeholder-service/${{ steps.extract_branch.outputs.branch }}/psalm/psalm-report.html](http://files.antonshell.me/github-actions/placeholder-service/${{ steps.extract_branch.outputs.branch }}/psalm/psalm-report.html)
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          repo-token-user-login: 'github-actions[bot]' # The user.login for temporary GitHub tokens
          allow-repeats: false # This is the default

В результате получаем примерно такой отчет.

Тестовый проект доступен на github. Также есть Pull Request с реализацией покрытия тестами. На этом пока все. Спасибо за внимание!