logo

【GitHub Actions】Docker Composeで実行したテスト結果をWorkflowに伝える方法

【GitHub Actions】Docker Composeで実行したテスト結果をWorkflowに伝える方法

はじめに

GitHub ActionsのWorkflowでDocker Composeを使ってテストを実行する際、テストが失敗してもWorkflowが成功扱いになってしまう問題が発生しました。

この記事では、以下の2つの問題の原因と解決策を解説します。

  1. Docker Composeで実行したテスト結果がWorkflowに反映されない
  2. upload-artifactを追加するとWorkflowが必ず成功扱いになる

サンプルコード

mizuyi/practice-jest-docker-compose-ci | GitHub

github.com

発生した問題と解決策

問題1: テスト結果がWorkflowに反映されない

最初は以下のようなワークフローでDocker Compose経由でテストを実行していました。

name: Test with Docker

on:
  push:
    branches:
      - main
      - feature/**

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Build Docker image
        run: docker compose -f compose.test.yml build

      - name: Run test
        run: docker compose -f compose.test.yml up

しかし、コンテナ内のテストが失敗しても、Workflowのステップは成功扱いになってしまいました。

workflow-exit-code-0

原因

テストの結果にかかわらず、docker compose upコマンドが exit code=0(成功)を返していました。

  1. コンテナ内でJestテストが失敗(exit code=1)
  2. docker compose upは正常に終了(exit code=0)
  3. Workflowは成功と判定

解決方法

--exit-code-from オプションを使用することで、特定のサービスの終了コードをdocker compose upコマンド全体の終了コードとして使用できます。

  - name: Run test
    run: |
-     docker compose -f compose.test.yml up
+     docker compose -f compose.test.yml up --exit-code-from test-with-docker

これにより、テストの結果がWorkflowに伝わりました。

問題2: upload-artifactを追加するとWorkflowが必ず成功扱いになる

問題1を解決した後、テスト結果をHTMLレポートとしてアーティファクトにアップロードする機能を追加しました。

- name: Run test
  run: |
    docker compose -f compose.test.yml up --exit-code-from test-with-docker

- name: Upload test result to artifact
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: test-result
    path: test-result

しかし、この構成ではテストが失敗してもWorkflow全体が成功扱いになってしまいました。

原因

if: always() を使用すると、前のステップが失敗しても後続のステップが実行されます。しかし、GitHub Actionsのデフォルト動作では、最後に実行されたステップが成功すればWorkflow全体も成功と判定されます。

つまり、以下のような状況が発生していました:

  1. Run test ステップでテストが失敗(終了コード1)
  2. Upload test result to artifact ステップが if: always() により実行される
  3. アップロードステップが成功(終了コード0)
  4. Workflow全体が成功と判定される(本来は失敗すべき)

解決方法

以下の3つの要素を組み合わせて解決します:

  1. continue-on-error: true: テスト失敗時もWorkflowを継続
  2. id: test: テストステップに識別子を付与
  3. steps.test.outcome == 'failure': 最終ステップでテスト結果を確認し、明示的に失敗させる
  - name: Run test
+   id: test
+   continue-on-error: true
    run: |
      docker compose -f compose.test.yml up --exit-code-from test-with-docker

  - name: Upload test result to artifact
    uses: actions/upload-artifact@v4
    if: always()
    with:
      name: test-result
      path: test-result

+ - name: Check test result
+   if: steps.test.outcome == 'failure'
+   run: |
+     echo "Test failed"
+     exit 1
  • テストが失敗しても continue-on-error: true でWorkflowは継続
  • アーティファクトのアップロードが if: always() で必ず実行される
  • 最終ステップで steps.test.outcome を確認し、テストが失敗していれば明示的に exit 1 でWorkflowを失敗させる

各設定のポイント

--exit-code-from test-with-docker

指定したサービスの exit code を、docker compose upコマンド exit code として使用します。
これにより、テストの結果がWorkflowに伝わりました。

continue-on-error: true

テストが失敗してもWorkflowを継続させます。これにより、テスト失敗時でもアーティファクトのアップロードが実行されます。
ただし、これだけでは最終的にWorkflowが成功扱いになるため、 steps.test.outcome チェックが必要です。

steps.test.outcome == 'failure'

最終ステップでテスト結果を確認し、失敗していた場合は明示的に exit 1 でWorkflow全体を失敗させます。

重要: continue-on-error: true を使用している場合、steps.test.result ではなく steps.test.outcome を使用してください。

  • steps.test.outcome:ステップの実際の実行結果(continue-on-error の影響を受けない)
  • steps.test.result:ステップの最終的な結果(continue-on-error: true の場合、失敗しても success になる)

まとめ

Docker ComposeでテストをGitHub Actionsで実行する際の2つの問題と解決策

問題1: テスト結果がWorkflowに反映されない

  • --exit-code-from でテストコンテナの終了コードを使用

問題2: アーティファクトアップロードで成功扱いになる

  • continue-on-error: true でWorkflowを継続
  • steps.test.outcome でテスト結果を最終判定