CI\CD/GitHub Actions

[GitHub Actions] if 사용해 Step이 Fail되었을 때 다음 Step 제어하기

Step의 Fail을 제어하는 것이 필요한 이유

테스트를 돌렸는데 테스트가 Fail 되었을 때 Test 리포트를 업로드 하는 Step이 수행되어야 하는데 수행되지 않는다면 어떻게 될까? 테스트를 돌린 것 자체가 의미가 없어진다. 테스트가 Fail 되면 Test 리포트가 업로드 되어야 한다. 즉, 특정한 Step이 Fail 되더라도 다른 Step이 진행되어야 할 수 있다.

 

Job을 만들다 보면 위와 같은 상황을 자주 마주한다. 이번 글에서는 위 상황을 제어하는 방법에 대해 알아본다. 먼저 문제 상황을 만들어보자

 

문제 상황 만들기

이번 글에서 다룬 문제 상황은 바로 안드로이드에서 테스트를 돌렸는데 실패하는 경우이다.

 

Workflow 파일 만들기

app 모듈에 대해 testDebug Task를 실행하고 테스트 리포트를 upload-artifact를 통해 업로드한다.

name: Handle Failure - Not Handled

on:
  workflow_dispatch:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Check out Repository
        uses: actions/checkout@v3

      - name: set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'
          cache: gradle

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      # Test with Gradle
      - name: Test with Gradle
        run: ./gradlew :app::testDebug

      # Test Report Upload
      - name: Upload Test
        uses: actions/upload-artifact@v3
        with:
          name: test-report
          path: app/build/reports/tests/testDebugUnitTest/index.html

 

Test 실패하도록 만들기

위 동작을 확인하기 위해서 실패하는 간단한 테스트를 만들도록 하자.

internal class GitHubActionTest {
    @Test
    fun testSuccess() {
        assert(false)
    }
}

 

 

문제 상황 실행해보기

여기까지 만들고 GitHub에 올려서 Workflow를 실행해보자. 그러면 Test with Gradle이 실패하자 Upload Test는 생략되는 것을 확인할 수 있다.

 

 

문제 상황 제어하기

문제가 발생한 이유

문제가 발생한 이유는 step은 무조건 순차적으로 실행되고 이전 step이 fail되면 이후 step은 진행하지 않도록 설정되어 있기 때문이다. 이를 해결하기 위해 step이 fail 되더라도 성공된 것으로 설정하는 프로퍼티가 바로 continue_on_error이다.  문서는 아래 링크에서 확인 가능하다.

 

 

GitHub Actions에 대한 워크플로 구문 - GitHub Docs

워크플로에 대한 YAML 구문 정보 워크플로 파일은 YAML 구문을 사용하며 파일 확장명이 .yml 또는 .yaml이어야 합니다. YAML을 처음 사용하며 자세히 알아보려는 경우 “Y분 안에 YAML 알아보기”를 참

docs.github.com

 

continue_on_error 사용해 문제 상황 제어하기

위의 Test with Gradle Step에 continue_on_error: true 를 추가한 후 Workflow을 다시 실행해보자

- name: Test with Gradle
  continue-on-error: true
  run: ./gradlew :app::testDebug

 

그러면 Test with Gradle이 Fail 되더라도 Upload Test가 정상적으로 동작하는 것을 확인할 수 있다. 

 

 

continue_on_error의 한계

하지만 continue_on_error 을 제어하면 실패 하더라도 표시가 나지 않는다. 또한 Step의 error가 무시되어서, 이후의 모든 Step이 진행된다. 하지만 실무에서 CI를 만들 때 일반적인 유즈케이스는 애러가 나면 애러와 관련된 로깅을 하거나 리포트만 올리는 것일 것이다. 따라서 continue_on_error를 사용하는 것은 문제가 있다.

 

이후에 만약 여러 Step이 있는데 Fail 시 특정 Step만 실행하고 싶다면 어떻게 해야할까? 바로 if 문과 GitHub Action에서 제공해주는 failure() 메서드를 사용해 위의 문제 상황을 제어하는 것이다. 

 

if와 failure사용해 이전 step이 실패해도 실행되도록 만들기

위에서 Upload Test가 동작하지 않았던 이유는 아래 코드에 이전 코드가 success될 때만 실행된다는 메서드가 숨어있기 때문이다.

- name: Upload Test
  uses: actions/upload-artifact@v3
  with:
    name: test-report
    path: app/build/reports/tests/testDebugUnitTest/index.html

 

즉, 위 코드는 아래 코드와 같이 동작한다. success() 이전 Step이 모두 성공했을 때만 true를 반환하는 GitHub Action 메서드이다. 위에서 continue_on_error: true로 바꾸면 Test with Gradle Step이 실패하더라도 성공된 것으로 만들기 때문에 아래의 if 문을 통과한 것이다.

- name: Upload Test
  if: success()
  uses: actions/upload-artifact@v3
  with:
    name: test-report
    path: app/build/reports/tests/testDebugUnitTest/index.html

 

따라서 이전 상황이 실패하더라도 해당 Step은 실행되어야 한다면, if: failure()을 추가해 명시적으로 위에 동작을 바꾸면 된다.

- name: Upload Test
  if: failure()
  uses: actions/upload-artifact@v3
  with:
    name: test-report
    path: app/build/reports/tests/testDebugUnitTest/index.html

 

이렇게 바꾼 후 Workflow를 다시 실행해보면 Test with Gradle Step이 실패하더라도 Upload Test는 제대로 실행되는 것을 확인할 수 있다.

 

 

정리

이번 글에서는 특정 Step이 Fail 되었을 때 다른 Step을 제어하는 다양한 방법에 대해 알아보았다. 다음글에서는 특정 Step이 Fail 되었는지 체크 후 실행하는 방법에 대해 알아볼 것이다.

반응형

 

이 글의 저작권은 Dev World 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com