값의 전달이 필요한 이유
앞선 글에서 Job 간에 파일을 전달하는 방법에 대해 알아보았다. 하지만, 대용량 파일을 전달할 때 말고 단순한 값들을 전달하는 것이 필요할 때가 있다. 예를 들어 앞선 글들에서는 upload-artifact에서 name으로 사용한 값을 download-artifact를 사용하기 위해 똑같이 복사 붙여넣기 해주는 과정을 거쳤는데, 이 값을 직접 전달한다면 더욱 안정성이 증가할 것이다. 혹은 랜덤한 Hash 값을 전달해야 할 수도 있는데, 이 값을 매번 생성해주는 것보다는 전달하는 것이 좋다.
자 이제 outputs 객체에 데이터를 저장하고 꺼내는 방법에 대해 살펴보도록 하자.
outputs 객체를 사용해 Job간에 데이터 전달하기
Job 간에 데이터를 전달하기 위해서는 outputs 객체에 데이터를 저장해야 한다. outputs 객체는 GitHub Actions의 Context에 포함되어 있으며, key-value 형태로 데이터를 저장한다. 시각적으로 과정을 살펴보자.
먼저 outputs 객체에 Key=Value 로 저장요청을 한다.
그러면 outputs에 Key=Value 데이터가 저장된다.
이후 Key를 읽기 요청을 하면 Value를 응답한다.
자 이제 값을 저장하는 부분부터 살펴보자.
outputs 에 데이터 저장하기
outputs에 데이터를 저장하기 위해서는 두가지 과정을 거쳐야 한다.
- Step 수준의 outputs에 데이터를 저장
- Step 수준에 저장된 데이터를 Job 수준의 outputs로 가지고 나와야 한다.
Step 수준의 outputs에 데이터 저장하기
먼저 Step 수준의 output에 데이터를 key-value 쌍으로 저장하기 위해서는 다음 명령어를 실행해야 한다.
echo '[key]=[value]' >> $GITHUB_OUTPUT
그러면 steps.[step_id].outputs.[key] 위치에 [value]가 저장된다.
예를 들어 아래와 같이 step을 만들면 steps.write-step.outputs.apk-filename 에 test가 저장된다.
steps:
- name: Write outputs to step
id: write-step
run: echo 'apk-filename=test' >> $GITHUB_OUTPUT
이제 이 Step 수준의 output을 Job 수준으로 끌어 올려보도록하자.
Job 수준의 outputs에 데이터 저장하기
Job 수준의 Outputs에 데이터를 저장하기 위해서는 outputs: 블록을 선언해야 한다. 이후 하위에 [Job Output Key]: [Job Output Value]를 설정하면 해당 Job들간에 공유할 수 있는 Key-Value 쌍이 만들어진다.
outputs:
[Job Output Key]: [Job Output Value]
위에서 만든 Step 수준의 Key-Value 쌍을 Job 수준으로 끌어올려 보도록 하자. [Job Output Key]는 apk-name으로 [Job Output Value]는 위에서 만든 step 수준의 output 값을 읽어오는 $${ steps.write-step.outputs.apk-filename } 로 설정하도록 한다.
build:
runs-on: ubuntu-latest
outputs:
# Step 중 apk-publish 라는 id를 가지고 있는 step의 outputs 중 apk-filename을 가져와 Job outputs의 apk-name에 넣기
apk-name: ${{ steps.write-step.outputs.apk-filename }}
steps:
- name: Write outputs to step
id: write-step
run: echo 'apk-filename=test' >> $GITHUB_OUTPUT
생성한 output 불러오기
Job 수준의 outputs에 생성한 Key-Value 쌍을 을 출력하기 위해서는 Context 정보 중 needs 정보를 사용하면 된다. needs 객체는 현재 Job에 의존성이 있는 모든 Job의 outputs를 포함하기 때문에 위 build Job에 Dependent한 Job을 만들면 Job 수준의 outputs에 접근이 가능하다.
Context Name | Type | Description |
needs | object | Contains the outputs of all jobs that are defined as a dependency of the current job. For more information, see needs context. 현재 job에 dependent하다고 정의된 모든 job의 output을 포함한다. 더 많은 정보를 위해서는 needs context 문서를 참고하라. |
needs.[의존성 있는 Job 명칭].outputs.[Key] 로 접근이 가능하며, build Job의 apk-name 파라미터를 가져와야 하므로 needs.build.outputs.apk-name 을 참조하면 위에서 설정한 test가 넘어온다.
print-output:
needs: build # needs를 설정하면 build Job 다음에 순차적으로 수행되는데, 이때 정보도 같이 넘어옴
runs-on: ubuntu-latest
steps:
- name: Print Output
run: echo "${{ needs.build.outputs.apk-name }}"
여기까지 작성한 후 GitHub Action에 올려보도록 하자.
아래와 같이 출력이 예상한대로 "test"로 나오는 것을 확인할 수 있다.
전체 코드
전체 코드는 다음과 같다.
name: Value Share Between Jobs - Simple
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
outputs:
# Step 중 apk-publish 라는 id를 가지고 있는 step의 outputs 중 apk-filename을 가져와 Job outputs의 apk-name에 넣기
apk-name: ${{ steps.write-step.outputs.apk-filename }}
steps:
- name: Write outputs to step
id: write-step
run: echo 'apk-filename=test' >> $GITHUB_OUTPUT
print-output:
needs: build # needs를 설정하면 build Job 다음에 순차적으로 수행되는데, 이때 정보도 같이 넘어옴
runs-on: ubuntu-latest
steps:
- name: Print Output
run: echo "${{ needs.build.outputs.apk-name }}"
정리
이 글에서는 단순한 값을 outputs 객체를 통해 전달하는 방법에 대해 살펴보았다. 만약 특정한 Job에서 생성된 값이 모든 Job에 공유되어야 한다면 위와 같이 사용하는 것을 권장한다.