heroku-modular-buildpack

A buildpack based on the idea of packages, delivering a modular system and basic dependency management.

Using

It is possible to use this buildpack as is, and contain all your extra data in your project itself. Configuration for this buildpack should always be placed inside your project under /build/heroku/.

A minimum configuration has at least these files living in /build/heroku/:

Optional components are:

Packages

Packages are represented by installer scripts that install one specific part of your environment, for example there is an installer included under installers which install a basic nginx webserver.

The name of a package is the name of it’s installer script without the .sh extension.

Package manager

This buildpack includes a package manager which allows you to centralize the management of your packages.

Enabling the package manager

By default the package manager is disabled, you can enable it simply by adding a repos file to your /build/heroku/ directory.

The file-format of the repos file is as simple as a link ( any link supported by curl ) per line of the file.

Sample repos file:

http://jorgen.evens.eu/heroku-cedar14/index
http://example.com/deploy/heroku

Repositories

A repository is a plain text file using the following format <package-name> <package-link> <package-md5> <comments> where each package is on its own line. It is important to use a space to separate the package from its link, a tab is currently not supported.

<package-link> is a link ( any link supported by curl ) to the installer file for the package. <package-md5> is a md5 hash of the installer file which is used to check for an outdated cache.

A sample repository

nginx-deploy-page http://jorgen.evens.eu/heroku/nginx-deploy-page.sh 9bbb050c6bba8c7ad8f738ef056088ae # Exposes deployment information through a static page.

Note: Currently no versioning of packages is available. If you would like to add multiple versions you will have to include the version in the package name. nginx-1.4.2 for example.

Repository sample + tools

There is a github repository with the scripts to generate a repository for the packages contained within it.

Custom installers

You can build your own buildpack by forking this repository and adding your own installers, but if you would like to keep your buildpack as clean as possible you can also install installer scripts in the /build/heroku/installers folder of your project.

An alternative is to use the package manager to distribute the packages.

Variables

The buildpack passes 4 variables into the installer, three of which are the exact same variables as Heroku passes to the compile script. The fourth indicates the location at which the installer was stored.

These directories are created for you when the buildpack runs.

Environment variables you may have set in Heroku will be loaded and available to your installer script as well.

Note: When using the package manager $INSTALLER_DIR will point to the location in the repository file rather than to the local copy that gets downloaded.

Helper functions

An installer has access to some helper functions to print to the console and to manage dependencies it might require.

Note: You should NOT mark your own package as installed using dependency_mark, this is done for you.

dependency_mark use case

A sample use-case for the dependency_mark function is given here to illustrate its use.

If your package can be used as a drop-in replacement for another package you can mark the original package as installed so your package does not get overwritten when a different package depends on the original.

An example:

In this scenario we would like to combine nginx-module with nginx-status, if we would setup our install file like illustrated below we would overwrite nginx-module with generic nginx since nginx-status depends on it.

nginx-module nginx-status

To solve this problem we can mark nginx as installed at the end of our nginx-module installer by calling dependency_mark nginx. Now when nginx-status is installed nginx will be reported as installed and nginx-module will not get overwritten.

boot.sh

A boot.sh file is always created with a shebang #!/bin/sh followed by an empty line. If your installer wants to add something to the boot.sh file you should simple append the lines to the ${BUILD_DIR}/boot.sh file.

It is important that you send blocking applications to the background using &. For example:

/app/vendor/nginx/sbin/nginx &

A wait will be added to the end of the boot.sh script so that the script will wait for the background tasks to complete and heroku will not think that the script exited. This way all the commands in the boot.sh file get executed and all services start as they are supposed to.

Project specific compile

The project specific compile script has access to the same functionality as a custom installer and is for all intents and purposes a custom installer that always gets run at the end.

Cleaning cache

Setting the environment variable CLEAN_CACHE to a non empty value will result in the buildpack removing the CACHE_DIR before running any installers. This will ensure that the cache is empty and all the required packages and files will be downloaded again.

Contributions

I really appreciate any contribution you would like to make, so don’t hesitate to report an issue or submit pull requests.

Special thanks to these people for contributing to this project

License

This project is available under the New BSD License.

About me

Hi, my name is Jorgen Evens. By day I built things (mainly in PHP and JavaScript) for Ambassify and by night I tinker around with these kinds of projects.