Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use GitHub actions cache with brew install

I'd like to use the GitHub Actions cache (actions/cache@v2) in order to save the cache of my brew install command, instead of re-downloading all the dependencies over and over again.

This would make my builds faster, how can I achieve it?

like image 799
Francesco Borzi Avatar asked Aug 31 '20 13:08

Francesco Borzi


2 Answers

In your workflow job configuration:

    steps:
    - name: Update Homebrew
      run: |
        brew update --preinstall
        cat "$(brew --repository)/Library/Taps/homebrew/homebrew-core/Formula/foo.rb" > .github/brew-formulae
    - name: Configure Homebrew cache
      uses: actions/cache@v2
      with:
        path: |
          ~/Library/Caches/Homebrew/foo--*
          ~/Library/Caches/Homebrew/downloads/*--foo-*
        key: brew-${{ hashFiles('.github/brew-formulae') }}
        restore-keys: brew-
    - name: Install Homebrew dependencies
      run: |
        env HOMEBREW_NO_AUTO_UPDATE=1 brew install foo

Here ~/Library/Caches/Homebrew corresponds to the output of brew --cache.

Rather than store the entire directory to the GitHub Actions cache, the above configuration will only store the files related to the "foo" package. This is because the Homebrew cache directory on the macOS images provided by GitHub already contains files for the base Homebrew install (which you don't need to store again).

You should note that this cache is unlikely to speed up your workflow. Installing Homebrew bottles (the default) will usually have similar performance to downloading from GitHub/Azure's own storage cache since the bottle files are served on bintray's CDN.

like image 143
p00ya Avatar answered Nov 20 '22 11:11

p00ya


This is tricky because actions/cache depends on you putting the libraries in a specific folder that then can be cached and retrieved. And system files have a lot of dependencies which makes each library unique when it comes to this process.

Here are three options that you can take to accomplish this

Path 1:

We could look into installing the brew packages into a specific folder but we cannot do that per package but instead for the whole OS. But according to homebrew https://github.com/Homebrew/brew/blob/664d0c67d5947605c914c4c56ebcfaa80cb6eca0/docs/Installation.md#untar-anywhere it's not a good idea as there could be issues with packages not installing properly. Also this would basically be caching everything which at the end of the day we don't know if it'll be faster than just installing the latest packages you need.

Path 2:

Install the package as you normally would with brew and then copy binaries. The caveat here is that you will need to do this on a per library basis as dependencies some times can get out of hand. Here is an example Caching APT packages in GitHub Actions workflow by going through this process with apt-get in linux, but you can follow same process with brew

Path 3:

Find or create your own docker file image that for which you keep up to date with the latest packages that you want. This would allow you to always have the latest and this will allow you to initialize your steps inside a container build from your docker image. This will then satisfy your system dependencies.

 jobs:
   ci:
     runs-on: ubuntu-latest
     container:
       image: <your-personalized-docker-image>
like image 29
Edward Romero Avatar answered Nov 20 '22 13:11

Edward Romero