I have a Travis CI osx
build with a brew
dependency that has to be built from source.
I know that Travis has the cache
feature, but it doesn't have any documentation on how to cache brew
builds or outputs.
Any idea on how to cache a brew
package in travis?
There are 3 separate, loosely related problems here:
You don't necessarily need all three, so follow whichever sections fit your needs.
Add $HOME/Library/Caches/Homebrew
to Travis' cache (actually, this path is supposed to be retrieved with brew --cache
but you can't call it here, can you)
cache: directories: - $HOME/Library/Caches/Homebrew
Run brew cleanup
at before_cache
stage -- otherwise, the cache will grow indefinitely as new package versions are released
before_cache: - brew cleanup
The full code is too long to list it here so giving the algorithm.
This is in addition to the previous section. If using without it, save local bottles somewhere outside of Homebrew cache at on installing step and add them to the cache under appropriate names at the at startup step below.
On installing:
brew deps
recursively (bottled)
in brew info <pkg>
output), include build dependencies with --include-build
For each of the packages and dependencies,
brew list --versions <pkg>
succeeds) and latest version (absent from brew outdated
), skip itbrew unlink
the old version if it's not keg-only (no [keg-only]
in brew info
output)brew install
's with --force
brew install
itIf a bottle is not available,
Build and install it with the following sequence:
brew install --build-bottle <pkg> brew bottle --json <pkg> brew uninstall --ignore-dependencies <pkg> brew install <bottle>
(There doesn't seem to be any official way to get the names of the resulting bottle and JSON file. I took the bottle name from brew bottle
output and inferred JSON file name from it.)
Add the bottle info into the package's formula
brew bottle --merge --write <json file>
Save the bottle file into Travis cache under an appropriate name given by brew --cache <pkg>
$HOME/Library/Caches/Homebrew
. You don't need to do this.)At startup:
brew update
if you're going tobrew info --json=v1 <pkg>
and brew info --json=v1 <bottle>
for this data). brew --cache
at this point, you need to have saved it independently. Symlinks aren't being saved in Travis' cache as of this writing, so I ended up using regular files that held the paths.brew --cache <pkg>
still points to your bottle after adding the info.At before_cache
:
brew cleanup
from the previous section, save your locally-built bottle files from cache somewhere before running it because cleanup
may delete those that weren't needed this time around. After cleanup
, restore those that were deleted.(Again, the full code is too long so giving the algorithm.)
If you run brew update --verbose
(and make sure there are no secret variables in .travis.yml
or your Travis project settings -- brew
prints many status messages only if stdout
is a tty) -- you'll see what exactly consititutes a Homebrew selfupdate operation -- thus what you should cache:
rebase
'ing by default) into a few paths that are actually git
repositories: /usr/local/Homebrew
-- Homebrew itself/usr/local/Homebrew/Library/Taps/*/*
-- installed tapsTaps/caskroom/homebrew-cask
to Taps/homebrew/homebrew-cask
, creating a copy at Taps/homebrew/homebrew-cask/homebrew-cask
. If cached, this copy will cause an "error: file exists" on the next run.Taps/homebrew/homebrew-versions
So, the actions will be:
Add /usr/local/Homebrew
to Travis cache
postinstall
scripts may affect other arbitrary parts of the system, so one should install new package versions from (cached) bottles each time rather than cache the result. Installing a bottle only takes a few seconds anyway.Before brew update
: clean up Homebrew codebase
Taps/caskroom/homebrew-cask
dir if Taps/homebrew/homebrew-cask
existsgit
repos under /usr/local/Homebrew
(find -type d -name .git
, get dirname
of the result) and run git clean -fxd
in each to get rid of Travis' leftoversbrew cleanup
(if using in conjunction with the previous section, see there for additional operations) -- otherwise, you'll get lots of errors in brew update
on the "Migrating cache entries..." stage.At brew update
:
brew update --merge
instead -- it will auto-resolve any possible conflicts with your local commits with bottle infoWhen re-adding local bottles (if using in conjunction with the previous section):
git commit
the result. There's no stock way to do that, so you'll have to parse and edit the formula file with a script and delete the corresponsing line from bottle do
table. The path to the formula file is retrieved with brew formula <pkg>
.When installing:
If using 3rd-party taps, always check if you already have that tap installed:
brew tap | grep -qxF <tap> || brew tap <tap>
Since symlinks aren't saved in Travis cache, pins will likely not be remembered. But it won't hurt to check for them, too:
brew tap --list-pinned | grep -qxF <tap> || brew tap-pin <tap>
At before_cache
:
Taps/homebrew/homebrew-cask/homebrew-cask
if it existsIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With