Step 실패 시 흐름 제어
이전 글에서 if와 failure() 을 조합해 Step 실패 시 실행되는 Step을 정의해보았다. 그렇다면 만약 여러 Step이 있고 특정 Step이 fail 되었을 때만 수행되어야 하는 Step이 있으면 어떻게 해야할까? 바로 if 문에 step failure을 체크하기 위한 코드를 추가하는 것이다. 이를 위해 다른 step의 어떤 상태 값에 접근할 수 있는지 Context를 확인해보자.
특정 step이 fail 되었는지 체크하기 위한 Context
steps Context 에서는 steps.<step_id>.outcome 를 통해 step 실행 결과에 대한 상태 값을 제공한다.
속성 이름 | Type | Description |
steps.<step_id>.outcome | string | continue-on-error가 적용되기 전 완료된 단계의 결과입니다. 가능한 값은 success, failure, cancelled 및 skipped입니다. continue-on-error 단계가 실패하면 outcome은 failure이지만 최종 conclusion은 success입니다. |
즉, id가 abc라면 steps.abc.outcome 값이 'failure'이면 해당 Step은 실패한 것이다.
continue-on-error: true가 문제인 이유
앞선 글에서 continue-on-error은 되도록 쓰지 말아야 한다고 이야기 했다. outcome에 대한 description에도 이유가 적혀있다.
continue-on-error 단계가 실패하면 outcome은 failure이지만 최종 conclusion은 success입니다.
즉, continue-on-error: true 가 되면 outcome 값이 무조건 true 가 됨을 알 수 있다. 이 말은 outcome이 fail 되더라도 강제로 success가 된다는 것이다. 이렇게 하면 continue-on-error: true가 들어간 step은 실패에 따른 제어가 불가능해짐을 뜻한다. 따라서 되도록 쓰지 않는 것이 좋다.
* 물론 써야 할 곳에는 써야 한다.
자 이제 이 상태값을 사용해 if 문에 조건을 추가해보자.
특정 step fail 되었는지 확인하기
Test가 실패했을 때만 Test를 업로드하면 된다. 만약 JDK를 설정하거나 코드를 체크아웃 하는 작업이 실패하면 굳이 Test를 업로드 할 필요가 없다. 따라서 Test with Gradle과 Upload Test를 다음과 같이 바꾸자.
- name: Test with Gradle
id: exec-test
run: ./gradlew :app::testDebug
- name: Upload Test
if: failure() && steps.exec-test.outcome == 'failure'
uses: actions/upload-artifact@v3
with:
name: test-report
path: app/build/reports/tests/testDebugUnitTest/index.html
Test with Gradle에는 exec-test라는 <step_id>를 추가했고 Upload Test Step의 if 문에는 steps.exec-test.outcome == 'failure' 을 추가해 해당 Step이 Test with Gradle 이 실패했을 때만 실행되도록 만들었다.
Workflow 실행하기
이제 Workflow를 실행하면 다음과 같이 나오는 것을 확인할 수 있다.
Test with Gradle이 실패했을 때만 Upload Test가 실행된다.