Travis CI

CI/CDTravis CIオープンソースGitHub自動化クラウドYAMLシンプル

CI/CDツール

Travis CI

概要

Travis CIはオープンソースプロジェクト向けの老舗CI/CDサービスです。GitHub統合、シンプルな設定、多言語サポートが特徴で、.travis.ymlによる分かりやすい設定でCI/CDパイプラインを構築できます。

詳細

Travis CI(トラビスシーアイ)は、2011年に設立されたクラウドベースのCI/CD(継続的インテグレーション・継続的デリバリー)サービスです。オープンソースプロジェクト向けのCI/CDの先駆者として、GitHub統合に特化した設計により多くの開発者に愛用されています。リポジトリ内の.travis.ymlファイルでビルド設定を定義し、バージョン管理されたCI/CD設定を実現します。2024年3月には開発者生産性向上のためのアップデートが実施され、.travis.yml設定ファイル内でジョブログの長さを定義できる機能が追加されました。Java、Node.js、Python、Ruby、PHP等の主要言語をネイティブサポートし、各言語に最適化されたビルド環境を提供します。Linux、macOS、Windowsの複数プラットフォームに対応し、Build Config Importsによる共有設定機能で大規模プロジェクトの管理効率を向上させます。オープンソースプロジェクトには無料プランを提供し、プライベートプロジェクトには有料プランで高度な機能を利用可能です。

メリット・デメリット

メリット

  • GitHub完全統合: Pull Request、Issue、Release等との緊密連携
  • シンプルな設定: .travis.ymlファイルによる直感的な設定
  • 多言語サポート: 主要言語の最適化されたビルド環境
  • オープンソース親和性: 無料プランでOSSプロジェクト支援
  • プラットフォーム対応: Linux、macOS、Windows環境
  • コミュニティサポート: 長年のユーザーベースと豊富な情報
  • 共有設定機能: Build Config Importsによる設定再利用
  • 歴史と実績: 10年以上の運用実績と安定性

デメリット

  • 機能制限: 他のCI/CDツールと比較して機能が限定的
  • パフォーマンス: ビルド速度と並列処理能力の課題
  • カスタマイズ制限: 高度なワークフロー制御の制約
  • 料金体系: プライベートプロジェクトでのコスト
  • 企業機能不足: エンタープライズ向け機能の不足
  • プラットフォーム制限: Windows完全サポートの課題
  • 競合優位性: 新興サービスとの機能格差

主要リンク

書き方の例

基本的なNode.js設定

# .travis.yml
language: node_js
node_js:
  - "18"
  - "20"
  - "22"

cache:
  directories:
    - node_modules

before_script:
  - npm install

script:
  - npm run test
  - npm run lint
  - npm run build

after_success:
  - npm run coverage

notifications:
  email:
    recipients:
      - [email protected]
    on_success: change
    on_failure: always

マルチ言語プロジェクト

# .travis.yml
matrix:
  include:
    - language: node_js
      node_js: "18"
      script:
        - npm install
        - npm test
    - language: python
      python: "3.9"
      install:
        - pip install -r requirements.txt
      script:
        - python -m pytest
    - language: java
      jdk: openjdk11
      script:
        - ./gradlew test

env:
  - NODE_ENV=test
  - PYTHON_ENV=test
  - JAVA_OPTS="-Xmx1024m"

before_install:
  - echo "Setting up multi-language environment"

cache:
  directories:
    - node_modules
    - $HOME/.cache/pip
    - $HOME/.gradle/caches/

Docker統合ビルド

# .travis.yml
language: minimal

services:
  - docker

env:
  - DOCKER_COMPOSE_VERSION=2.21.0

before_install:
  - sudo rm /usr/local/bin/docker-compose
  - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
  - chmod +x docker-compose
  - sudo mv docker-compose /usr/local/bin

script:
  - docker build -t myapp:latest .
  - docker run --rm myapp:latest npm test
  - docker-compose up -d
  - docker-compose exec web npm run test:integration
  - docker-compose down

after_success:
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
  - docker tag myapp:latest $DOCKER_USERNAME/myapp:$TRAVIS_BUILD_NUMBER
  - docker tag myapp:latest $DOCKER_USERNAME/myapp:latest
  - docker push $DOCKER_USERNAME/myapp:$TRAVIS_BUILD_NUMBER
  - docker push $DOCKER_USERNAME/myapp:latest

branches:
  only:
    - main
    - develop

デプロイメント設定

# .travis.yml
language: node_js
node_js: "18"

cache:
  directories:
    - node_modules

script:
  - npm test
  - npm run build

deploy:
  - provider: pages
    skip_cleanup: true
    github_token: $GITHUB_TOKEN
    local_dir: dist
    on:
      branch: main
  
  - provider: heroku
    app: myapp-staging
    api_key: $HEROKU_API_KEY
    on:
      branch: develop
  
  - provider: heroku
    app: myapp-production
    api_key: $HEROKU_API_KEY
    on:
      branch: main

  - provider: script
    script: bash scripts/deploy.sh
    on:
      branch: main
      condition: $TRAVIS_TAG =~ ^v[0-9]+

env:
  global:
    - NODE_ENV=production
    - secure: "encrypted_api_key_here"

notifications:
  slack:
    rooms:
      - secure: "encrypted_slack_token"
    on_success: change
    on_failure: always

ブランチ制御とステージ分離

# .travis.yml
language: node_js
node_js: "18"

# ブランチ制御
branches:
  only:
    - main
    - develop
    - /^feature\/.*$/
  except:
    - legacy
    - experimental

# ビルドステージ定義
stages:
  - name: test
  - name: build
    if: branch IN (main, develop)
  - name: deploy
    if: branch = main

jobs:
  include:
    # テストステージ
    - stage: test
      name: "Unit Tests"
      script:
        - npm run test:unit
    
    - stage: test
      name: "Integration Tests"
      script:
        - npm run test:integration
    
    - stage: test
      name: "Linting"
      script:
        - npm run lint
        - npm run type-check

    # ビルドステージ
    - stage: build
      name: "Build Application"
      script:
        - npm run build
      after_success:
        - npm run build:analyze

    # デプロイステージ
    - stage: deploy
      name: "Deploy to Production"
      script: skip
      deploy:
        provider: script
        script: bash scripts/deploy-production.sh
        on:
          branch: main

before_install:
  - nvm install $TRAVIS_NODE_VERSION
  - npm install -g npm@latest

install:
  - npm ci

cache:
  directories:
    - node_modules
    - $HOME/.npm

env:
  global:
    - NODE_ENV=test
  matrix:
    - TEST_SUITE=unit
    - TEST_SUITE=integration

セキュリティとシークレット管理

# .travis.yml
language: node_js
node_js: "18"

before_script:
  - npm audit
  - npm run security:check

script:
  - npm test
  - npm run build

after_script:
  - npm run coverage:report

# 暗号化された環境変数
env:
  global:
    - secure: "encrypted_api_key_1"
    - secure: "encrypted_api_key_2"
    - NODE_ENV=test

# 暗号化されたファイル
before_install:
  - openssl aes-256-cbc -K $encrypted_key -iv $encrypted_iv -in secrets.tar.enc -out secrets.tar -d
  - tar xvf secrets.tar

addons:
  sonarcloud:
    organization: "myorg"
    token:
      secure: "encrypted_sonar_token"

  code_climate:
    repo_token: 
      secure: "encrypted_codeclimate_token"

after_success:
  - bash <(curl -s https://codecov.io/bash)
  - sonar-scanner

notifications:
  email:
    recipients:
      - secure: "encrypted_email_1"
      - secure: "encrypted_email_2"
    on_success: change
    on_failure: always
  
  webhooks:
    urls:
      - secure: "encrypted_webhook_url"
    on_success: change
    on_failure: always