Semantic Versioning : Version 0 is unstable

We’ve been using Semantic Versioning for quite a while at work now.  It’s easy to explain and follow, and it provides valuable context to the numerous releases of the projects and components that we are doing on a daily basis.

Turns out, however, that I missed a small, but important part of the standard.  All releases in major version 0 are considered to be unstable, so even if they introduce backward compatibility breaking changes, there is no need to increment the major version to 1.  Here’s the relevant quote:

Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.

If you are relying on the semantic versioning in your projects, make sure to check your dependency management tool, to verify that it handles major version 0 correctly.  Gladly, for us, composer does the job:

The ^ operator behaves very similarly but it sticks closer to semantic versioning, and will always allow non-breaking updates. For example ^1.2.3 is equivalent to >=1.2.3 <2.0.0 as none of the releases until 2.0 should break backwards compatibility. For pre-1.0 versions it also acts with safety in mind and treats ^0.3 as >=0.3.0 <0.4.0.

 

composer-plugin-qa – Composer Plugin for PHP Quality Assurance Tools

composer-plugin-qa is a Composer plugin which adds all the most popular PHP quality assurance tools as composer scripts, so that you don’t have to install and set them up one by one.  The list of tools includes the following:

  • PHPUnit: Testing Framework
  • PHPCOV: CLI frontend for the PHP_CodeCoverage
  • Paratest: Parallel testing for PHPUnit
  • DbUnit: Puts your database into a known state between test runs
  • PHPLOC: A tool for quickly measuring the size of a PHP project
  • PHPCPD: Copy/Paste Detector
  • PHP_Depend: Quality of your design in the terms of extensibility, reusability and maintainability
  • PHPMD: User friendly frontend application for the raw metrics stream measured by PHP Depend
  • PhpMetrics: Static analysis tool, gives metrics about PHP project and classes
  • PHP_CodeSniffer: Detects violations of a defined set of coding standards
  • PHP-CS-Fixer: A tool to automatically fix coding standards issues
  • Security-Checker: Checks if your application uses dependencies with known security vulnerabilities

This list is very similar to the one in my other recent post.

Have you tried Composer Scripts? You DO not need Phing.

Have you tried Composer Scripts? You may not need Phing.” is a nice blog post showing how to use Composer scripts to solve simple build and deployment automation.  There’s plenty of good advice in there.

However I have one issue with it.  It’s the “You may not need Phing.” part.  Irrelevant of your use of Composer scripts, you DON’T need Phing.  Phing had its time.  It was one of the first build and deployment tools for PHP and it was better than all the alternatives at the time (manual builds, custom shell scripts, or tools from other programming languages).

Those days are long gone and we have better tools now.  If you are still using (or even considering using Phing), I beg you to look another way.  Check out Deployer.  Check out Robo.li.  Check other alternatives.  Don’t use Phing.

What’s wrong with Phing? Well, I can sum it up in one and one reason only.  It’s XML-based.  Yeah, that’s right.  Phing routes come from Apache Ant, which is a very common build tool for the Java world.  And Java world is full of XML.

In the year of 2018, we’ve figured out better ways.  Both JSON and YAML are better alternatives to XML for both humans and machines.  JSON and YAML are easier to read and generate.

Furthermore, even XML is not the most appropriate format for what Phing is working with.  Sure, as long as you can stick with the basic configuration of existing tasks and options – it doesn’t make much difference.  But at some point, you’ll need to extend and customize your build and deployment process.  And you’ll eventually end up writing PHP code using XML syntax.  And trust me, there is no fun in that at all.

Use PHP to write PHP code.  Use PHP tools for your PHP projects.  We have these now and they are great.  At work we are using Robo.li very extensively and it works amazing!  You don’t have to use it.  Pick whatever works for you.  But if Phing works for you, you’re probably doing something wrong.

Oh, and yes, Composer scripts are awesome too.  Try them out, if you haven’t already.

Updating WordPress with Composer and WP-CLI

The other day I came across this blog post by Mark Jaquith, who is one of the lead contributors to WordPress, in which he describes his process of updating WordPress plugins with WP-CLI and Git.  I think a lot of people these days are trying to use Git for version control and automate their deployments, so WordPress developers aren’t an exception, and Mark’s post is a useful resource for that.

With that said, however, I think there is a better.  At work, we’ve been dealing with quite a few WordPress-based projects, and automation of builds and deploys is very important to us.  So we’ve taken a different approach.

The initial inspiration for our approach was taken from this blog post by Scott Walkinshaw of the amazing Roots team.

Yes, that’s right, we use Composer to manage the WordPress, plugins and themes, both during the initial installation and the upgrades later.  But we’ve taken it a step further by also integrating the WP-CLI to our setup, which you can find in our project-template-wordpress GitHub repository.

I have oversimplified both the development and deployment process below, mostly for clarity.   (We do a lot more automation for our needs.)

During the development:

  1. Configure Composer to install WordPress into the webroot/wp folder.
  2. Configure Composer to install plugins and themes into webroot/wp-content folder. (Notice: we use a different wp-content folder location from the default WordPress one).
  3. Adjust wp-config.php for the new paths and drop it into the webroot/ folder.
  4. Add Composer’s vendor/ folder, and both webroot/wp and webroot/wp-content to .gitignore.
  5. Add all required themes and plugins to the composer.json.
  6. Run composer update to create or update the composer.lock file.
  7. Commit both composer.json and composer.lock, as well as .gitignore and any other files you modified.
  8. Add a WP-CLI script that automates activation of plugins and sets the current theme.
  9. Push your changes to the git repository.

During the deployment:

  1. Clone or pull the changes from the git repository.
  2. Run composer install to fetch and install specific versions of WordPress, plugins, and themes, from the composer.lock file.
  3. Run the WP-CLI script to finalize the installation or update with the plugin activation, theme selection, etc.

While it might look a little bit more complicated than what Mark and Scott described in their respective blog posts, I think this is a better approach for the following reasons:

  1. Use a specialized tool to solve each problem.   Git is great for version control, so that’s what it should do.  Composer is great for managing dependencies, and that’s what WordPress and its themes and plugins are for your project.  WP-CLI is great for automating WordPress tasks.
  2. Keep the git repository clean and simple.  When working on a project, we never ever modify the code of the WordPress or any of its themes or plugins.  And our setup enforces this approach.  If you need to change the WordPress source code for a particular project, you are probably doing something wrong.  If you need to change the plugin’s source code or the theme’s source code, you are probably doing something wrong again.  Instead create child theme or your own version of the plugin and install those with Composer, keeping the plugin or theme related code changes in a separate repository.
  3. Easily extendable and customizeable.  Git, composer, and WP-CLI are great tools and we love using them.  But the world is moving forward and there are constantly more and better tools to help with the complexities of the web development.  Our setup expands and extends to welcome any tools that we find useful.  For example, we have integrated with Robo, PHPUnit and PHP Code Sniffer, TravisCI, BitBucket Pipelines, and many other tools over time.  We’ve also said good bye to a few that became obsolete or to which we found better alternatives.

Anyways, project-template-wordpress works quite well for us and I hope you’ll find it useful.  Give it a try and let us know if you find any issues or improvements.   Pull Requests are welcome. :)

Composer Local Packages for Dummies

Composer (in combination with Packagist) is one technology that has significantly changed the ecosystem of the PHP programming language.  Anybody working with PHP in this day and age MUST know how to use composer.  However, not everyone does.  So here is a nice tutorial on how to get started with Composer if you already have a large legacy application that you want to split into packages and use composer to manage them – Composer Local Packages for Dummies.

17 Tips for Using Composer Efficiently

Martin Hujer has collected 17 tips for using composer efficiently, and then added a few more after receiving the feedback on the blog post.  I was familiar with most of these, but there are still a few that are new to me.

Tip #7: Run Travis CI builds with different versions of dependencies

I knew about the Travis CI matrix configuration, but used it only for other things.  I’ll be looking into extending it for the composer tests shortly.

Tip #8: Sort packages in require and require-dev by name

This is a great tip!  I read the composer documentation several times, but somehow I missed this option.  It is especially useful for the the way we manage projects at work (waterfall merges from templates and basic projects into more complex ones).

Tip #9: Do not attempt to merge composer.lock when rebasing or merging

Here, I’m not quite sure about the whole bit on git attributes.  Having git try to merge and generate a conflict creates a very visible problem.  Avoiding the merge might hide things a bit until they popup much later in the CI.  I guess I’ll have to play around with this to make up my mind.

Tip #13: Validate the composer.json during the CI build

This is a great tip!  I had plenty of issues with composer validations in the past.  Currently, we have a couple of unit tests that make sure that composer files are valid and up-to-date.  Using a native mechanism for that is a much better option.

Tip #15: Specify the production PHP version in composer.json

This sounds like an amazing feature which I once again missed.  Especially now that we are still migrating some projects from PHP 5.6 to PHP 7.1, and have to sort out dependency conflicts between the two versions.

Tip #20: Use authoritative class map in production

We are already almost doing it, but it’s a good opportunity to verify that we utilize the functionality correctly.

 

Dependency Management and WordPress: A Proposal

I came across this article – “Dependency Management and WordPress: A Proposal“, which provides an excellent overview of some of the recent developments and discussions in the area of composer integration with WordPress, and even more generically, some of the issues around dependency management in an ecosystem as large and complex as that of WordPress.

It’s been a while since I checked what’s going on in this area.  A couple of years back, I linked to an article that shows a way to use composer with WordPress, and since then I’ve built something similar for our use at work.

But it’s good to see that the problem is not tossed and forgotten, and that there are some very smart people still trying to work it out.

composer-git-hooks – manage git hooks in your composer config

composer-git-hooks looks awesome!  From the project page description:

Manage git hooks easily in your composer configuration. This package makes it easy to implement a consistent project-wide usage of git hooks. Specifying hooks in the composer file makes them available for every member of the project team. This provides a consistent environment and behavior for everyone which is great.

Validating JSON against schema in PHP

GitHub was rather slow yesterday, which affected the speed of installing composer dependencies (since most of them are hosted on GitHub anyway).  Staring at a slowly scrolling list of installed dependencies, I noticed something interesting.

...
  - Installing seld/jsonlint (1.6.0)
  - Installing justinrainbow/json-schema (5.1.0)
...

Of course, I’ve heard of the seld/jsonlint before.  It’s a port of zaach/jsonlint JavaScript tool to PHP, written by Jordi Boggiano, aka Seldaek, the genius who brought us composer dependency manager and packagist.org repository.

But JSON schema? What’s that?

The last time I heard the word “schema” in a non-database context, it was in the XML domain.  And I hate XML with passion.  It’s ugly and horrible and should die a quick death.  The sooner, the better.

But with all its ugliness, XML has does something right – it allows the schema definition, against which the XML file can be validated later.

Can I have the same with JSON?  Well, apparently, yes!

justinrainbow/json-schema package allows one to define a schema for what’s allowed in the JSON file, and than validate against it.  And even more than that – it supports both required values and default values too.

Seeing the package being installed right next to something by Seldaek, I figured, composer might be using it already.  A quick look in the repository confirmed my suspicion.  Composer documentation provides more information, and links to an even more helpful JSON-Schema.org.

Mind.  Officially.  Blown.

At work, we use a whole lot of configuration files for many of our projects.  Those files which are intended for tech-savvy users, are usually in JSON or PHP format, without much validation attached to them.   Those files which are for non-technical users, usually rely on even simpler formats like INI and CSV.  I see this all changing and improving soon.

But before any of that happens, I need to play around with these amazing tools.  Here’s a quick first look that I did:

  1. Install the JSON validator: composer require justinrainbow/json-schema
  2. Create an example config.json file that I will be validating.
  3. Create a simple schema.json file that defines what is valid.
  4. Create a simple index.php file to tie it altogether, mostly just coping code from the documentation.

My config.json file looks like this:

{
	"blah": "foobar",
	"foo": "bar"
}

My schema.json file looks like this:

{
	"type": "object",
	"properties": {
		"blah": {
			"type": "string"
		},
		"version": {
			"type": "string",
			"default": "v1.0.0"
		}
	}
}

And, finally, my index.php file looks like this:

<?php
require_once 'vendor/autoload.php';

use JsonSchema\Validator;
use JsonSchema\Constraints\Constraint;

$config = json_decode(file_get_contents('config.json'));
$validator = new Validator; $validator->validate(
	$config,
	(object)['$ref' => 'file://' . realpath('schema.json')],
	Constraint::CHECK_MODE_APPLY_DEFAULTS
);

if ($validator->isValid()) {
	echo "JSON validates OK\n";
} else {
	echo "JSON validation errors:\n";
	foreach ($validator->getErrors() as $error) {
		print_r($error);
	}
}

print "\nResulting config:\n";
print_r($config);

When I run it, I get the following output:

$ php index.php 
JSON validates OK

Resulting config:
stdClass Object
(
    [blah] => foobar
    [foo] => bar
    [version] => v1.0.0
)

What if I change my config.json to have something invalid, like an integer instead of a string?

{
	"blah": 1,
	"foo": "bar"
}

The validation fails with a helpful information:

$ php index.php 
JSON validation errors:
Array
(
    [property] => blah
    [pointer] => /blah
    [message] => Integer value found, but a string is required
    [constraint] => type
)

Resulting config:
stdClass Object
(
    [blah] => 1
    [foo] => bar
    [version] => v1.0.0
)

This is great. Maybe even beyond great!

The possibilities here are endless.  First of all, we can obviously validate the configuration files.  Secondly, we can automatically generate the documentation for the supported configuration options and values.  It’s probably not going to be super fantastic at first, but it will cover ALL supported cases and will always be up-to-date.  Thirdly, this whole thing can be taken to the next level very easily, since the schema files are JSON themselves, which means schema’s can be generated on the fly.

For example, in our projects, we allow the admin/developer to specify which database field of a table is used as display field (in links and such).  Only existing database fields should be allowed.  So, we can generate the schema with available fields on project deployment, and then validate the user configuration against his particular database setup.

There are probably even better ways to utilize all this, but I’ll have to think about it, which is not easy with the mind blown…

Update (March 16, 2017): also have a look at some alternative JSON Schema validators.  JSON Guard might be a slightly better option.

Composer require inline alias

Here’s a feature of composer that I didn’t know about until a few days ago – require inline alias.  Here’s the example from the documentation:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/you/monolog"
        }
    ],
    "require": {
        "symfony/monolog-bundle": "2.0",
        "monolog/monolog": "dev-bugfix as 1.0.x-dev"
    }
}

This is super useful when you have dependencies in your project that require a particular version of a third-party library or plugin, and you want to try a branch of that library or plugin. Switching to the branch alias doesn’t solve the problem, as everything that has version constraints on that requirement, will complain. With inline alias, you can alias a particular branch of the dependency as a particular version.

With inline alias, composer will fetch the branch that you want, but will assume that that branch works as a particular version that you specify, and thus satisfy all the other dependencies that require that particular version.

In my particular case, I was working on the CakePHP-based application, which was using a few CakePHP plugins (installed via composer).  Those plugins require CakePHP v3+.  I wanted to test a branch of CakePHP which had a particular fix I was interested in, but without disabling all the plugins.  Switching my application’s composer to require a branch dissatisfied all the plugins, as now composer didn’t know if the branch that I am requiring is of the CakePHP v3 or not.  Aliasing the branch to v3.4.1 (current stable version at the time) worked like a charm.