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
1 | { |
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
1 | # |
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
1 | /// <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!
1 | $ 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!
Dependencies
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
1 | { |
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.