How one line in a script can save you hours of debugging agony.
I recently ran into an issue with a CraftCMS plugin where the plugin worked locally but displayed bizarre behavior (404ing on a certain page) on our staging environment. It was a heck of a bug–there were few error messages and the ones that I saw didn’t seem to be related to the plugin.
I tried deactivating and reactivating the plugin. I tried upgrading and downgrading the plugin. I tried switching the local environment to more closely mimic the staging environment.
Nothing solved the problem.
I reached out to the plugin maintainers with a video of the issue and they suggested that an old version of the plugin was somehow executing, because in the video they didn’t see new features.
I double checked that I had the latest version of the plugin, both in composer.json and in the plugin screen of the CraftCMS control panel. Yup.
Finally, in despair I thought “let’s delete the vendor directory and reinstall all the plugins and see what happens.” The vendor directory is where all third party composer managed dependencies live. It should be totally disposable, but the host that we are using for our applciation has persistent disk and therefore as new dependencies are added, the old ones remain.
Lo and behold, that was the issue. The plugin started to behave normally after I reinstalled all the dependencies.
Now, one solution to this would be to move to a hosting platform with an ephemeral filesystem. (Looking at you, heroku.) At this point there are several things tying us to this hosting provider, so I did the next best thing. I wrote a script to remove the vendor directory on every deploy.
Now, if I hadn’t chosen to do that, I could have done one of the following:
- ignored it. After all, it only happened with one plugin and one project across all our projects. It was a pretty rare beast.
- documented it. I could have put it in the readme of the project and hoped that if it happened again, someone would remember it.
But, instead, having it in the build script means that, at least on this project, this issue will never pop up again. I don’t have to remember it or how it was fixed. Boop, it’s all gone.
I had a colleague once who called software “condensed knowledge” and I like to think of build scripts as one of the purest forms of that. As I did, you spend hours tracking down an issue, then you automate the fix so that it never happens again.