Shorthanded
Automatically deploy an app to Heroku and add a CNAME for it in DNSimple. Go
from zero to http//dry-pine.mysite.com
in under a minute.
This is part of a larger project to make it easy to automatically deploy one
application for multiple people, each of whom gets a unique URL for their
deployment of the application. The unique URL is a Heroku-esque subdomain like
dry-pine
or icy-glitter
plus a domain that you provide.
The full workflow
- A request hits the API and provides a subdomain in the params (see below for more about the API).
- A Heroku app is created with a semi-random name. It's only semi-random because it has a (configurable) prefix like "shorty-" or "custom-" to make generated apps easy to find in your Heroku console.
- As part of the app creation, the Heroku app deploys the .tar.gz containing
the code of another app. The URL of the .tar.gz is given by
$URL_OF_TAR_GZ_TO_DEPLOY
. The .tar.gz must be an app with an app.json in the root, which will tell Heroku what environment variables to set and generally how to deploy that app. - The provided subdomain is created on your DNSimple domain.
- The subdomain is mapped to the Heroku application.
- Voila, it's all wired up, from DNSimple -> Heroku.
What's the API?
POST /apps
Required params (in JSON):
{
"app": {
"subdomain": "whatever-subdomain-you-want"
}
}
Required headers:
Accept: application/vnd.shorthanded+json; version=1
X-App-Secret: {Whatever you set $HEADER_SECRET to in the env}
Returns JSON.
Success
Status code: 201 Created
{
"url": "http://dry-pine.mysite.com"
}
Failure
Status code: 502 Bad Gateway
Failure is directly from Heroku or DNSimple, depending on which failed.
Example Heroku response:
{
"id": "invalid_params",
"message": "Name is already taken"
}
Example DNSimple response:
{
"message": "CNAME hello.yourdomain.com already exists so it was ignored."
}
OK, how do I deploy this?
You can push it to Heroku like any other app. Most of the functionality is controlled by environment variables:
| Name | Meaning | Example |
|---|---|---|---|---|
| HEROKU_APP_NAME_PREFIX
| A short (<= 7 characters) string that will be used as the prefix of each Heroku app to make autogenerated apps easy to find in the Heroku console. If you want a longer prefix, change how long a SecureRandom string gets generated in HerokuAppNameGenerator. | shorty- |
| HEROKU_OAUTH_TOKEN
| Get one using instructions in their docs. | aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa |
| URL_OF_TAR_GZ_TO_DEPLOY
| Heroku has an API to take in .tar.gz of apps with an app.json in the root. If you add an app.json
to your app on GitHub, GitHub will gladly generate a .tar.gz for you on the fly using a URL like https://github.com/gabebw/shorthanded/archive/master.tar.gz
| https://github.com/gabebw/shorthanded/archive/master.tar.gz |
| DNSIMPLE_DOMAIN
| The domain name (WITHOUT a scheme like http://
) to add a subdomain for. Must have DNS controlled by DNSimple. | example.com
|
| DNSIMPLE_DOMAIN_TOKEN
| DNSimple has a couple different ways to authenticate against their API. Shorthanded uses the domain token because it gives the least access to a user's account. You can find it under the "settings" for a specific domain on DNSimple's website. | 3125f1af24979e2f821ef829bc8040a5 |
| HEADER_SECRET
| A secret token that must be sent with the headers of every request. It prevents random people from creating a lot of Heroku apps on your behalf. | secret |
Local development
After you have cloned this repo, run this setup script to set up your machine with the necessary dependencies to run and test this app:
% ./bin/setup
It assumes you have a machine equipped with Ruby, Postgres, etc. If not, set up your machine with this script.
After setting up, you can run the application using foreman:
% foreman start
If you don't have foreman
, see Foreman's install instructions. It
is purposefully excluded from the project's Gemfile
.
Guidelines
Use the following guides for getting things done, programming well, and programming in style.
Deploying
If you have previously run the ./bin/setup
script,
you can deploy to staging and production with:
$ ./bin/deploy staging
$ ./bin/deploy production