Have you enjoyed the convenience that buildpacks give you when deploying on platforms that support it, such as Heroku? Have you wished you can have the same convenience for your CI/CD pipeline without have to dig for the steps that you need to get everything running properly? You are not alone!
Buildpack CI is an action on GitHub Actions that uses buildpacks and Herokuish to give us this convenience on the GitHub platform. In the simplest case, adding one line to your GitHub Actions workflow will build and run unit tests for your app. Ready to give it a shot?
Super-simple. Just add the following line to your workflow. See examples below.
- uses: buildpack-ci/run-tests@v1
Run-Tests rely on the bin/test
and bin/test-compile
scripts within buildpacks to build and trigger the unit tests. The following languages (which use Heroku officially-supported buildpacks) will work out of the box.
- Ruby
- Java
- Scala
- Golang
- NodeJS
The "native" buildpacks for some languages don't include the necessary scripts (i.e. bin/test
and bin/test-compile
), so one will have to create your own buildpack to get the scripts added. The following buildpacks have been forked to add the necessary scripts.
- https://github.com/vincetse/heroku-buildpack-python.git (PR heroku/heroku-buildpack-python#982 submitted to add scripts)
- https://github.com/buildpack-ci/heroku-buildpack-multi.git
- https://github.com/buildpack-ci/null-buildpack.git
Here is an example of the most basic usage with an app that does not require a database server component.
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Clone code repo
uses: actions/checkout@v2
- name: Build and run unit tests with Buildpack CI
uses: buildpack-ci/run-tests@v1
Need to use a custom buildpack? You can do so by setting the BUILDPACK_URL
environment variable to the URL of the buildpack that you need for your application. This example builds a Perl app which isn't supported natively by Herokuish.
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Clone code repo
uses: actions/checkout@v2
- name: Build and run unit tests with Buildpack CI
uses: buildpack-ci/run-tests@v1
env:
BUILDPACK_URL: https://github.com/vincetse/heroku-buildpack-python.git
If your application uses multiple buildpacks, you will need to do 2 things:
- Use the [buildpack-ci/heroku-buildpack-multi] as the custom buildpack by setting the environment variable
BUILDPACK_URL
to a value ofhttps://github.com/buildpack-ci/heroku-buildpack-multi.git
. - At the root of your application directory, create a file named
.buildpacks
with the URL of each buildpack you want to use for your application. Dokku has the best documentation I can find on this topic.
Note that if one of the buildpacks does not support tests (i.e. have the bin/test
and bin/test-compile
scripts), you can skip over those buildpacks by defining the BUILDPACK_MULTI_PASS_IF_MISSING_TEST_SCRIPTS
variable to a value of true
.
The buildpack-ci/django-app-multi-buildpack example application demonstrates such a configuration in its CI configuration.
This Rails app demonstrates how to use a Postgresql container during the build & test process by using a service within the workflow.
name: CI
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_DB: test
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Clone code repo
uses: actions/checkout@v2
- name: Build and run unit tests with Buildpack CI
uses: buildpack-ci/run-tests@v1
env:
DATABASE_URL: postgres://postgres:postgres@postgres:5432/test
RAILS_ENV: test
DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL: true
Running a Django app on Heroku requires the app to read database credentials from the DATABASE_URL
environment variable, and we have stuck with that convention for this example. The dj-database-url Python package makes it very convenient to use DATABASE_URL
to pass database credentials to the application.
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_DB: test
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Clone code repo
uses: actions/checkout@v2
- name: Build and run unit tests with Buildpack CI
uses: buildpack-ci/run-tests@v1
env:
BUILDPACK_URL: https://github.com/vincetse/heroku-buildpack-python
DATABASE_URL: postgres://postgres:postgres@postgres:5432/test
The following are a bunch of GitHub Actions workflows for example apps. Make sure to check out the workflow files too.
- https://github.com/buildpack-ci/django-example/actions/runs/119584374
- https://github.com/buildpack-ci/nodejs-example/actions/runs/119944160
- https://github.com/buildpack-ci/rails-example/actions/runs/119767216
- https://github.com/buildpack-ci/django-app-multi-buildpack/actions/runs/120027240
Configuring CI for frameworks such as Ruby-on-Rails or Django is pretty straightforward, but may involve several steps that require referring to a manual to jolt one's memory on how to configure the setup. GitLab Auto DevOps simplifies the CI for developers with a zero-configuration functionality, but one will have to go off-platform for the convenience. This tool aims to provide a low-effort option right on the GitHub platform.
This tool was conceived while the author was sheltering in place in New York City during the COVID-19 pandemic, and process of designing and assembling the pieces provided a fun project in these tough times. Hopefully, it will delight the GitHub community too.
- Cloud Native Buildpacks are really cool! They are probably going to be the future, and one should really explore them. They don't support running unit tests automatically right now, but one can probably work around that.
- Heroku CI looks pretty sweet for those already paying Heroku. Some would argue lock-in is a concern, but speaking from past experience, most of us are more worried about lock-in than we should be since most of us will never exercise other options any way.
- GitLab Auto DevOps is a very nice feature. Why hasn't GitHub also launched such functionality?
- Google Cloud, AWS, and Microsoft Azure have similar functionality too, right? I can't remember.