Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I cache steps in GitHub actions?

Say I have a GitHub actions workflow with 2 steps.

  1. Download and compile my application's dependencies.
  2. Compile and test my application

My dependencies rarely change and the compiled dependencies can be safely cached until I next change the lock-file that specifies their versions.

Is a way to save the result of the first step so that in future workflow can skip over that step?

like image 658
lpil Avatar asked Mar 11 '19 21:03

lpil


People also ask

Can you CD in GitHub Actions?

GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub.

In which file do you define the steps to execute in your GitHub action?

GitHub Actions uses YAML syntax to define the workflow. Each workflow is stored as a separate YAML file in your code repository, in a directory named .

Do GitHub Actions steps run in parallel?

Only jobs can run in parallel, but steps always run sequentially.


2 Answers

Caching is now natively supported via the cache action. It works across both jobs and workflows within a repository. See also: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/caching-dependencies-to-speed-up-workflows.

Consider the following example:

name: GitHub Actions Workflow with NPM cache  on: [push]  jobs:   build:      runs-on: ubuntu-latest      steps:     - uses: actions/checkout@v1      - name: Cache NPM dependencies       uses: actions/cache@v1       with:         path: ~/.npm         key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }}         restore-keys: |           ${{ runner.OS }}-npm-cache-      - name: Install NPM dependencies       run: npm install 

Where the path and key parameters of the cache action is used to identify the cache.

The optional restore-keys is used for a possible fallback to a partial match (i.e. if package-lock.json changes the previous cache will be used).

Prefixing the keys with some id (npm-cache in this example) is useful when the restore-keys fallback is used and there're multiple different caches (e.g. for JS packages and for system packages). Otherwise, one cache could fall back to the other unrelated cache. Similarly, an OS prefix useful when using matrix builds so caches of different systems don't get mixed up.

You can also build your own reusable caching logic with @actions/cache such as:

  • 1-liner NPM cache
  • 1-liner Yarn cache

Old answer:

Native caching is not currently possible, expected to be implemented by mid-November 2019.

You can use artifacts (1, 2) to move directories between jobs (within 1 workflow) as proposed on the GH Community board. This, however, doesn't work across workflows.

like image 84
thisismydesign Avatar answered Sep 22 '22 05:09

thisismydesign


The cache action can only cache the contents of a folder. So if there is such a folder, you may win some time by caching it.

For instance, if you use some imaginary package-installer (like Python's pip or virtualenv, or NodeJS' npm, or anything else that puts its files into a folder), you can win some time by doing it like this:

    - uses: actions/cache@v2       id: cache-packages  # give it a name for checking the cache hit-or-not       with:         path: ./packages/  # what we cache: the folder         key: ${{ runner.os }}-packages-${{ hashFiles('**/packages*.txt') }}         restore-keys: |           ${{ runner.os }}-packages-     - run: package-installer packages.txt       if: steps.cache-packages.outputs.cache-hit != 'true' 

So what's important here:

  1. We give this step a name, cache-packages
  2. Later, we use this name for conditional execution: if, steps.cache-packages.outputs.cache-hit != 'true'
  3. Give the cache action a path to the folder you want to cache: ./packages/
  4. Cache key: something that depends on the hash of your input files. That is, if any packages.txt file changes, the cache will be rebuilt.
  5. The second step, package installer, will only be run if there was no cache

For users of virtualenv: if you need to activate some shell environment, you have to do it in every step. Like this:

- run: . ./environment/activate && command 
like image 34
kolypto Avatar answered Sep 22 '22 05:09

kolypto