My weekend release snafu
- Jason Bahl
sna•fu noun a confused or chaotic state; a mess.
This past weekend I released v1.2.0 of WPGraphQL.
And 1.2.1, and 1.2.2, and 1.2.3, and 1.2.4, and 1.2.5.
I made some changes to the Github repo that caused deploys to not behave as intended, and to call it a “snafu” might be an understatement.
For the first 4 years of WPGraphQL, the plugin was not distributed on the WordPress.org plugin repository, one of the most common distribution channels for WordPress plugins. The plugin has been versioned on Github and primarily distributed on Github and Packagist.org. Users that wanted to install WPGraphQL would either clone the plugin or download the zip from Github, or use Composer to install the plugin from packagist.org.
Since downloading a Zip from Github was a pretty common way for folks to get the plugin, and I wanted users to be able to download the Zip, install it to WordPress and be immediately productive, without having to run composer commands to install dependencies. So, I made the decision to version the plugins external dependencies in the repository, even against the advice of Composer.
For quite some time the plan was to deploy the plugin to WordPress.org after the v1.0 release, and then stop versioning the Composer dependencies as Github would no longer be the primary method of distribution.
WPGraphQL reached v1.0 in November and has been distributed on WordPress.org since, so I began to work on implementing the plan to no longer version the vendor dependencies in the Git repo.
I already had a Github Workflow that installed the vendor dependencies and deployed to WordPress.org using the fantastic WordPress deploy action from 10up.
This workflow was in place starting in v1.0 of the plugin.
The workflow installs composer dependencies, then deploys the plugin to WordPress.org.
I was pretty sure that since the Workflow already included the
composer install --no-dev step prior to the deploy action that I was already good to go. All I needed to do was add a new part of the workflow to create a Zip file of the plugin, including the installed dependencies, and upload that compiled Zip to the release as a release asset, so that users that still want to be able to download a zip from Github could do so.
I added that new part of the workflow.
The next step was remove the vendor directory and tell
.gitignore that I no longer want to version that directory. This would allow me and other contributors to install the vendor dependencies while working locally, but not worry about committing them to the repo. So, I updated the .gitignore to ignore the vendor directory.
I released v1.2.0. And shortly after was told that it was breaking things for users.
Users were reporting seeing the following screen:
I checked out the deploy action to see if it failed for some reason.
Updating Deploy Action
Github was reporting that my arguments for the “generate-zip” option on the 10up deploy action were not accurate.
I thought perhaps this was maybe causing something to not work quite right. So I checked the 10up action docs and it appeared this option perhaps wasn’t needed, so I removed the option, re-released, and watched the deploy process.
Still no luck. WordPress.org was missing files.
The error that was reported to me made it clear that WordPress.org was excluding the vendor directory from the plugin, but I wasn’t sure why, as the workflow runs
composer install before deploying.
I dug into the code for the 1oup action, and realized that if a
.distignore isn’t present, then tit uses the
git archive command, which ignores files from the `.gitignore` and the `.gitattributes` files.
This means that when I added the
vendor directory to the
.gitignore file to stop versioning the directory, the deploy action was leaving that directory out of what gets deployed to WordPress.org. So my step in the workflow that runs
composer install was being nullified by the update to the
I did more investigating and found that the 10up action reads the
.distignore file, if it exists. This was the missing piece!
I can use a
.gitignore to ignore files used in local development from being versioned in Git, but separately configure what to ignore for distribution.
So, I added a
.distignore file that ignores a lot of files that are useful for development but are not needed to run the plugin, and I configured this file to NOT ignore the
Now the plugin was deploying to WordPress.org with the vendor dependencies.
Fixed! But, still broken.
I had confirmation that installing from WordPress.org was working for users. It was fixed!
But now I was now getting reports that users installing the plugin from Composer, specifically as a dependency of Trellis / Bedrock were running into the same
wp_die() screen that folks reported seeing when installing from WordPress.org where the vendor directory was missing.
So this seemed to mean that installing the plugin from Composer was also excluding the vendor dependencies?
I spun up a Trellis environment locally. It was super easy by the way – I typically use localwp.com for my local WordPress installs, but Trellis made it a breeze to get a local WordPress install running. Kudos to Ben and the other contributors of the project! ????.
From my Trellis-built WordPress environment, I installed WPGraphQL from WordPress.org, and it worked fine. ????
I deleted the plugin and installed from wpackagist (a wordpress specific Composer repository) and it worked fine. ????
But then, I installed the plugin from packagist.org, and I was met with the
wp_die() screen others had reported. ????
It turns out that Composer installs the dependencies in the vendor directory of the parent project. I knew this, but my brain didn’t want to connect these dots.
This means that this code here was problematic.
Since the vendor directory was previously always installed in the
wp-graphql/vendor directory, as it was versioned with the plugin, the
file_exists() check was always true.
Now that the vendor directory isn’t versioned in the plugin, it can be installed anywhere within the project, so this check isn’t always true anymore.
When installing WPGraphQL from Packagist, the dependencies are not going to be installed in the
wp-graphql/vendor, but instead in the
vendor directory of the project that’s including WPGraphQL as a dependency.
So, I was able to update this part of the code to use the autoload from the WPGraphQL plugin if it exists, which it will when installing from WordPress.org or downloading the Zip from the Github release, and otherwise check for the existence of the dependency class (
GraphQL\GraphQL) to make sure dependencies are installed whether in the plugin or the parent project.
Back in business!
Now, the plugin deploys to WordPress.org fine, can be installed with Composer from WPackagist and Packagist, and follows the recommendation of Composer to not version the dependencies in the Git repo.