Last Updated: July 24, 2020
· cs3b

Speed up Travis-CI build preparation time by 800%


update 2013-10-22

Travis-Ci introduce caching -
So far it is only available for private repositories, still it is worth to look at this instead of custom solution that I've drafted in that document. Thanks for Travis-CI guys for finally implementing it :-)


We want to start using travis-ci our customers projects, unfortunately preparing build was taking 8 minutes, and it is the time before test are starting. Another drawback from this, was fact that parallelism builds have no value (each instance will take their 8 minutes before running tests), and we really want to use this Travis-Ci feature ( )

So I spend last day's in order to improve this - result: preparation is taking less then a one minute :-)

here is our final travis.yml file

language: ruby
  - 1.9.3
  - TAG_FILTER=~js DB=postgres RAILS_ENV=test
  - TAG_FILTER=js DB=postgres RAILS_ENV=test
install: touch ~/do_not_run_bundle
  - "./script/travis/ &"
  - "./script/travis/ &"
  - "./script/travis/"
  - "bundle exec ruby script/travis/bundle_cache.rb &"
script: "bundle exec rspec --tag $TAG_FILTER && sleep 1"
  email: false

1) Caching .bundle directory

the most time consuming tasks was installing gems (6 minutes), so we thought what it would be if we will cache .bundle directory :-) Compressed directory is about 110MB - downloading it from us-west-1 takes 30 seconds in average, from eu-west-1 50 seconds. The most fastest is keeping your file in hetzner server if you have any ( 5 seconds in average).
In case you wish to encrypt your credentials, please read -


require 'fog/storage'
file_name = 'bundle.tgz'
s3_file_path = "travis/#{file_name}"
local_file_path = file_name
storage ={
  :provider => 'AWS',
  :aws_access_key_id => '<KEY>',
  :aws_secret_access_key => '<ACCESS_KEY>',
  :region => 'us-west-1'

# prepare archive

`rm -rf #{local_file_path}`
`tar -cjf bundle.tgz .bundle`

# put on s3

bucket = '<YOUR_BUCKET>')
file =
bucket.files.create(body:, key: s3_file_path, public: true)

3 things worth noted are
* we upload file with public permission, thanks to that we are able to download file with authorization (.bundle directory is usually nothing secret)
* we prepare cache in the background - so it's not delay starting tests
* we skip installing gems that are are used only in development



curl -o bundle.tgz https://<HOST_NAME>/travis/bundle.tgz
tar -xf bundle.tgz

bundle install --path .bundle --quiet --without=development

exit 0

2) loading database without rake

just set to dump you schema in sql format and you will save another 60 seconds :-)


config.active_record.schema_format = :sql



psql -c 'create database <DB_NAME>;' -U postgres
psql -U postgres -q -d <DB_NAME> -f db/structure.sql
cp -f config/travis/database.yml config/database.yml

3) separate configuration for rspec ( spec_helper.rb .rspec)

in development we use spork - for ci we don't, so we remove few unnecessary lines from spec_helper and prepare separate file (more readable then many if's) - it will give you a few seconds more of speed up

It's is definitely possible to write it in better - still I see that idea is worth of sharing. Hope that in some day travis-ci will give possibility to use somekind cache directory between builds out of the box :-) (for Pro Users - ask support if you don't have yet:

There is one more challenge that I have with Travis-CI, but this is something for the next holiday time :-)

5 Responses
Add your response

@minad yeah that's true - we also use hetzner for caching bundle bacause
1) it's much faster (but it will change after travis-ci infrastructure will be moved to us)
2) if you are not buying server especial for bundle cache, it's much cheaper

still Amazon S3 is more widely available

over 1 year ago ·

I've also noted that using gzip instad of bzip2 for compression get much better results for decompression ( in our case it gives another 8 seconds less for preparation phase).

This of course apply most when you host your files on hetzner server ( files size increase a little, from 114 MB to 123 MB)

over 1 year ago ·

Inspired by this post, I wrote my own version of the S3 bundle cache script (heavily inspired by your code):

The main difference would probably be that my script only uploads a new version of the bundle if the Gemfile.lock has changed.

I also use a multipart upload to S3 due to some slowness I encountered while testing this script (though that particular issue has been fixed by the Travis team now).

over 1 year ago ·

@k33l0r thx for writing a better implementation :-) maybe with time it will land as default for travisci pro

over 1 year ago ·

does this work only for travis pro?

over 1 year ago ·