Skip to content
CI/CD Best Practices

Travis CI

Caching

language: python    
cache: pip

You can also manually specify which directories will be cached, though you can’t choose the cache key.

cache:
  directories:
    - $HOME/.cache/pip
before_cache:
  - rm -f $HOME/.cache/pip/log/debug.log

Debugging Pipelines

Debugging Tools for Travis CI

Travis CI provides debug mode, structured build logs, and build matrix views to help diagnose failures across different configurations.

1. Debug Mode

When to use: Need interactive access to the build environment, want to run commands manually, or need to inspect the environment that caused a failure.

How to enable:

Via Travis CI API:

# Trigger debug build via API
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Travis-API-Version: 3" \
  -H "Authorization: token YOUR_TRAVIS_TOKEN" \
  -d '{"quiet": true}' \
  https://api.travis-ci.com/job/{job_id}/debug

Or restart a job with debug enabled:

  1. Go to your build on travis-ci.com
  2. Click “Restart build” → “Debug build”
  3. Build will start with SSH access enabled

What you get:

  • SSH connection string in build log
  • Access to build environment for 30 minutes
  • Ability to run commands interactively
  • Full access to environment variables and tools

Connect via SSH:

# Connection details appear in build log
ssh XXXXX@ny2.tmate.io

# Once connected, navigate to repo
cd ~/build/username/repo

# Run failed commands with modifications
bundle exec rake test --verbose

Important notes:

  • Debug mode available on private repositories
  • Session expires after 30 minutes
  • Build doesn’t automatically proceed - you control execution

2. Build Logs with Fold Sections

When to use: First place to look for any Travis build failure. Logs are structured with collapsible sections for easy navigation.

How to access:

  1. Click on your build in Travis CI dashboard
  2. Logs appear automatically in main view
  3. Click sections to expand/collapse

What you see:

  • Worker info: VM image, environment details
  • System info: OS, kernel version, tools
  • Before install: Dependency setup
  • Install: Package installation
  • Before script: Pre-test setup
  • Script: Main build/test commands
  • After success/failure: Post-build steps

Add custom fold sections:

# .travis.yml
script:
  - echo -e "travis_fold:start:tests"
  - echo "Running tests..."
  - npm test
  - echo -e "travis_fold:end:tests"

  - echo -e "travis_fold:start:linting"
  - echo "Running linter..."
  - npm run lint
  - echo -e "travis_fold:end:linting"

Debugging tips:

# Add verbose output
script:
  - echo "=== Environment Check ==="
  - node --version && npm --version
  - echo "=== Disk Space ==="
  - df -h
  - echo "=== Running Tests ==="
  - npm test -- --verbose

3. Build Matrix View

When to use: Testing across multiple configurations (Node versions, OS, etc.) and need to identify which specific configuration is failing.

How to access: Build page automatically shows matrix if configured in .travis.yml

What you get:

  • Visual grid of all build combinations
  • Quick identification of failing configurations
  • Compare successful vs failed builds
  • Isolate environment-specific issues

Example matrix configuration:

language: node_js
node_js:
  - '16'
  - '18'
  - '20'
os:
  - linux
  - osx
  - windows

This creates 9 builds:

  • Node 16 + Linux
  • Node 16 + macOS
  • Node 16 + Windows
  • Node 18 + Linux
  • Node 18 + macOS
  • … etc

Debugging matrix failures:

If only specific combinations fail:

# Exclude known problematic combinations
jobs:
  exclude:
    - os: windows
      node_js: '16'  # Known issue with Windows + Node 16

  # Or allow specific failures
  allow_failures:
    - os: windows  # Windows builds can fail without blocking

Access matrix-specific environment:

script:
  - echo "Testing on $TRAVIS_OS_NAME with Node $(node --version)"
  - npm test

Tips for matrix debugging:

  • Start with minimal matrix (1-2 combinations) to isolate
  • Add configurations incrementally
  • Use allow_failures for unstable environments
  • Compare logs between passing and failing matrix builds

Local Validation

Local Validation with Docker

Travis CI doesn’t provide an official local runner, but you can validate your build logic using Docker Compose to replicate the Travis environment.

When to Use This Approach

Use Docker-based validation for:

  • Testing .travis.yml build scripts
  • Validating install and test commands
  • Debugging build failures locally
  • Developing new build stages

Note: This validates your actual build logic but not Travis-specific syntax or features.

Working Example

Create docker-compose.ci.yml matching your Travis configuration:

version: '3.8'

services:
  travis-validator:
    # Match your Travis language and version
    image: node:18

    working_dir: /build

    volumes:
      - .:/build
      - /build/node_modules

    # Replicate Travis lifecycle
    command: |
      bash -c "
        echo '==> before_install' &&
        # Add before_install commands here

        echo '==> install' &&
        npm ci &&

        echo '==> before_script' &&
        # Add before_script commands here

        echo '==> script' &&
        npm test &&

        echo '==> after_success' &&
        echo 'Build passed ✅'
      "

    environment:
      CI: true
      TRAVIS: true
      CONTINUOUS_INTEGRATION: true

Basic Usage

# Run complete build
docker-compose -f docker-compose.ci.yml run --rm travis-validator

# Run specific lifecycle stage
docker-compose -f docker-compose.ci.yml run --rm travis-validator bash -c "npm test"

# Debug interactively
docker-compose -f docker-compose.ci.yml run --rm travis-validator bash

Matching Your Travis Configuration

Map from .travis.yml to Docker Compose:

Your .travis.yml:

language: node_js
node_js:
  - "18"

cache:
  directories:
    - node_modules

before_install:
  - npm install -g typescript

install:
  - npm ci

before_script:
  - npm run build

script:
  - npm test
  - npm run lint

after_success:
  - npm run coverage

Equivalent Docker Compose:

services:
  travis-validator:
    image: node:18
    working_dir: /build
    volumes:
      - .:/build
      - node_modules_cache:/build/node_modules
    command: |
      bash -c "
        echo '==> before_install' &&
        npm install -g typescript &&

        echo '==> install' &&
        npm ci &&

        echo '==> before_script' &&
        npm run build &&

        echo '==> script' &&
        npm test &&
        npm run lint &&

        echo '==> after_success' &&
        npm run coverage
      "
    environment:
      CI: true

volumes:
  node_modules_cache:

Language-Specific Examples

Python:

services:
  travis-validator:
    image: python:3.11
    working_dir: /build
    volumes:
      - .:/build
    command: |
      bash -c "
        pip install -r requirements.txt &&
        pytest &&
        flake8
      "

Ruby:

services:
  travis-validator:
    image: ruby:3.2
    working_dir: /build
    volumes:
      - .:/build
    command: |
      bash -c "
        bundle install &&
        bundle exec rake test
      "

Go:

services:
  travis-validator:
    image: golang:1.21
    working_dir: /go/src/app
    volumes:
      - .:/go/src/app
    command: |
      bash -c "
        go mod download &&
        go test ./... &&
        go build
      "

Adding Service Dependencies

If your Travis build uses databases or services:

Your .travis.yml:

services:
  - postgresql
  - redis

env:
  - DATABASE_URL=postgres://postgres@localhost/test

Docker Compose equivalent:

services:
  travis-validator:
    image: node:18
    working_dir: /build
    volumes:
      - .:/build
    depends_on:
      - postgres
      - redis
    environment:
      DATABASE_URL: postgres://postgres:password@postgres:5432/test
      REDIS_URL: redis://redis:6379
    command: |
      bash -c "
        npm ci &&
        npm test
      "

  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_DB: test

  redis:
    image: redis:7-alpine

Limitations

What this validates:

  • ✅ Build commands execute correctly
  • ✅ Tests pass in similar environment
  • ✅ Dependencies install properly
  • ✅ Scripts work as expected

What it doesn’t validate:

  • ❌ Travis .travis.yml syntax (use travis lint instead)
  • ❌ Travis-specific features (deploy providers, encryption)
  • ❌ Build matrix combinations
  • ❌ Travis environment variables and secrets

Syntax validation:

Install Travis CLI for syntax checking:

gem install travis

# Validate .travis.yml syntax
travis lint

This catches syntax errors but doesn’t run builds. Combine with Docker Compose for full validation.

Workflow Integration

Pre-push validation script:

Create scripts/validate-travis.sh:

#!/bin/bash
set -e

echo "Validating Travis syntax..."
travis lint --exit-code

echo "Running build locally..."
docker-compose -f docker-compose.ci.yml run --rm travis-validator

echo "✅ Travis build validated successfully"

Make it executable:

chmod +x scripts/validate-travis.sh

Run before pushing:

./scripts/validate-travis.sh
git push

Tips

  • Match the image: Use the same base image version as Travis (check Travis CI images)
  • Replicate lifecycle order: Follow Travis’s exact order: before_installinstallbefore_scriptscript
  • Use travis lint: Always validate syntax with the Travis CLI first
  • Test incrementally: Run commands interactively to debug before committing to Docker Compose config
  • Document environment: Note any differences between Docker and Travis in your README
  • Keep in sync: Update Docker Compose when changing .travis.yml

Alternative Tools

travis-build (unofficial, limited):

# Clone travis-build
git clone https://github.com/travis-ci/travis-build.git
cd travis-build

# Compile .travis.yml to bash script
bin/travis compile > ci-script.sh

# Review and run
bash ci-script.sh

Warning: This is an internal Travis tool not officially supported for local use. Docker Compose is more reliable.

Parallelisation

Say you want to split up your unit tests and your integration tests into two different build jobs. They’ll run in parallel and fully utilize the available build capacity for your account.

Here’s an example on how to utilize this feature in your .travis.yml:

env:
  - TEST_SUITE=units
  - TEST_SUITE=integration

Then you change your script command to use the new environment variable to determine the script to run.

script: "bundle exec rake test:$TEST_SUITE"

Travis CI will determine the build matrix based on the environment variables and schedule two builds to run.