{"id":168801,"date":"2021-02-02T16:00:06","date_gmt":"2021-02-02T13:00:06","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/"},"modified":"2021-02-02T16:00:06","modified_gmt":"2021-02-02T13:00:06","slug":"how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/","title":{"rendered":"#How to Create A GitLab CI Pipeline to Statically Analyse PHP Projects \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_89 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6adf21dd02cb2\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6adf21dd02cb2\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/#Getting_Setup_with_PHPStan\" >Getting Setup with PHPStan<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/#Configuring_GitLab_for_CI\" >Configuring GitLab for CI<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/#Creating_a_GitLab_CI_Pipeline\" >Creating a GitLab CI Pipeline<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/#Using_the_Pipeline\" >Using the Pipeline<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/#Using_with_Merge_Requests\" >Using with Merge Requests<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects-cloudsavvy-it\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How to Create A GitLab CI Pipeline to Statically Analyse PHP Projects \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9359\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/cb9abbff1c411fb53abc687fed1ef0be\/p\/uploads\/2021\/01\/0ee9c227.jpg\" alt=\"Image with the GitLab and PHPStan logos\" width=\"1600\" height=\"900\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>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\u2019s how to run PHPStan within your GitLab CI pipelines.<\/p>\n<p>It\u2019s good to run PHPStan regularly while you\u2019re building out new features. Using it locally only takes you so far though. You\u2019re reliant on your other team members being as disciplined as you are. Integrating static analysis into a CI\/CD workflow ensures code can\u2019t be merged if it would break your project\u2019s main branch.<\/p>\n<h2 id=\"getting-setup-with-phpstan\"><span class=\"ez-toc-section\" id=\"Getting_Setup_with_PHPStan\"><\/span>Getting Setup with PHPStan<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You first need to add PHPStan into your project. We\u2019ve already got a detailed guide on installing and configuring PHPStan, so we\u2019ll only cover the basics here.<\/p>\n<p>First, use Composer to install PHPStan:<\/p>\n<pre>composer require --dev phpstan\/phpstan<\/pre>\n<p>Next, create a basic <code>phpstan.neon<\/code> configuration file in your project:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co4\">parameters<\/span>:<span class=\"co3\">\n  level<\/span><span class=\"sy2\">: <\/span>max<span class=\"co4\">\n  paths<\/span><span class=\"sy2\">:\n<\/span>    - src\n    - tests<span class=\"co3\">\n  tmpDir<\/span><span class=\"sy2\">: <\/span>.tmp<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>The temporary directory is overridden to assist GitLab CI\u2019s caching, setup below.<\/p>\n<p>You can now run PHPStan locally to check your configuration works:<\/p>\n<pre>vendor\/bin\/phpstan analyse<\/pre>\n<p>At this stage, it doesn\u2019t matter whether the tests pass.<\/p>\n<h2 id=\"configuring-gitlab-for-ci\"><span class=\"ez-toc-section\" id=\"Configuring_GitLab_for_CI\"><\/span>Configuring GitLab for CI<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Make sure you\u2019ve pushed your code to a project on your GitLab server. You\u2019ll need to check the Pipelines feature is enabled for your project \u2013 if you see \u201cCI \/ CD\u201d in the left sidebar, you\u2019re good to go.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9365\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/8a42c4dfa87837596dee1bc377599a4d\/p\/uploads\/2021\/01\/7c08cc9a.jpg\" alt=\"Screenshot of Pipelines menu item in GitLab\" width=\"472\" height=\"230\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>To enable your project\u2019s CI system, click the \u201cSettings\u201d button in the sidebar. Expand the \u201cVisibility, project features, permissions\u201d section and enable the \u201cPipelines\u201d feature.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9364\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/e5004c45eede86557ba026fab68255c9\/p\/uploads\/2021\/01\/9717c923.jpg\" alt=\"Screenshot of enabling Pipelines in GitLab\" width=\"982\" height=\"732\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>If you use GitLab\u2019s 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 \u201cMerge requests\u201d settings section and check the \u201cPipelines must succeed\u201d toggle button. Click \u201cSave\u201d to confirm. This will stop you accidentally merging an MR when PHPStan fails against its changes.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9363\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/7ee84096625f89174500fddbccf90b56\/p\/uploads\/2021\/01\/2768a828.jpg\" alt=\"Screenshot of enabling GitLab's MR required pipelines\" width=\"757\" height=\"411\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>To use GitLab CI, you\u2019ll 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.<\/p>\n<p>We\u2019re 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\u2019re on a self-managed instance and need to configure a new Runner, follow the guidance in our article on setting up GitLab CI.<\/p>\n<h2 id=\"creating-a-gitlab-ci-pipeline\"><span class=\"ez-toc-section\" id=\"Creating_a_GitLab_CI_Pipeline\"><\/span>Creating a GitLab CI Pipeline<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>GitLab CI is configured using a <code>.gitlab-ci.yml<\/code> file at the root of your project. CI pipelines support multiple sequential stages. Each stage\u2019s jobs run in parallel. For our purposes of running PHPStan, we need a single stage which runs one job.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co4\">stages<\/span><span class=\"sy2\">:\n<\/span>  - phpstan\n<span class=\"co4\">\ncache<\/span>:<span class=\"co3\">\n  key<\/span><span class=\"sy2\">: <\/span>$CI_COMMIT_REF_SLUG<span class=\"co4\">\n  paths<\/span><span class=\"sy2\">:\n<\/span>    - .tmp\/\n    - vendor\/\n<span class=\"co4\">\nphpstan<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>phpstan<span class=\"co3\">\n  image<\/span><span class=\"sy2\">: <\/span>ghcr.io\/phpstan\/phpstan<span class=\"co4\">\n  <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">script<\/a><\/span><span class=\"sy2\">:\n<\/span>    - analyse --no-progress --error-format gitlab &gt; phpstan.json<span class=\"co4\">\n  artifacts<\/span>:<span class=\"co3\">\n    when<\/span><span class=\"sy2\">: <\/span>always<span class=\"co4\">\n    reports<\/span>:<span class=\"co3\">\n      codequality<\/span><span class=\"sy2\">: <\/span>phpstan.json<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>This GitLab CI file contains all we need to run PHPStan within our pipeline. We define a stage, <code>phpstan<\/code>, containing a job that\u2019s also called <code>phpstan<\/code>. The job uses the official PHPStan Docker image from the GitHub container registry.<\/p>\n<p>The GitLab CI cache is configured to cache the <code>.tmp<\/code> and <code>vendor<\/code> directories. This will improve the performance of subsequent runs on the same branch. The cache will get restored automatically. Back in our <code>phpstan.neon<\/code>, we set the <code>tmpDir<\/code> to <code>.tmp<\/code> for this reason \u2013 it means we can now confidently reference it in the CI pipeline\u2019s caching configuration.<\/p>\n<p>We also cache <code>vendor<\/code> to avoid needlessly reinstalling Composer dependencies on each run. Note that you don\u2019t need to run <code>composer install<\/code> manually \u2013 the official PHPStan Docker image invokes it automatically.<\/p>\n<p>The <code>--error-format<\/code> flag is passed to PHPStan\u2019s <code>analyse<\/code> command. This configures PHPStan to create a JSON file in the format accepted by GitLab\u2019s code quality report. Down in the <code>artifacts<\/code> section, this file gets uploaded to GitLab after the job completes.<\/p>\n<h2 id=\"using-the-pipeline\"><span class=\"ez-toc-section\" id=\"Using_the_Pipeline\"><\/span>Using the Pipeline<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Commit your <code>.gitlab-ci.yml<\/code> and push to your GitLab server. The CI system should now kick in and create your first pipeline. Use the \u201cCI \/ CD\u201d link in the left navigation to view the pipeline\u2019s progress.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9362\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/8cf98c5d092e719868c2132dcbe2ce4c\/p\/uploads\/2021\/01\/bb5ea6a1.jpg\" alt=\"Screenshot of PHPStan GitLab CI pipelines\" width=\"1466\" height=\"398\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>If you get a green tick, PHPStan\u2019s tests passed! Your branch is in a good state and it\u2019s ready to merge. If a red cross appears, you\u2019ve got more work to do. PHPStan and GitLab CI just stopped you merging potentially broken code.<\/p>\n<p>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.<\/p>\n<h2 id=\"using-with-merge-requests\"><span class=\"ez-toc-section\" id=\"Using_with_Merge_Requests\"><\/span>Using with Merge Requests<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Reading the JSON manually doesn\u2019t make for a great experience. However, GitLab\u2019s 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.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9361\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/15717e02c770d624810e001b6c5ba1eb\/p\/uploads\/2021\/01\/7836165b.jpg\" alt=\"Screenshot of GitLab Code Quality Merge Request widget\" width=\"983\" height=\"475\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Merge requests with a failing pipeline should display an expandable \u201cCode quality\u201d section. This indicates the number of errors encountered. Expand the section to view a complete list of problems found by PHPStan.<\/p>\n<p>Once you\u2019ve addressed the issues, push your changes up to GitLab. The pipeline will run again. Once it\u2019s completed, you\u2019ll see the new status on the Pipelines screen and in your merge request\u2019s code quality widget.<\/p>\n<h2 id=\"conclusion\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>PHPStan helps you write better PHP that\u2019s 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\u2019t be ignored or circumvented.<\/p>\n<p>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\u2019t enter your main branch without passing a PHPStan run. PHPStan\u2019s full support for GitLab\u2019s code quality reports make it easy to assess errors without leaving the web UI, helping you rapidly fix any problems which are uncovered.\n<\/p><\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/9353\/how-to-create-a-gitlab-ci-pipeline-to-statically-analyse-php-projects\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How to Create A GitLab CI Pipeline to Statically Analyse PHP Projects \u2013 CloudSavvy IT&#8221; 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\u2019s how to run PHPStan within your GitLab CI pipelines. It\u2019s&#8230;<\/p>\n","protected":false},"author":1,"featured_media":168802,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/01\/0ee9c227.jpg","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-168801","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/168801","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=168801"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/168801\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/168802"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=168801"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=168801"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=168801"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}