Tested PR deploys
Recent news: Zeit.co has released a GitHub app for automatically deploying GitHub pull requests using Zeit Now tool. Previously, I have been a huge fan of testing my code on Now cloud using immutable deploys - read Immutable deploys and Cypress and try my helper tool now-pipeline. Now (excuse my pun), I wanted to see if I could run the same tests on each pull request without any custom tooling, just by using Zeit GitHub app.
So I made a tiny static repo bahmutov/tiny-blog and connected it to the "Now" GitHub application.
My example is a static site, which I configure using tiny-blog/now.json file
I needed to add a Dockerfile to test and serve my site. Zeit Now can be used for Node deploys, but its full power lies in running any Docker-based project. So I have added a Dockerfile that runs end-to-end tests against a local site using Cypress.io test runner. The Dockerfile looks intimidating, but as I explain in Fast Tests, Tiny Docker Image blog post, it only looks complicated because I build two images - one to run end-to-end tests, and another to actually serve the static site in production. By using Docker multi-stage build feature we can keep the production image really really small - because it will NOT include tests or test dependencies. In summary, the Dockerfile looks like this
That is it - and the best part is that you can build this Docker image locally to make sure it is working! You should see end-to-end tests executing headlessly. Here is a typical test that Cypress will run
/// <reference types="cypress" />
And here is the output from Docker building the image and running tests on my Mac. I am passing an argument to force Docker to NOT cache intermediate step "RUN npm test", thus forcing the tests to run. Notice how most steps say "Using cache" - because Docker is really good at caching intermediate steps as layers!
$ docker build . --build-arg HOSTNAME=$(date +%s)
Ok, works locally, now push to GitHub! From now on (again, another pun), every pull request to the bahmutov/tiny-blog repo is built on the Zeit cloud, the tests are executed and if they pass, the site is deployed under a unique url. You can see an example pull request 3
Under "details", Zeit adds a message with the link going to the deployment.
During deploy, if you are fast enough (or at any time by going to the
https://zeit.co/<username>/dashboard) you should see the same output, but from the Docker container being built by the Zeit cloud machines.
The deployed site does not look like much, does it 😄
But the really good thing about this setup is this - I have a well tested unique deploy for each pull request with minimum effort!
Well, if we can have one GitHub app, why not have two? I am a huuuge fan of RenovateApp - a fast and painless way to keep all my NPM dependencies up to date with minimum effort. What happens if we set both Zeit Now and Renovate apps?
I really trust good tests and usually allow automerging minor and patch version changes (if tests pass), while manually reviewing major version upgrades. So my renovate.json looks like this
And here is the result - when Renovate notices a new version of an NPM dependency, it opens a pull request. Zeit Now runs the end-to-end tests using Cypress, and tells GitHub.
Each pull request like this one tells me what is about to happen, and has a unique deploy URL
Renovate uses the test status (pass / fail) and upgrade type (major / minor / patch) to keep the PR open or automerge it after an hour or so. The commit log shows these auto-merged dependency upgrades.
Boom! I got myself pain-free, almost-zero config way of testing code changes, seeing the deployed result and keeping dependencies up to date.