Using Laminas Continuous Integration

Continuous Integration (CI) involves the frequent merging of code updates from developers into a shared codebase. This can be done as often as those updates are ready to be reviewed. Once the CI process is finalized, Continuous Delivery (CD) automatically deploys the code to the production environment. This flow streamlines the development process for faster and more reliable releases.

If you only have a handful of codebases, you may be able to handle maintenance manually, but an automated solution is readily available. Take the Laminas Project, for example. It has around 200 repositories across the Laminas and Mezzio organizations. Maintaining all of that code, from bug fixes to patches, from improvements to releases is a titanic task. Laminas CI is designed to help maintainers and developers review, merge and release updates rapidly and with fewer headaches. Wouldn't you rather sleep soundly at night knowing that your code has been checked by a tireless, objective reviewer? Laminas CD will be the topic of a future article, so let's focus on Laminas CI.

Can I use Laminas CI in my own projects?

Of course! Any project or package can benefit from a robust CI pipeline, and the Laminas CI workflows have been designed to be universal and easy to install. You can grab it from GitHub Marketplace.

We will cover the implementation in the next chapter. Dotkernel API is one of the several organizations that use Laminas components, so it makes perfect sense to trigger Laminas CI for each code update; you can read more about Dotkernel API Workflows. Another example of Laminas CI integration is php/pie PHP Installer for Extensions using Laminas CI.

How to implement the Laminas CI pipeline

A generic approach to CI is to use GitHub CI/CD, a built-in continuous integration, delivery, and deployment feature of GitHub that allows you to configure your own pipeline of jobs, stages and scripts. This still means that you have to know what you are doing, so an excellent choice is the Laminas CI implementation which does most of the heavy lifting for you. It generates a matrix of jobs for GitHub Actions based on your project configuration, runs the jobs and provides feedback.

Create the file .github/workflows/continuous-integration.yml using the content below. In this example, the workflow will run for all pull requests, pushes to any branch, and newly published tags. You can check out the documentation on the GitHub Workflow Documentation page.

name: "Continuous Integration"

on:
  pull_request:
  push:
    branches:
    tags:

jobs:
  ci:
    uses: laminas/workflow-continuous-integration/.github/workflows/continuous-integration.yml@1.x

When pushing PHP code for review, Laminas CI generates a series of automated processes which are designed to:

  • Check code style and formatting using PHP Code Sniffer based on the presence of phpcs.xml (phpcs.xml.dist can also be used).
  • Run the battery of tests using PHPUnit based on phpunit.xml (phpunit.xml.dist can also be used).
  • Run static analysis to detect bugs and check that best programming practices are respected using psalm based on psalm.xml (psalm.xml.dist can also be used).
  • Run yamllint and markdownlint for docs/book/**/*.md files and mkdocs.yml.

A full list of its capabilities is listed on the Laminas CI Automation README. Check it out to see what items it can identify based on the configuration files you include in your project.

Based on your project and the files you update in a given push, you can expect to see a job matrix like the one below:

  • Documentation Linting [8.2, latest]
  • MkDocs Linting [8.2, latest]
  • PHPUnit [8.2, lowest]
  • PHPUnit [8.2, latest]
  • PHPUnit [8.3, lowest]
  • PHPUnit [8.3, latest]
  • PHPUnit [8.4, latest]
  • PHPCodeSniffer [8.2, latest]
  • Psalm [8.2, latest]

Note that the job matrix generator is smart enough to ignore jobs that are not relevant to the affected items in your changes; if you only updated markdown files, then only markdown linting jobs will be run, or, if you've updated PHP code, your PHPUnit test suite will be run for all supported PHP versions listed in your composer.json. This ensures that the job matrix is as effective and efficient as possible, while still offering a solid review.

Each of the above jobs takes its configuration settings straight from your project:

  • PHP version
  • Additional extensions
  • php.ini settings
  • dependency - lowest, locked, or latest

Once the job has the above values, it runs a command which is the actual QA check.

The automated process returns a result for each job. If you get any errors, the job is marked as failed. You may be able to fix some of the errors automatically in your local code e.g. via phpcs and psalm specific commands (phpcbf and psalter, respectively) while others need to be investigated manually. Only when all errors are resolved do you get the coveted green check mark. And a good night's sleep, of course.

Conclusions

Using Laminas CI in a CI pipeline can be beneficial for any framework or library, given its broad range. It usually takes less than a minute to receive the feedback that turns iterating on patches into a breeze, meaning you can release easily and release often. Its high value is guaranteed by the authors of the Mezzio microframework and Laminas components, the people who best understand the ins and outs of those code bases. They expanded their initial CI workflow multiple times, based on their needs, while ensuring that the flow has universal application for any PHP project.

  • The CI pipeline can be optimized for PHP-specific tasks because Laminas is designed specifically for PHP applications. The tasks range from dependency management with Composer, to code style checks, to running PHPUnit tests.
  • Seamless integration with GitHub Actions
  • Composer integration ensures consistent dependency management across different environments, from development to production, which is crucial for maintaining stability and reliability.
  • Laminas encourages modern PHP practices by enforcing PSR (PHP Standard Recommendation) compliance and the use of dependency injection.
  • Extensive Documentation and Community Support

More on the topic:

Back to blog posts