Zeit Now GitHub app + Renovate app + Cypress tests = 💝
How Cypress, Zeit Now GitHub app and Renovate app play well together to give you well tested PRs and keep your dependencies up to date with zero effort.
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
now.json
1 2 3
{ "type":"static" }
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
# # Testing image # FROM cypress/base:10 as TEST # dependencies will be installed only if the package files change COPY package.json . COPY package-lock.json . # by setting CI environment variable we switch the Cypress install messages # to small "started / finished" and avoid 1000s of lines of progress messages # https://github.com/cypress-io/cypress/issues/1243 ENV CI=1 RUN npm ci # tests will rerun if the "cypress" folder, "cypress.json" file or "public" folder # has any changes # copy tests COPY cypress cypress COPY cypress.json . # copy what to test COPY public public # # run e2e Cypress tests # RUN npm test
# # Production image - without Cypress and node modules! # FROM busybox as PROD COPY --from=TEST /app/public /public # nothing to do - Zeit should take care of serving static content # we would only need a command if we want to use this image locally
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
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!
INFO: Gracefully shutting down. Please wait... Removing intermediate container 766257f65511 ---> 669fd49b065a Step 15/18 : FROM busybox as PROD ---> 22c2dd5ee85d Step 16/18 : COPY --from=TEST /app/public /public ---> Using cache ---> 080af7d4cccd Step 17/18 : RUN ls -la ---> Using cache ---> 8996a8bc6893 Step 18/18 : RUN du -sh ---> Using cache ---> 84d15f475947 Successfully built 84d15f475947
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
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.