CLI tool
travis-ci/travis-build avatar
travis-ci/travis-build

travis-build turns a .travis.yml into the bash script Travis would have run

.travis.yml => build.sh converter

659 stars422 forksRubyMIT

At a glance

What is it?
travis-build is the Ruby service behind Travis CI's build scripts: it takes a .travis.yml, expands it into a bash script, and hands that script to the worker or the job board to execute. Exposed through the travis CLI as travis compile, it is the tool you reach for when a Travis build fails and you want to see the shell script rather than the log.
Who is it for?
Adopt travis-build if you maintain Travis CI pipelines and need to reproduce a failing job locally, because it gives you the exact shell script rather than a log to read. Do not adopt it as a CI system of your own, since it does not run jobs, it only generates the script, and the generated script makes system changes, including edits to /etc/resolv.conf and installs that need sudo and are not easily undone, so the README recommends running it in a container.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A service that generates shell scripts, not a CI system

travis-build is best understood by reading the README's first paragraph carefully, because the name undersells it.

The README says Travis Build exposes an API that Travis Workers and the Job Board use to generate a bash script, which is then copied to the job execution environment and executed, with the resulting output streamed back to Travis. So the pipeline is: a .travis.yml goes in, a bash script comes out, and that script is what actually runs on the worker. travis-build is the part that turns configuration into a shell script.

The codebase has been through several iterations of development. The README says it was originally extracted from the legacy Travis Worker before taking its current form, which tells you the code carries the scars of a system that grew rather than one that was designed once.

The practical audience is narrower than the technology suggests. This is a tool for people who already have a Travis CI build that fails and need to find out why. The web console shows you the log, the log shows you the output of a shell script, and this is how you get the shell script itself.

The repository layout matches a small Sinatra style web service. There is a config.ru for the Rack application, a Procfile for process declarations, a Dockerfile, a docker-compose.yml, an init.rb, lib/ for the code, script/ for the executable entry points, spec/ for the RSpec suite, example_payloads/ for fixtures, and public/ for the compiled assets. The primary language is Ruby, and the licence is MIT with copyright held by the Travis CI development team, dated 2011 to 2016.

Installing it as a plugin for the travis CLI

The travis CLI can load travis-build as a plugin, and the README gives the setup as a sequence of shell commands:

bash
git clone https://github.com/travis-ci/travis-build
cd travis-build
mkdir -p ~/.travis
ln -s $PWD ~/.travis/travis-build
gem install bundler
bundle install --gemfile ~/.travis/travis-build/Gemfile
bundler binstubs travis

The shape of it is worth noting. The repository is cloned, a symlink is placed at ~/.travis/travis-build, which is where the travis CLI looks for plugins, the dependencies are installed from that symlinked Gemfile, and the travis binary is stubbed through bundler so the plugin is on the load path.

After that, you can run travis compile, which produces the bash script that runs the specified job. The README immediately qualifies what you get: the secure environment variables are not defined, and the build matrix expansion is not considered.

Those two limitations are the same limitations as in the invocation section below, and they are the ones that matter. A Travis build that fails in CI may depend on an encrypted variable that only exists on the Travis servers, and a matrix job that fails may be job four of nine, which the local compile will not reproduce. The generated script is a close approximation of one job, not a faithful copy of the job you saw fail.

The test suite is run the usual Ruby way, with bundle exec rake spec, and the README notes that the specs check that parsing, rendering and compiling return the expected results, that formatting follows the guidelines, and that code coverage is at the expected level.

Three ways to invoke compile, and what it will not expand

The compile command has three forms, and the README is precise about each.

Without an argument it produces and prints a bash script from the actions in the local .travis.yml, without considering env and matrix values, and it explains why in parentheses: travis-build is unable to expand these keys correctly. So the local compile gives you the script for the base configuration, with no matrix fan out and no environment variable expansion. The command is:

bash
~/.travis/travis-build/bin/travis compile

With a single integer it produces the script for the given build, or the first job of that build matrix:

bash
~/.travis/travis-build/bin/travis compile 8

With an argument of the form M.N it produces the script for that specific job:

bash
~/.travis/travis-build/bin/travis compile 351.2

That third form is the one that matters in practice, because it is the only way to point at a particular cell of an expanded matrix, and it is how you approximate the job that actually failed. The README is clear that with a single integer you get the first job of the matrix, which is often not the job you are chasing.

The intended use is stated in the README: the generated script can be used in a container or a virtualized environment that closely mimics the Travis CI build environment, to aid in debugging build failures. The instructions for running such a container are pointed at in the Travis CI documentation.

So the workflow is: find the job number, compile it, read the script, run the script in a throwaway environment, and find the line that fails.

The raw CLI path and the Docker route

There are two ways to use the project that do not go through the travis CLI plugin, and both are shorter.

The first is the standalone CLI script, which takes a payload on standard input and writes the build script to standard output:

bash
bundle exec script/compile < payload.json > build.sh

The payload is JSON, and the example_payloads/ directory in the repository holds examples of what that payload looks like. This is the lowest level interface, and it is the one to reach for when you are scripting the compilation of many configurations.

The second is Docker, which the README recommends if you want to run travis-build locally, for example to interact with a Travis worker. The compose file builds a service called web from the repository context, passing a GITHUB_OAUTH_TOKEN build argument, with the RACK_ENV environment variable defaulting to production and port 4000 published on the host:

bash
docker-compose build web

and then:

bash
docker-compose run web

For local development the README shows running the service in the development environment with the container's port 4000 forwarded to the host:

bash
docker-compose run -e RACK_ENV=development -p 4000:4000 web

That creates a container with the contents of the travis-build repository in /usr/src/app and drops you into that directory, from where you can run the same plugin setup commands as before, which is how the compile command becomes available to the Travis CLI inside the container.

The Dockerfile is a two stage Ruby 3.2.2 build. The builder installs the bundle with --frozen --deployment --without='development test', precompiles the assets, and tars up the public directory. The final image is ruby:3.2.2-slim with jemalloc development headers, the app copied in, a health check running script/healthcheck every five seconds, PORT set to 4000, and the server started through script/server. There is also a cron job installed to keep a Go tool up to date.

The generated script changes your system, so use a container

The README puts a warning in a section marked Important, and it is the most operationally important line in the document.

It says the bash script generated by the compile command contains commands that make changes to the system on which it is executed, for example editing /etc/resolv.conf and installing software. Some of those require sudo privileges and they are not easily undone. The recommendation is that it is highly recommended to run this in a container or other virtualized environment.

That is a fair warning, and it is more than boilerplate. A compiled Travis script is a sequence of commands that assume a disposable machine, including network configuration changes and package installs that need root. Run it on a laptop without thinking and you can end up with a modified resolver on your host and packages you did not intend to install.

The container route is therefore not a convenience here, it is the safe default. The Docker path above gives you exactly that, and the compose file's port mapping means the service is reachable on the host for the local worker interaction case without exposing anything beyond your machine.

The other thing to keep in mind is the interaction between the warning and the limitations of the compile output. Because env and matrix expansion are not applied and secure variables are not defined, the script you get is not identical to the one Travis ran, and running it may behave differently from the failed job in ways that are not obvious. Combine the two facts and the sensible procedure is: use compile to find the suspicious commands, then reproduce the environment deliberately rather than hoping the script reproduces the failure on its own.

Maintenance, and a codebase that shows its age

The maintenance picture is mixed, and it is worth understanding before you invest in the tool.

The last push was on 2026-10-09, so the repository is being worked on. There are no GitHub releases, and the version information is stamped into the built artefacts rather than published as tags, with the Dockerfile writing a VERSION file from git describe and a BUILD_SLUG_COMMIT file from the commit hash.

The code itself signals its age honestly. The copyright notice covers 2011 to 2016, which tells you the bulk of the code was written in that window, and the build tooling has been kept current on its own schedule, with ruby:3.2.2 in the Dockerfile and a gem update to 3.3.26 in both stages, and a cron entry that fetches the latest Go toolchain. There is a .rubocop.yml with a .rubocop_todo.yml beside it, a .rspec file, a .simplecov for coverage, and a .ruby-version and .ruby-gemset pinning the Ruby for development.

For a service whose job is to interpret a configuration format, that combination is not fatal. The .travis.yml format is stable, and the generated scripts are what people are usually after when a build breaks. The risk is in the surrounding integration, the worker, the job board and the CLI, all of which live in other repositories and change on their own schedule.

The licence is MIT, with the copyright held by the Travis CI development team, so using the code inside your own tooling carries no obligation beyond keeping the notice.

Editorial conclusion

Adopt travis-build if you maintain Travis CI pipelines and need to reproduce a failing job locally, because it gives you the exact shell script rather than a log to read. Do not adopt it as a CI system of your own, since it does not run jobs, it only generates the script, and the generated script makes system changes, including edits to /etc/resolv.conf and installs that need sudo and are not easily undone, so the README recommends running it in a container. Before you use the output, check what your .travis.yml actually does at the point of failure, and remember that the compiler does not expand env or matrix values and does not define secure environment variables.

Frequently asked questions

What does travis-build do?

It exposes an API that Travis Workers and the Job Board use to generate a bash script from a .travis.yml, which is then copied to the job execution environment and executed with the output streamed back to Travis. The travis CLI plugin exposes that as the travis compile command.

How do I set up travis-build as a Travis CLI plugin?

Clone the repository, create ~/.travis and symlink the clone to ~/.travis/travis-build, then run gem install bundler, bundle install --gemfile ~/.travis/travis-build/Gemfile and bundler binstubs travis. After that you can run travis compile to produce the build script.

What are the limits of travis compile?

The generated script does not have the secure environment variables defined, and the build matrix expansion is not considered because travis-build is unable to expand env and matrix keys correctly. To target a specific matrix cell you pass an argument of the form M.N, for example travis compile 351.2.

Is it safe to run the script that travis compile generates?

Not on a machine you care about. The README warns that the generated script makes changes to the system, such as editing /etc/resolv.conf and installing software, that some steps need sudo and are not easily undone, and it highly recommends running it in a container or other virtualized environment.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. travis-ci/travis-build on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/travis-ci-travis-build.svg)](https://hysenlabs.com/projects/travis-ci-travis-build)

Was this useful?