Регистрируемся в Scrutinizer

Проще, наверное, войти через вашу учетную запись в GitHub, т.к. это избавит вас от необходимости линковать ваш GitHub профиль, а делать это все равно придется.

Для установки приложения Scrutinizer переходим по ссылке, этот шаг можно пропустить, но имейте ввиду, что в дальнейшем у вас не будут работать интерактивные плюшки и будет висеть нотификация: Scrutinizer GitHub App Is Not Installed…

Даем ему все скоупы, которые требует. Не бойтесь, Scrutinizer не удалит ваши репозитории и никак вам не навредит. Это нужно для того, чтобы приложение могло общаться с вашим GitHub по АПИ и в real-time управлять вашим Check Suite, давая ему обратную связь, и кодом в ваших PR для удобства ревью и тд.

Пример, как выглядит окно установки Scrutinizer

Создаем глобальную конфигурацию

Вообще говоря, если у вас много репозиториев, то Best Practies считается правильным иметь одну глобальную конфигурацию, где хранить общие настройки, а специфичные конфиги выносить в конфигурации ваших репозиториев, как бы перезаписывая отдельные куски конфигураций.

Чтобы создать глобальную конфигурацию перейдите по ссылке.

Пример глобальной конфигурации для PHP проекта
build:
    environment:
        php: 7.3.15

build_failure_conditions:
  - 'project.metric_change("scrutinizer.quality", < -0.10)'
  - 'elements.rating(<= D).exists'                                # No classes/methods with a rating of D or worse
  - 'elements.rating(<= D).new.exists'                            # No new classes/methods with a rating of D or worse allowed
  - 'issues.label("coding-style").exists'                         # No coding style issues allowed
  - 'issues.label("coding-style").new.exists'                     # No new coding style issues allowed
  - 'issues.severity(>= MAJOR).new.exists'                        # New issues of major or higher severity                        
  - 'project.metric("scrutinizer.quality", < 9)'                  # Code Quality Rating drops below 9
  - 'patches.label("Doc Comments").exists'                        # No doc comments patches allowed
  - 'patches.label("Spacing").exists'                             # No spacing patches allowed

checks:
    php:
        verify_property_names: true
        verify_argument_usable_as_reference: true
        verify_access_scope_valid: true
        variable_existence: true
        useless_calls: true
        use_statement_alias_conflict: true
        unused_variables: true
        unused_properties: true
        unused_parameters: true
        unused_methods: true
        unreachable_code: true
        too_many_arguments: true
        symfony_request_injection: true
        switch_fallthrough_commented: true
        sql_injection_vulnerabilities: true
        simplify_boolean_return: true
        security_vulnerabilities: true
        return_in_constructor: true
        return_doc_comments: true
        return_doc_comment_if_not_inferrable: true
        require_scope_for_methods: true
        require_php_tag_first: true
        remove_extra_empty_lines: true
        property_assignments: true
        properties_in_camelcaps: true
        precedence_mistakes: true
        precedence_in_conditions: true
        phpunit_assertions: true
        parse_doc_comments: true
        parameters_in_camelcaps: true
        parameter_non_unique: true
        parameter_doc_comments: true
        param_doc_comment_if_not_inferrable: true
        overriding_private_members: true
        overriding_parameter: true
        non_commented_empty_catch_block: true
        no_trait_type_hints: true
        no_trailing_whitespace: true
        no_short_variable_names:
            minimum: '3'
        no_short_open_tag: true
        no_short_method_names:
            minimum: '3'
        no_property_on_interface: true
        no_non_implemented_abstract_methods: true
        no_long_variable_names:
            maximum: '20'
        no_goto: true
        no_exit: true
        no_eval: true
        no_error_suppression: true
        no_debug_code: true
        naming_conventions:
            local_variable: '^[a-z][a-zA-Z0-9]*$'
            abstract_class_name: ^Abstract|Factory$
            utility_class_name: 'Utils?$'
            constant_name: '^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$'
            property_name: '^[a-z][a-zA-Z0-9]*$'
            method_name: '^(?:[a-z]|__)[a-zA-Z0-9]*$'
            parameter_name: '^[a-z][a-zA-Z0-9]*$'
            interface_name: '^[A-Z][a-zA-Z0-9]*Interface$'
            type_name: '^[A-Z][a-zA-Z0-9]*$'
            exception_name: '^[A-Z][a-zA-Z0-9]*Exception$'
            isser_method_name: '^(?:is|has|should|may|supports)'
        more_specific_types_in_doc_comments: true
        missing_arguments: true
        method_calls_on_non_object: true
        instanceof_class_exists: true
        foreach_usable_as_reference: true
        foreach_traversable: true
        fix_use_statements:
            remove_unused: true
            preserve_multiple: false
            preserve_blanklines: false
            order_alphabetically: false
        fix_line_ending: true
        fix_doc_comments: true
        encourage_shallow_comparison: true
        duplication: true
        deprecated_code_usage: true
        deadlock_detection_in_loops: true
        comparison_always_same_result: true
        code_rating: true
        closure_use_not_conflicting: true
        closure_use_modifiable: true
        check_method_contracts:
            verify_interface_like_constraints: true
            verify_documented_constraints: true
            verify_parent_constraints: true
        catch_class_exists: true
        call_to_parent_method: true
        avoid_superglobals: true
        avoid_length_functions_in_loops: true
        avoid_entity_manager_injection: true
        avoid_duplicate_types: true
        avoid_closing_tag: true
        assignment_of_null_return: true
        argument_type_checks: true

Обратите внимание, что проверки, описанные ниже, будут приводить к фейлу сборки, поэтому, если для вас некоторые из них не нужны, удалите или понизьте лимиты:

Проверки для сборок
build_failure_conditions:
  - 'project.metric_change("scrutinizer.quality", < -0.10)'
  - 'elements.rating(<= D).exists'
  - 'elements.rating(<= D).new.exists' 
  - 'issues.label("coding-style").exists' 
  - 'issues.label("coding-style").new.exists'              
  - 'issues.severity(>= MAJOR).new.exists'                                     
  - 'project.metric("scrutinizer.quality", < 9)'
  - 'patches.label("Doc Comments").exists'
  - 'patches.label("Spacing").exists' 

Хотел бы отметить, всегда указывайте ваше окружение (версию PHP, базы данных и тд), т.к. значения по умолчанию могут меняться и ваши сборки в один прекрасный день будут зафейлены. Что собственно и приключилось со мной буквально на днях, когда релизнулся PHP 8.0.1.

Настройка репозитория

По сути мы просто добавляем свой репозиторий с GitHub, для этого переходим по ссылке.

Пример окна добавления репозитория

Начинаете вводить название репозитория и автозаполнение автоматически выдаст все доступные публичные репозитории, указываете язык и все.

Далее идем в настройки вашего репозитория, которые находятся вот тут:
https://scrutinizer-ci.com/g/ваш-логин/название-репозитория/settings

Настройка Check Suite

Тут немного остановимся и я расскажу почему.

Дело в том, что сборки Scrutinizer довольно медленные, даже для одного окружения сборка с анализом и покрытием может длиться минут 20.

За это время ваши обычные проверки в GitHub CI уже могут быть пройдены, линтеры показали ваши ошибки или вы вспомнили, что что-то забыли, и успеели толкнуть пару-тройку коммитов до завершения сборки Scrutinizer.

Tracking Settings

По умолчанию каждый коммит будет добавлять в очередь сборку. Таким образом, чтобы дождаться заветной зеленой галочки в CheckSuite, придется ждать не один час, ну а если там ошибка или ваши сборки очень сложные, то и того дольше.

  • Pull-Request Tracking – отвечает за запуск сборок только для Pull-реквестов в основную ветку.

  • Pull-Request Notification – отвечает за то, как вы хотите узнавать о результатах сборки и анализа, например, через GitHub Check Suite.

  • Tracked Branches – отвечает за запуск сборок при пушах. Рекомендую, выставить опцию “Track only branches listed below” и указать вашу основную ветку.

Здесь находится пример с правильными настройками

Auto-Cancel Non-Finished Inspections

Если вы все же успели толкнуть пару коммитов до завершения сборок, эти настройки отменят предыдущие задания и сразу перезапустят их для вашего последнего коммита.

Это удобно, ведь нас не интересуют результаты билдов для промежуточных коммитов.

Здесь находится пример с правильными настройками

Настройка конфигурации репозитория

Переходим по ссылке:
https://scrutinizer-ci.com/g/ваш-логин/название-репозитория/settings/build-config

Важно выбрать вашу глобальную конфигурацию.

Пример, как задействовать глобальную конфигурацию
Пример конфигурации для проекта для Postgres
build:
    nodes:
        coverage:
            services:
                postgres: 12
            tests:
                override:
                    -
                        command: |
                            sed -e "s/${USERNAME}/scrutinizer/" 
                                -e "s/${PASSWORD}/scrutinizer/" 
                                -e "s/${DATABASE}/scrutinizer/" 
                                -e "s/${HOST}/127.0.0.1/" 
                                phpunit.xml.dist > phpunit.xml
                            ./vendor/bin/phpunit 
                                --verbose  
                                --stderr  
                                --coverage-clover build/logs/clover.xml 
                                --coverage-text
                        coverage:
                            file: build/logs/clover.xml
                            format: clover
        analysis:
            tests:
                override:
                    - php-scrutinizer-run
                    -
                        command: phpcs-run
                        use_website_config: true
    cache:
        disabled: true
        directories:
            - vendor/
filter:
    excluded_paths:
        - 'tests/*'

В некоторых случаях сборки могут падать из-за отсутствия phpcs в коде вашего репозитория, в таком случае добавьте этот файл.

phpcs.xml
<?xml version="1.0"?>
<ruleset>
    <file>./</file>
    <exclude-pattern>./vendor/*</exclude-pattern>
    <exclude-pattern>./tests/*</exclude-pattern>
    <exclude-pattern>./.github/*</exclude-pattern>
    <rule ref="PSR1" />
</ruleset>

А в ваш composer.json в секцию require-dev добавьте:

"squizlabs/php_codesniffer": "^3.5"

Начало работы

Теперь, давайте толкнем коммит в основную ветку и посмотрим, как выглядит Check Suite со Scrutinizer.

Пример корректной интеграции с GitHub

При желании эти проверки можно сделать обязательными (все или только часть) в настройках вашего репозитория на GitHub (в разделе настроек ограничений веток), – об этом я рассказывал в своем предыдущем посте про автоматизацию ручных действий с GitHub Actions.

Интерактив от Scrutinizer в ревью

После интеграции и успешно пройденной сборки в Scrutinizer появится три кнопки: Code Intelligence, Issues и Coverage.

По сути это визуализированный результат анализа вашего кода, очень помогает ревьюить, наверное…

А покрытие кода выглядит примерно так

При наведении на методы и переменные Code Intelligence подсвечивает типы возвращаемых значений, а зеленые маркеры справа от нумератора строк сообщают о покрытии тестами.

В целом, это удобно, хотя я к Code Intelligence еще не привык.

Итог

Я буду рад, если мой опыт был вам полезен и вот такие красивые отчеты вас будут мотивировать писать совершенный код.

Если у вас что-то не получилось с первого раза, не отчаивайтесь.

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

Ну а если, вы все же отчаялись и у вас ничего не получилось, мои контакты открыты для вас, напишите мне, и мы вместе решим вашу проблему.

Let’s block ads! (Why?)

Read More

Recent Posts

VK купила 40% билетной платформы Intickets.ru

VK объявляет о приобретении 40% компании Intickets.ru (Интикетс). Это облачный сервис для контроля и управления продажей билетов на мероприятия. Сумма…

2 дня ago

OpenAI готовится запустить поисковую систему на базе ChatGPT

OpenAI готовится запустить собственную поисковую систему на базе ChatGPT. Информацию об этом публикуют западные издания. Ожидается, что новый поисковик может…

2 дня ago

Роскомнадзор рекомендовал хостинг-провайдерам ограничить сбор данных с сайтов для иностранных ботов

Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…

3 дня ago

Apple возобновила переговоры с OpenAI и Google для интеграции ИИ в iPhone

Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…

1 неделя ago

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

1 неделя ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

1 неделя ago