For iterating and debugging, CI/CD can never be fast enough.

GitHub actions is still in beta, and performance and features are likely to change.

However, the basic design (consecutive docker image runs along a directed acyclic graph) already implies some conclusions for making the most of the service.

Caching

There are different levels of caching relevant to the performance of caching.

  1. Build artefacts are any files created by the actions as they run over your repository. There is currently no native support for caching build artefacts from GitHub actions (tracked in #48). You can persist artefacts across actions (anything inside /github/), though not between workflows or runs.

    ghactions – the R package – currently has its own “McGyvered” caching, using Google Cloud Storage. You can look at the main.workflow for inspiration, but this likely isn’t ready for prime-time yet. The preferred solution should be for GitHub actions to support caching natively.
  2. FROM image caching concerns the downloaded images from Docker Hub or another registry that are listed in the FROM field of the Dockerfile driving some action in question. Though this isn’t documented, GitHub actions appears to be caching those on-site, because even very large images such as rocker/verse or rhub/debian-gcc-release start running in a matter of seconds (~30).
  3. Additional layers from RUN and similar fields in the Dockerfile appear to be downloaded from Docker Hub and locally cached **only if published using the action builder action. The action builder action and associated Makefiles tag uploaded Docker images by all the git refs (SHA, branch, PR) which the uses = field allows. To get these tags exactly right, it’s easiest to use the action builder action, though it may be possible to achieve the same result using other means.

    Thus published, these images, even with relatively expensive RUNs all start running in a matter of seconds (~20).

    Arguably GitHub actions could (or did at some point in the past already?) automatically and transparently do what the action builder action now does via make.

To sum up, it appears that:

  • Large images are not very expensive (though slimming them down is always a good idea, tracked in #166).
  • RUNs and friends inside an actions Dockerfile are pretty expensive, unless published to Docker Hub.
  • Caching for build artefacts across workflows and runs brings the usual performance gains. remotes::install_deps() for a medium-sized package such as ghactions now completes in around 4 minutes (because of 3 in the above), whereas without caching it took around 15-20 minutes. The overhead of the caching actions (un/tarring, down/uploading) is negligible (<20 seconds each).