Automatically deploy pull requests into Flynn cluster. Heroku Review Apps DIY.
Compared to Heroku, Flynn is a good fit in the case where your monorepo has more than one web service. Because you can deploy the entire stack of services with single git push
, whereas on Heroku you'd have no choice but to split the repo into multiple ones. Euuuww.
However Flynn is missing a few goodies one of which is Heroku review apps... until now! Flynn-pr-apps enables review apps for flynn. Interested? Read on.
This is itself a flynn app, so first thing is to add it to your cluster (see below for instructions).
Once up, the pr-apps instance will start watching pull requests lifecycle events. It'll deploy (open pr), update (push) or destroy (close pr) the app (or stack of apps) from the linked github repo into your flynn cluster. The deployed app url will be shown on github pull request page. E.g:
git clone https://github.com/featurist/flynn-pr-apps
cd flynn-pr-apps
flynn create pr-apps
flynn resource add postgres
flynn env set GH_REPO=https://github.com/some-org/some-repo.git
flynn env set GH_USER_TOKEN=YOUR_TOKEN
flynn env set WEBHOOK_SECRET=$(openssl rand -hex 20)
flynn env set FLYNN_AUTH_KEY=$(flynn -a controller env get AUTH_KEY)
git push flynn master
Github account for GH_USER_TOKEN
above should be a collaborator on GH_REPO
with Admin
privileges (for github api access).
For GH_REPO
create a webhook for pull_request
events and point it to https://pr-apps.$FLYNN_CLUSTER_DOMAIN/webhook
.
Set content type to application/json
and Disable SSL verification
. More about webhooks here.
Applications beyond trivial often require custom environment variables, extra resources, services and endpoints. Drop pr-app.yaml
at the root of your project to be able to customise all this. E.g.:
env:
API_URL: "https://api-${APP_DOMAIN}"
DEBUG: true
resources:
- redis
routes:
api-web: "api-${APP_DOMAIN}"
Route key (api-web
in the example above) refers to a service name in your Procfile
. Each route's service is automatically scaled to 1.
$APP_DOMAIN
is interpolated. E.g. pr-234.prs.example.com
. Where pr-234
is an autogenerated flynn app name for pull request 234 and prs.example.com
is your flynn cluster domain.
It doesn't make much sense to run Pr Apps locally (even though you could with yarn dev
) because of the hard dependency of flynn api. I personally rely on tests and occasionally push the changes to flynn app in the real flynn cluster (see Create Pr-Apps flynn app above).
The only exception to the above is working on "deployment logs" page. To get there you need a test deployment. Generate one with:
yarn sequelize db:seed:all
Then yarn dev
and then open http://localhost:5599/deployments/a4d8ffe3-7a6d-47a9-aa69-6d62cc436e0e
This project takes a novel approach to testing outlined in more detailed here. There is no catchy name yet (ideas are welcome), but basically the idea is that instead of a traditional test pyramid with different sets of tests for different layers (integration, unit, etc.), there is a single layer of tests that runs in different modes (aka assemblies). Ranging from an in-memory core assembly, where all external dependencies (e.g. fs, database, browser ui, etc.) are replaced with memory implementations, down to the one with the most possible amount of "real" dependencies. The more "real" assemblies cover more code but also take longer to run.
The basic premise of all this is that a lot of your app is actaully that inner core, that can be tested all in memory in milliseconds. And as the application gets bigger it's mostly growing core and to a lesser extent the integration surface with external APIs. All this means:
- blazingly fast integration tests with a reasonable coverage whose performance does not degrade over time;
- the same tests can be run in a more real mode (in an envirinments where we don't care about fast feedback, e.g. CI) means that they don't go out of sync with reality;
- easy of debugging (if memory is passing, but memory + web service isn't, than the bug is likely in web service layer)
- and more (see the link above)
Back to Pr Apps though. In here you'll find three assemblies: memory, local and github.
To run memory assembly:
./test-memory
For local assembly (memory + real fs, postgres, git, pr apps service, fake flynn service, fake github remote) you need a local postgres server and a test db that is created with this command:
NODE_ENV=test yarn sequelize db:create
Then:
./test-local
As above except with actual github (remote + api). Needs some extra environment:
TEST_GH_REPO
existing github repo (with username/org) that will be used in tests to simulate user workflow.
TEST_GH_USER_TOKEN
API token of the account that can has access (create webhooks, pull code) to the above repo.
If you're offline (or want local test a bit faster) put the following in /etc/hosts
:
127.0.0.1 pr-apps.prs.localtest.me
127.0.0.1 git.prs.localtest.me
127.0.0.1 controller.prs.localtest.me
127.0.0.1 pr-23.prs.localtest.me
127.0.0.1 pr-24.prs.localtest.me
./test-real
Each of the above have -debug
counterpart (e.g. ./test-local-debug
) that starts node debugging session.
Finally, run all of the above with ./test
Featurist provides full stack, feature driven development teams. Want to join us? Check out our career opportunities.