Github Actions를 만들 때 사용했던 개념들을 모아보았습니다. (진행중)
Workflow, Job, Step
Github Actions를 구성하는 요소는 크게 Workflow, Job, Step이 있습니다. 이 요소들 간의 관계를 다이어그램을 그려보면 아래와 같습니다. 빨간색 화살표는 실행 흐름을 의미합니다.
Workflow
•
Workflow는 하나의 Github Action의 전체 실행 흐름을 의미합니다. (가장 상위 요소)
•
Yaml 파일로 정의되고 .github/workflow 디렉토리 안에 위치해야 합니다.
•
on 키워드를 이용해서 issue 생성이나 PR 오픈 등의 이벤트가 발생했을 때 Workflow가 실행되도록 설정할 수 있습니다.
•
Workflow 안에는 여러 개의 Job이 포함됩니다.
Workflow 구조 예시
name: Example Workflow
on: "pull_request" # PR 이벤트가 발생하는 경우 workflow를 실행
jobs:
# Workflow에서 실행할 Job 정의
YAML
복사
Job
•
Job은 Workflow 내의 실행 단위입니다.
•
Workflow 내의 각 Job들은 기본적으로 병렬실행되지만, needs 키워드를 이용해서 순차 실행이 가능하도록 할 수도 있습니다.
•
각 Job들은 독립적인 실행 환경(Runner)을 가지기 때문에 파일 등을 공유하기 위해서는 Artifact 같은 도구가 추가로 필요합니다. 예를 들면 하나의 Job에서 node 실행 환경 설정을 하고 그 환경을 여러 Job에서 공유하는 아래의 구조가 기본적으로는 불가능합니다.
# 생략...
jobs:
setup-node:
runs-on: ubuntu-latest
steps:
- name: setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: install dependency
run: npm install
test:
runs-on: ubuntu-latest
needs: setup-node # node 설정 Job이 완료된 뒤에 작업 실행
steps:
- name: run test
run: npm run test # 🚨 node 실행 환경을 찾을 수 없습니다.
# 또 다른 작업들...
YAML
복사
Job 구조 예시
# 생략...
jobs:
# job1과 job2는 병렬 실행
job1:
runs-on: ubuntu-latest
steps:
# job1의 step들
job2:
runs-on: ubuntu-latest
steps:
# job2의 step들
YAML
복사
Step
•
Step은 Job 내에서 실행되는 작업 단위입니다.
•
위에서부터 차례대로 순차 실행됩니다. (not 병렬)
•
같은 Job의 Step은 같은 실행환경(Runner)에서 실행되기 때문에 이전 Step에서 만들어진 결과를 그대로 사용할 수 있습니다.
Step 구조 예시
jobs:
setup-node:
runs-on: ubuntu-latest
steps:
- name: setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: install dependency
run: npm install # actions/setup-node@v4의 결과를 사용할 수 있다.
YAML
복사
Token
GITHUB_TOKEN
워크플로우 생성 시 자동으로 생성되는 토큰입니다. secrets.GITHUB_TOKEN으로 접근할 수 있고 (당연하게도) 자동으로 생성되기 때문에 따로 Github Actions secret에 등록할 필요는 없습니다.
GITHUB_TOKEN의 기본 권한은 settings > actions > Workflow permissions 에서 설정할 수 있는데요.
특별히 어떤 워크플로우에는 권한을 추가한다거나 하는 식으로 워크플로우별로 권한 설정이 필요하다면 yaml 파일에서 permission 키워드로 설정할 수 있습니다. 이렇게 설정한 권한은 기본 권한에 덮어씌워집니다.
name: Automate PR Reviews
on:
pull_request:
types: [opened, ready_for_review]
jobs:
# PR에 라벨을 추가하고 이슈를 이동하는 작업
automate-pr-review:
runs-on: ubuntu-latest
permissions:
pull-requests: write # PR에 라벨을 추가하기 위한 권한
issues: read # 이슈 라벨을 읽어오기 위한 권한
# 생략...
YAML
복사
GITHUB_TOKEN을 사용하는 유저는 기본적으로 github_actions[bot] 이라는 가상의 유저로 설정됩니다. (가상의 유저이기 때문에 계정을 누르면 actions 페이지로 이동해요.)
개인적인 의견으로는, 특별히 아래에서 설명할 PAT를 사용할 이유가 없거나 따로 봇 계정이 있는 것이 아니라면 액션으로 작업된 결과임을 명확히 하기 위해서 GITHUB_TOKEN을 사용하는 것이 (편하기도 하고..) 좋다고 생각합니다.
PAT (Personal Access Token)
GITHUB_TOKEN의 권한만으로 대부분의 Github와 관련된 Action의 권한을 처리할 수 있었는데요. 가끔 해당하는 레포지토리가 아닌 다른 레포지토리에 작업해야 하는 등의 좀 더 확장된 권한이 필요한 경우가 생깁니다. 이럴 때에는 GITHUB_TOKEN의 권한으로는 작업이 불가능하기 때문에 Personal Access Token을 생성해서 사용해야 합니다.
예전에 어떤 레포지토리의 내용을 다른 레포지토리와 동기화하는 워크플로우를 작성할 때 PAT를 사용했던 경험이 있어서 이 상황을 예시로 들어볼게요. (너무 예전 코드라 코드 전문은 링크하지 않겠습니다… 🥹) 다른 조직의 레포지토리에 push해야 하는 상황이었기 때문에 GITHUB_TOKEN을 사용할 수 없어서 PAT를 생성해서 직접 secret에 정의해 주었습니다.
# 생략...
jobs:
sync:
runs-on: ubuntu-latest
steps:
# 생략...
- name: Pushes to another repository
uses: cpina/github-action-push-to-another-repository@main
env:
API_TOKEN_GITHUB: ${{ secrets.TEST_DEPLOY_REPO_OWNER_TOKEN }}
# 생략...
YAML
복사
저는 marketplace의 action을 이용했기 때문에 따로 유저 정보를 정의해주지 않았는데요. 기본적으로 Github Actions 환경에는 Git 사용자 설정이 되어 있지 않기 때문에 user.email과 user.name도 함께 설정해줘야 합니다.
git config --global user.email "blahblah@example.com"
git config --global user.name "blahblah"
Bash
복사
Context
워크플로우 실행이나 변수, job, step과 관련된 정보를 얻을 수 있는 객체들을 context라고 합니다. context의 데이터는 ${{ <context>.<key> }}로 접근할 수 있습니다.
각 context들의 종류와 프로퍼티들은 위 링크에 잘 정리되어 있는데요. 개인적으로 자주 사용한 context들을 정리하면 아래와 같습니다.
github context
워크플로우 실행과 실행을 트리거한 이벤트에 대한 정보를 담고 있습니다.
프로퍼티 키 | 타입 | 설명 | 예시 |
github.actor | string | 워크플로우를 처음 실행한 유저의 이름 (re-run 기능이 있기 때문에 처음 실행한 유저를 구분합니다.) | “yoouyeon” |
github.event_name | string | 워크플로우 실행을 트리거한 이벤트의 이름 | “pull_request”
”push” |
github.ref_name | string | 워크플로우 실행이 트리거된 branch나 tag의 ref 이름의 짧은 버전 (refs/heads 나 refs/tags 같은 것들을 제외한 이름입니다.) | “main”
”develop”
“feature/login”
”123/merge” |
github.head_ref | string | PR의 경우 github.ref_name은 <issue_number>/merge 형식의 병합 브랜치입니다. 현재 PR의 브랜치 정보는 github.head_ref 에 있습니다. | ”develop”
“feature/login” |
github.repository | string | 레포지토리 소유자와 레포지토리 이름 | “yoouyeon/hello-world” |
env context
workflow, job, step에 설정된 variable에 접근할 수 있습니다.
프로퍼티 키 | 타입 | 설명 |
env.<env_name> | string | 설정한 변수의 값 |
steps context
현재 job의 step에 대한 정보를 담고 있습니다.
프로퍼티 키 | 타입 | 설명 |
steps.<step_id>.outputs.<output_name> | string | step_id에 해당하는 step의 output 중 output_id에 해당하는 output |
secrets context
workflow에서 사용할 수 있는 secret에 대한 정보를 담고 있습니다.
프로퍼티 키 | 타입 | 설명 |
secrets.GITHUB_TOKEN | string | 매 워크플로우 실행마다 자동으로 생성되는 워크플로우용 토큰 |
secrets.<secret_name> | string | secret_name에 해당하는 secret의 값 |
needs context
현재 job이 의존하고 있는 다른 job의 output에 접근할 수 있는 context입니다.
프로퍼티 키 | 타입 | 설명 |
needs.<job_id>.result | string | 현재 job이 의존하고 있는 특정한 job의 결과
- success
- failure
- cancelled
- skipped |
needs.<job_id>.outputs.<output name> | string | 현재 job이 의존하고 있는 특정한 job의 output 중 특정한 값 |
context 예제 일부…
Reusable Workflow / Composite Action
중복해서 사용해야 하는 작업이 있다면 Reusable Workflow와 Composite Action을 이용해서 중복을 줄일 수 있습니다. 중복된 작업을 하나로 정의해서 재사용할 수 있게 한다는 목적은 같지만 차이점도 있는데요. 몇가지만 간단히 정리하면 아래와 같습니다.
Reusable Workflow | Composite Action |
재사용할 여러 개의 Job을 포함 | 재사용할 여러 개의 Step을 포함 (job은 포함하지 않음) |
Job에서 바로 호출 | Job을 구성하는 Step 중 하나로 호출 |
.github/workflow 디렉토리 안에 하나의 단독 파일로 구성 | action.yml 파일을 포함해서 여러 파일로 구성될 수 있고 디렉토리 위치는 자유로움 |
yml 파일을 직접 참조해서 호출 | action이 정의된 레포지토리나 디렉토리 이름을 참조해서 호출 |
Reusable Workflow
•
다른 workflow 파일과 거의 비슷한 포맷으로 정의할 수 있습니다.
•
Reusable Workflow에는 on 키워드의 값에 workflow_call이 반드시 있어야 한다는 차이점이 있습니다.
•
workflow_call의 값을 통해서 input과 secret을 전달받을 수 있습니다.
name: Reusable workflow example
on:
workflow_call:
inputs:
config-path:
required: true
type: string
secrets:
token:
required: true
jobs:
# 생략...
YAML
복사
•
이렇게 정의한 workflow는 같은 repository 뿐 아니라 다른 repository에서도 호출해서 사용할 수 있습니다.
◦
같은 repository에서 : ./.github/workflows/{filename}
◦
다른 repository에서 : {owner}/{repo}/.github/workflows/{filename}@{ref}
Composite Action
•
Composite Action은 action metadata 파일인 action.yml 파일에 정의합니다.
•
runs 키워드의 값으로 실행할 step들을 정의할 수 있습니다.
•
정의한 action은 action.yml이 위치한 디렉토리의 이름으로 호출할 수 있습니다.
Cache
추가 예정…
Artifact
추가 예정…