Job Lifecycle
Travis CI provides a default build environment and a default set of phases for each programming language. A virtual machine is created with the build environment for your job, your repository is cloned into it, optional addons are installed and then your build phases are run.
Keep reading to see how you can customize any phase in this process, via your .travis.yml
and have a look at the Travis CI Build Config Reference.
The Build #
The .travis.yml
file describes the build process. A build in Travis CI is a sequence of stages. Each stage consists of jobs run in parallel.
The Job Lifecycle #
Each job is a sequence of phases. The main phases are:
install
- install any dependencies requiredscript
- run the build script
Travis CI can run custom commands in the phases:
before_install
- before the install phasebefore_script
- before the script phaseafter_script
- after the script phase.after_success
- when the build succeeds (e.g. building documentation), the result is inTRAVIS_TEST_RESULT
environment variableafter_failure
- when the build fails (e.g. uploading log files), the result is inTRAVIS_TEST_RESULT
environment variable
There are three optional deployment phases.
The complete sequence of phases of a job is the lifecycle. The steps are:
- OPTIONAL Install
apt addons
- OPTIONAL Install
cache components
before_install
install
before_script
script
- OPTIONAL
before_cache
(if and only if caching is effective) after_success
orafter_failure
- OPTIONAL
before_deploy
(if and only if deployment is active) - OPTIONAL
deploy
- OPTIONAL
after_deploy
(if and only if deployment is active) after_script
A build can be composed of many jobs.
Customizing the Installation Phase #
The default dependency installation commands depend on the project language. For instance, Java builds either use Maven or Gradle, depending on which build file is present in the repository. Ruby projects use Bundler when a Gemfile is present in the repository.
You can specify your own script to install your project dependencies:
install: ./install-dependencies.sh
When using custom scripts, they should be executable (for example, using
chmod +x
) and contain a valid shebang line such as/usr/bin/env sh
,/usr/bin/env ruby
, or/usr/bin/env python
.
You can also provide multiple steps, for instance to install both ruby and node dependencies:
install:
- bundle install --path vendor/bundle
- npm install
When one of the steps in the install fails, the build stops immediately and is marked as errored.
You can also use apt-get
or snap
to install dependencies
Skipping the Installation Phase #
Skip the installation step entirely by adding the following to your .travis.yml
:
install: skip
Customizing the Build Phase #
The default build command depends on the project language. Ruby projects use rake
, the common denominator for most Ruby projects.
You can overwrite the default build step in .travis.yml
:
script: bundle exec thor build
You can specify multiple script commands as well:
script:
- bundle exec rake build
- bundle exec rake builddoc
When one of the build commands returns a non-zero exit code, the Travis CI build runs the subsequent commands as well and accumulates the build result.
In the example above, if bundle exec rake build
returns an exit code of 1, the following command bundle exec rake builddoc
is still run, but the build will result in a failure.
If your first step is to run unit tests, followed by integration tests, you may still want to see if the integration tests succeed when the unit tests fail.
You can change this behavior by using a little bit of shell magic to run all commands subsequently but still have the build fail when the first command returns a non-zero exit code. Here’s the snippet for your .travis.yml
script: bundle exec rake build && bundle exec rake builddoc
This example (note the &&
) fails immediately when bundle exec rake build
fails.
Note on $? #
Each command in script
is processed by a special bash function.
This function manipulates $?
to produce logs suitable for display.
Consequently, you should not rely on the value of $?
in script
section to
alter the build behavior.
See this GitHub issue
for a more technical discussion.
Complex Build Commands #
If you have a complex build environment that is hard to configure in the .travis.yml
, consider moving the steps into a separate shell script.
The script can be a part of your repository and can easily be called from the .travis.yml
.
Consider a scenario where you want to run more complex test scenarios, but only for builds that aren’t coming from pull requests. A shell script might be:
#!/bin/bash
set -ev
bundle exec rake:units
if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then
bundle exec rake test:integration
fi
Note the
set -ev
at the top. The-e
flag causes the script to exit as soon as one command returns a non-zero exit code. This can be handy if you want whatever script you have to exit early. It also helps in complex installation scripts where one failed command wouldn’t otherwise cause the installation to fail.
The -v
flag makes the shell print all lines in the script before executing them, which helps identify which steps failed.
To run that script from your .travis.yml
:
- Save it in your repository as
scripts/run-tests.sh
. - Make it executable by running
chmod ugo+x scripts/run-tests.sh
. - Commit it to your repository.
- Add it to your
.travis.yml
:script: ./scripts/run-tests.sh
How does this work? (Or, why you should not use exit
in build steps) #
The steps specified in the job lifecycle are compiled into a single bash script and executed on the worker.
When overriding these steps, do not use exit
shell built-in command.
Doing so will run the risk of terminating the build process without giving Travis a chance to
perform subsequent tasks.
Using
exit
inside a custom script is safe. If an error is indicated the task will be mark as failed.
Breaking the Build #
If any of the commands in the first four phases of the job lifecycle return a non-zero exit code, the build is broken:
- If
before_install
,install
orbefore_script
returns a non-zero exit code, the build is errored and stops immediately. - If
script
returns a non-zero exit code, the build is failed, but continues to run before being marked as failed.
The exit code of after_success
, after_failure
, after_script
, after_deploy
and subsequent stages do not affect the build result.
However, if one of these stages times out, the build is marked as failed.
Deploying your Code #
An optional phase in the job lifecycle is deployment. This phase is defined by using one of our continuous deployment providers to deploy code to Heroku, Amazon, or a different supported platform. The deploy steps are skipped, if the build is broken.
When deploying files to a provider, prevent Travis CI from resetting your
working directory and deleting all changes made during the build ( git stash
--all
) by adding skip_cleanup
to your .travis.yml
:
deploy:
skip_cleanup: true
You can run commands before a deploy by using the before_deploy
phase. A non-zero exit code in this phase will mark the build as errored.
If there are any steps you’d like to run after the deployment, you can use the after_deploy
phase.
Note that
after_deploy
does not affect the status of the build.
Note that
before_deploy
andafter_deploy
are run before and after every deploy provider, so they will run multiple times, if there are multiple providers.