Continuous Integration: How I use Buddy CI
Last updated: 28th October 2019Thank you to Buddy for sponsoring this post.
Introduction
I had the opportunity of reviewing the service Buddy. In this post, I try to give an honest review of the service so you can be aware of what it offers, and maybe consider using it yourself.
The surprisingly well polished video on the homepage explains what the service supports. You can think of it as continuous integration and deployment for your software projects. To give a brief example of what one might use this service for, with Buddy, you can:
- Run a number of actions when you push your website code to GitHub
- Build/compile code (e.g. transform TypeScript into JavaScript)
- Only run certain actions if your tests pass (e.g. only deploy if unit tests pass)
- Push the built code to your hosting provider (e.g. Digital Ocean)
- Check the live website and make sure it has been updated correctly
That's just one example workflow, you could also adopt the following workflow:
- Every 1 hour, check if a retailer has discounted a product you're interested in
- Send a push notification to your mobile phone when a discount is active
When adopting workflows like those above, or your own, two important aspects are:
- Buddy uses visual interface to configure such workflows, meaning coding is optional.
- These jobs can continue to run when you switch off your machine (applicable to any CI service). Meaning your job which checks for discounted retail products can run throughout the entire day on someone else's infrastructure which you don't need to maintain.
Creating Pipelines
Pipelines are a set of predefined steps applied to your codebase and/or other services.
Having used services like Jenkins/Travis CI/Circle CI a bunch in the past, it was refreshing to use a service which guides you through the steps of creating, configuring and using a software pipeline for your software in a visual way. Instead of being forced to learn buddy.yml (or .travis.yml
etc.) syntax, I could instead click through the relevant steps in the Buddy configuration page.
Note however, there are many benefits of storing your configuration in code. To address this, Buddy has YAML Mode: Instead of going through the wizard, you commit a buddy.yaml
file which includes a codified version of your pipeline. If you've used other popular CI services, you'll be familiar with this.
You can transition between the two modes easily, e.g. use the wizard to configure a pipeline, then export it as YAML, and then commit it to your repository. For my personal projects, I would happily use the visual mode, which frees up my time to focus on building my project, rather than the infrastructure powering it.
In testing this feature, it appeared as if a codified pipeline which I committed in my repository could then subsequently be manipulated via the interface in Buddy, my concern however is that these two pipelines could now get out of sync.I wonder if the GitHub Actions approach of committing your pipeline changes via Git would be a better approach here.
Interestingly however, it appears that Buddy has considered at least one element of Git and provides a Pipeline history where you can view diffs of the under-the-hood YAML file which represents your pipeline.
Browsing the Filesystem
Buddy has an excellent feature where you can browse the filesystem after a pipeline executes.
Notice the node_modules
folder. The node_modules
folder is not present in my Git repository, so Buddy is actually presenting me with a filesystem snapshot after the pipeline executed (and thus the command npm install
ran).
As an example, if your grunt/gulp/webpack minifies a bunch of JavaScript files and writes them to a dist
folder, you will then see that dist
folder in the Buddy filesystem snapshot. You can view files in the Buddy editor, or download them for further debugging. This feature is useful in a variety of debugging situations, one being:
You've deployed a new version of your website, but assets do not seem to be updating when you reload the page. Does the error lie with the build pipeline? The CDN you're using? Your local browser cache? Browsing the filesystem snapshot means you can check that the assets are being output correctly, and thus rule out the build pipeline as a point of failure.
A possible feature request I'd have here: I wonder if terminal access is possible, so I can run commands in the same environment which my pipeline executed in? Sometimes it'd be nice to jump straight into the pipeline execution context and re-run that failing npm test
command with npm test | grep audio_player_tests.js
for example. That being said, I've not seen other services implement such a thing.
Buddy Actions
There are a heap of built-in actions to choose from. For example, instead of specifying a test command in your package.json
, which invokes ESLint like this: ./node_modules/.bin/eslint .
You could simply use the built-in ESLint action.
One thing I'd like to see here: In the Node version select box, it'd be great to have extra options like:
- Use latest LTS version
- Use latest current version
- Use the latest matching version according to the engines field definition in
package.json
This is because I like to keep my Node.js versions up to date across the board. I wouldn't want Node.js versions to get out of sync where I forget to update the Buddy ESLint action during a Node.js upgrade.
That aside, having these prebuilt actions is great. There are a heap of them to search through. Here's a snippet:
There are even actions you might have not known you needed! For example, I imagine many of us happily run our tests in our build scripts without giving a second thought towards parallel execution. While browsing through the actions, I noticed there is a 'Split tests' actions which does exactly that, it categorises your tests into separate buckets so they can be run in parallel rather than sequentially.
Feature request for the team: Would be helpful to see more documentation on the actions page, for example the 'Split tests' action page shows this:
Which doesn't really explain what it does. Interestingly enough, Buddy already have a great blog post on using the 'Split tests' action, so maybe it's just a case of linking those up.
There are a heap of other actions which are highly likely to integrate with the services you already use, e.g. Google Cloud, Amazon Web Services, Cloudflare, Slack, Email, there's even an action which can execute an arbitrary HTTP request. And finally, as you might expect, there are the 'vanilla' actions where you simply execute any script of your choice, if for whatever reason the pre-built actions don't cut it for you.
The pleasant thing about all of these pre-built actions is that configuration is a breeze. No coding required. As mentioned, the only real feedback I have here would be a little: "When to use this" message a.k.a. A description to explain what the action does.
Buddy Git Hosting
Turns out Buddy offers Git hosting. If for example you didn't want to provide Buddy with read and write access to your GitHub, you could simply host your project within Buddy itself.
To complement this feature, Buddy includes a code viewer and editor. You can make code changes and commit them back to your Buddy Git repository, entirely within the online editor. It also includes a diff viewer so you can see what changes have been made in a given revision.
Documentation
I was impressed with the quality of writing in Buddy's documentation. Content was succinct, to the point, and included lots of screenshots which made digesting it a lot easier.
If you've never used Buddy, their guides are handy in that they demonstrate how popular recipes can be used on their platform. E.g.
Often, when reading product specific documentation, I still won't know how easy my task at hand will be until I've tried it. However using these guides (a.k.a recipes) helps me understand exactly what I'd need to do for my particular task (assuming they have it of course). In this case, I know exactly how I previously did Node.js deployments, so I was pleased to see that the Node.js deployment guide would be quick carry out, contained no surprises, and was fairly intuitive.
Deployments
Continuously testing your changed code is one thing, and continuously deploying your service is another. Modern CI tools typically support both. Buddy CI includes a number of predefined deployment actions which you can use in your pipeline. The whole process was simple. I was surprised to get continuous deployment configured in ~15 minutes to a remote VPS.
My continuous deployment story used to be a random assortment of bash scripts, git hooks and git remotes. If I hadn't deployed in a while, I'd forget how things worked. It's a huge relief that I can now update my code, and trust that my website will get deployed as long as all the tests pass.
For some services/websites, I use Digital Ocean. To set up the action, it was a simple case of connecting my Digital Ocean Account to my Buddy account. Once connected, Buddy listed my Droplets (servers) and even allowed me to browse the remote server filesystem so I could confirm where my built website should be deployed to. This level of integration meant I didn't have to go through 20 "test"-style commits where I'd be logging and debugging until the deployment worked.
The execution of the deployment took way longer than configuring it! Upon debugging, I discovered it was my particular Droplet, possibly due to the region I had selected.
The first deploy (copying of files from Buddy to my droplet) took ~40 minutes. That being said, the bulk of this time was from copying node_module
files, however I noticed their guide suggested to run npm install
on your own server (and only push your source files over). This is something I need to evaluate the pros/cons of, but for now I'm leaving it as it is.
Back to the issue of time: fortunately Buddy will only push new/changed files on subsequent deployments.
For the process management of a few personal Node.js projects, I have used pm2.
With PHP, you typically push your files, and your Apache/Nginx web server would start serving the new PHP files by default. With Node.js, the process running your application loads files upfront and stores them in memory, so an application restart is necessary.
To get this working, I used an SSH action configured with a one liner, pm2 restart
.
Note: If your VPS is not supported as a predefined Buddy Action, the RSync action helps achieve the same thing. Enter your SSH information, select the remote folder where you want your files deployed to, and after an initial full upload, only new/changed files are then synced across.
Buddy Email Updates
It's useful to see what features are being worked upon thanks to the Buddy email updates. The bullet point list of new features + changes meant quick skimming was possible to find out how the platform is evolving.
Privacy and Security
CI/CD services often have complete access to your codebase. If they manage the deployment, they can also have write access to your hosting platform. Additionally, when you sign in with GitHub, it's pretty common to see the "This application will be able to read and write all public and private repository data"
message, and so before continuing, it's healthy to do your due diligence.
Feature request: Would be great for Buddy to have some documentation on why write access is needed when signing in with GitHub. While almost all similar CI/CD services seem to do the same, it's still helpful to learn how such services write back to my GitHub account.
Buddy have a dedicated security page and it was great to read how they handle passwords: "Passwords in Buddy are salted and hashed by one-direction encryption scripts. We do not store user passwords"
They make reference to their "Buddy employee policy" which outlines how employees may deal with your private repositories, it clearly states explicit permission from the owner is required.
They also have a responsible disclosure policy, which hints at a willingness to work with security researchers, rather than against them.
Conclusion
In the longer term, considering the popularity of GitHub, I'm curious as to how their strategy will adapt to GitHub Actions. I'm also curious as to how their in-built actions will be used over manually declaring them in the relevant script runner of choice, within the repository. A guide on the pros and cons of each approach could be useful to users asking similar questions.
Using Buddy, there's lots to be impressed with. The UI looks great, it's free for open source, GitHub is supported and I can figure most things out without reading documentation.
The deployment strategy with Digital Ocean and Buddy was completely seamless. I had only skimmed through the documentation and I could use the time I saved on building my product.
Buddy was a pleasure to use and I'll be moving more of my personal projects across to make use of it.