[GitHub Actions] 삼가 수동배포의 명복을 GitHub Actions빔 - 3. GitHub Actions를 구동하는 방법. Events(이벤트)
⏰ 2023-10-29 (일) 02:58:29
Events
CI/CD 파이프라인을 사용하기 위해선, 구동할 적절한 시점이 제공되어야한다.
코드 변경이 항상 있을 때 동작해서는 안 된다. 개발 중이거나, 검증이 완료되지 않은 코드가 파이프라인을 탈 수 있기 때문이다.
따라서 환경에 따라 적절한 구동 시점을 정할 필요가 있는데, 이 때 활용하는 것이 GitHub Actions의 Events다.
Events에선 다양한 스크립트 동작 이벤트를 지정할 수 있다. 브랜치, 태그, 파일의 변경이 감지될 경우, 특정 시간이 될 경우 등. 구성에 따라 다양한 이벤트를 적용할 수 있다.
이 장에선 각 이벤트의 내용과 사용 방법, 예시에 대해 다뤄본다.
동작 트리거링
자주 사용하는 GitHub Actions의 이벤트를 알아보자. 원하는 때, 원하는 곳의 변경이 감지될 경우, 스크립트를 구동할 수 있다.
트리거링은 on
을 사용하며, 해당 키워드의 하위로 원하는 이벤트를 기술한다.
트리거 종류는 GitHub Docs의 🔗 Events that trigger workflows에서 확인할 수 있다.
단일 이벤트 트리거링
간단한 단일 동작에 대한 이벤트 트리거링 방법은 아래와 같다.
YAML
1 2 3 4 5
# push할 경우 동작 시 이벤트 수행 on: push ## PR 동작 시 이벤트 수행 on: pull_request
위와 같이 대상 이벤트를 지정한다. 이를 통해 브랜치에 커밋이 푸시되거나, PR이 올라올 경우 등, 원하는 시점에 GitHub Actions를 구동할 수 있다.
다중 이벤트 트리거링
간단한 다중 동작에 대한 이벤트 트리거링 방법은 아래와 같다.
YAML
1 2
# push, PR 동작 시 이벤트 수행 on: [ push, pull_request ]
배열의 형태로 원하는 이벤트를 지정한다.
활동 타입 트리거링
일부 이벤트의 경우, activity types
옵션을 제공한다. 이벤트가 가질 수 있는 동작을 세분화하여, 특정 이벤트 중에서도 특정 활동에서만 GitHub Actions를 동작하고자 할 때 활용할 수 있다.
YAML
1 2 3 4 5 6 7
# PR 생성, 수정, 닫기가 수행될 경우 이벤트 수행 on: pull_request: types: - opened - edited - closed
예를 들자면, PR 이벤트인 pull_request
의 경우 opened (PR 생성)
, edited (PR 수정)
, closed (PR 닫기)
등, 다양한 활동을 가질 수 있다.
이 중 PR 생성 등, 특정 활동에서만 GitHub Actions을 트리거링 할 수 있다. 만약, 이전의 예시처럼 pull_request
에 별다른 활동을 지정하지 않을 경우, 모든 활동에 동작한다.
pull_request
의 모든 activity types
은 🔗 GitHub Docs - Pull Request를 확인하자.
이벤트 필터
이벤트에 필터를 적용하여 이벤트의 동작을 필터링할 수 있다. 필터의 종류엔 브랜치명, 태그명, 파일 등 다양한 항목을 적용할 수 있다.
필터는 다중 적용이 가능하며, glob 패턴을 사용할 수 있다. 이를테면 release/**
은 release/
로 시작하는 모든 브랜치명과 같은 형식이다.
브랜치 필터
특정 브랜치에 필터링을 걸어 원하는 브랜치에서만 이벤트를 실행할 수 있다.
브랜치 포함 필터
아래의 스크립트는 지정한 특정 브랜치만을 트리거 대상에 포함한다.
YAML
1 2 3 4 5 6 7
# 대상 브랜치에 push할 경우 이벤트 수행 on: push: branches: - main - features/231024 - 'release/**'
이벤트 대상에 해당하는 브랜치는 아래와 같다.
main
브랜치features/231024
브랜치release/
로 시작하는 모든 브랜치release/development
release/test
release/development/231024
브랜치 제외 필터
아래의 스크립트는 지정한 특정 브랜치만을 트리거 대상에서 제외한다.
YAML
1 2 3 4 5 6 7 8 9 10 11 12 13
# 대상 브랜치가 아닌 브랜치에 push할 경우 이벤트 수행 on: push: branches-ignore: - test - 'feature/**-temp' # glob pattern의 부정연산자인 !를 활용하여 표현할 수도 있다. on: push: branches: - '!test' - '!feature/**-temp
이벤트 대상에서 제외되는 브랜치는 아래와 같다.
test
브랜치feature/
로 시작하고-temp
로 끝나는 모든 브랜치feature/alpha-test-temp
feature/textarea-temp
feature/java/code-temp
브랜치 혼합 필터
아래와 같이 브랜치 포함/제외 필터를 혼합하여 사용할 수 있다.
YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# 아래 조건에 맞는 브랜치일 경우 on: push: branches: - 'release/**' - '!release/**-test' # 위의 필터는 아래와 동일하다. on: push: branches: - 'release/**' branches-ignore: - 'release/**-test'
이벤트 대상에 해당하는 브랜치는 아래와 같다.
release/
로 시작하며,-test
로 끝나지 않는 모든 브랜치
위의 두 스크립트와 같이, glob pattern의 !
를 활용하여 한 번에 표기하거나, branches
, branches-ignore
를 혼합하여 사용하는 것 모두 활용 가능하다. 둘 중 더 편한걸로 취사선택하여 사용하면 된다.
태그 필터
GitHub에선 태그를 생성하여 형상관리가 가능하다. 브랜치 뿐만 아니라, 태그에 필터를 적용하여 이벤트를 실행할 수도 있다.
태그 필터는 tags
, tags-ignore
를 활용하며, 브랜치 필터와 매우 유사하다.
태그 포함 필터
아래의 스크립트는 지정한 특정 태그만 트리거 대상에 포함한다.
YAML
1 2 3 4 5 6
# 대상 태그에 push할 경우 이벤트 수행 on: push: tags: - v1.0.2 - 'v2*'
이벤트 대상에 해당하는 태그는 아래와 같다.
v1.0.2
태그v2
로 시작하는 태그v2.1.0
v2.3.1-alpha
태그 제외 필터
아래의 스크립트는 지정한 특정 태그만을 트리거 대상에서 제외한다.
YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 대상 태그가 아닌 태그에 push할 경우 이벤트 수행 on: push: tags-ignore: - v1.0.0 - 'v0*' - 'v**-alpha' # glob pattern의 부정연산자인 !를 활용하여 표현할 수도 있다. on: push: tags: - '!v1.0.0' - '!v0*' - '!v**-alpha'
이벤트 대상에서 제외되는 브랜치는 아래와 같다.
v1.0.0
태그v0
으로 시작하는 모든 태그v2.1.0
v2.3.1-alpha
v
로 시작하고-alpha
로 끝나는 모든 태그v3.0.1-alpha
v1.0.5-a460b53c-alpha
태그 혼합 필터
아래의 스크립트는 지정한 특정 태그만을 트리거 대상에서 제외한다.
YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# 아래 조건에 맞는 태그일 경우 on: push: tags: - 'v*' - '!v**-test' # 위의 필터는 아래와 동일하다. on: push: tags: - 'v*' tags-ignore: - 'v**-test'
이벤트 대상에 해당하는 태그는 아래와 같다.
v
로 시작하는 모든 태그v
로 시작하면서,-test
로 끝나지 않는 모든 태그
경로 필터
Git의 브랜치나 태그 뿐만 아니라, 소스코드의 경로의 파일 추가, 삭제. 특정 파일의 변경을 감지하고 이벤트를 수행할 수 있다.
브랜치나 태그 필터와 유사하게 paths
, paths-ignore
키워드를 사용한다.
경로 포함 필터
아래의 스크립트는 지정한 특정 경로만 트리거 대상에 포함한다.
YAML
1 2 3 4 5 6 7
# 대상 경로에 push할 경우 on: push: paths: - version.json - '**.tsx' - 'build/docs/**'
이벤트 대상에 해당하는 경로는 아래와 같다.
version.json
파일- 모든
tsx
파일src/apps/App.tsx
src/components/Header.tsx
template.tsx
build/docs
폴더 하위의 모든 폴더/파일build/docs/index.html
build/docs/images/favicon.ico
build/docs/css/index.css
경로 제외 필터
아래의 스크립트는 지정한 특정 경로만을 트리거 대상에서 제외한다.
YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 대상 경로가 아닌 경로에 push할 경우 이벤트 수행 on: push: paths-ignore: - hash.txt - 'test/**' - '**.md' # glob pattern의 부정연산자인 !를 활용하여 표현할 수도 있다. on: push: paths: - '!hash.txt' - '!test/**' - '!**.md'
이벤트 대상에서 제외되는 경로는 아래와 같다.
hash.txt
파일test
폴더 아래의 모든 폴더/파일test/index.json
test/api-test.java
test/assets/thumb.png
- 모든
md
파일README.md
src/code/index.md
경로 혼합 필터
아래의 스크립트는 지정한 특정 경로만을 트리거 대상에서 제외한다.
YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# 아래 조건에 맞는 경로일 경우 on: push: paths: - 'src/**' - '!src/generated/**' # 위의 필터는 아래와 동일하다. on: push: paths: - 'src/**' paths-ignore: - 'src/generated/**'
이벤트 대상에 해당하는 태그는 아래와 같다.
src
폴더 하위 중src/generated
하위에 있지 않은 모든 폴더/파일
일정 필터 (crontab)
위에서 언급한 필터들은 모두 특정 요소에 특정 동작이 발생할 경우에만 이벤트가 발생한다. 사용자가 레포지토리에 무언가를 할 때만 동작하는 수동적인 구조다.
다행히, GitHub Actions에선 crontab을 활용하여 레포지토리의 변경이 없어도 지정한 일정마다 이벤트를 실행할 수 있다.
YAML
1 2 3 4
on: schedule: # 매주 월요일 ~ 금요일 0시 0분에 이벤트 실행 - cron: '0 0 * * 1-5'
cron
키워드를 사용한다. 위 일정은 월요일(1) 부터 금요일(5)까지 매 0시 0분마다 이벤트를 수행한다.
crontab 활용방법
크론탭의 간략할 설정 방법은 아래와 같다.
TXT
1 2
* * * * * 분(0-59) 시간(0-23) 일(1-31) 월(1-12) 요일(0-7)
다른건 직관적이나, 요일이 조금 모호한데, 아래와 같다.
요일 | 숫자 |
---|---|
일요일 | 0 |
월요일 | 1 |
화요일 | 2 |
수요일 | 3 |
목요일 | 4 |
금요일 | 5 |
토요일 | 6 |
일요일 | 7 |
또한 쉼표(,
)와 대쉬(-
), 슬래시(/
)를 사용할 수 있으며, 예시를 들자면 아래와 같다.
BASH
1 2 3 4 5 6 7 8 9 10 11
# 매일 0시, 6시, 12시 18시 0분에 이벤트 수행 0 0,6,12,18 * * * # 월요일 ~ 금요일 매시 0분에 이벤트 수행 0 * * * 1-5 # 매일 3시간마다 이벤트 수행 0 */3 * * * # 3월 6월 9월 12월일 경우, 매주 월요일 ~ 금요일 매 3시간마다 이벤트 수행 0 */3 * 3,6,9,12 1-5
각 내용과 연산자를 조합하여 복잡한 일정을 지정할 수도 있다.
위 내용을 토대로 크론탭을 작성하면 된다. 본 문서는 크론탭에 대한 주제가 아니므로, 이 정도로 마무리한다.
workflow_dispatch를 통한 수동 이벤트 수행
지금까지 여러 이벤트 필터에 대해 살펴봤다. 하나같이 특정 요소에 무언가 작업을 해야하거나, 특정 시간까지 기다려야만 한다. 즉, 당신이 원할 때 이벤트를 실행하고 싶다면 무의미한 커밋이라도 하나 올려야한다는 셈이다.
만약 Git History에 민감한 환경이나 사람이라면 상당이 난감한 셈.
다행히도, GitHub Actions에선 workflow_dispatch
라는 키워드를 통해, 사용자가 직접 원할 때 수동으로 실행할 수 있도록 구성이 가능하다. 심지어, input
이나 select
를 지정하여 원하는 값을 직접 입력할 수도 있다!
기본 형태
가장 간단한 형태는 아래와 같다.
YAML
1 2
on: workflow_dispatch:
레포지토리의 Actions 탭에서 Run workflow
버튼을 통해 구동이 가능하다.
- 레포지토리의 Actions 탭에 들어간다.
- 좌측 사이드바에서 대상 스크립트를 클릭한다.
Run workflow
를 클릭하고, 구동하기 원하는 브랜치를 선택 후 구동한다.input
,select
설정을 하면 해당 탭에 추가된다.
심화 형태
앞서 언급했듯이, 원하는 값을 입력받아 스크립트에서 활용할 수 있다. 이 항목들은 required
설정도 가능하여, 구동 시 필수값을 입력받도록 구성할 수도 있다.
inputs
키워드를 활용하며, 각 컴포넌트의 변수명을 지정한뒤, 옵션을 설정하면 된다. 스크립트에서 활용 시, 해당 변수명을 통해 호출이 가능하다.
choice 타입
select
형태의 입력을 받을 수 있다. 지정된 값 중 하나를 선택할 수 있다.
YAML
1 2 3 4 5 6 7 8 9 10 11
workflow_dispatch: inputs: choice_component: description: '지정값 선택' required: true default: 'level1' type: choice options: - level1 - level2 - level3
위 컴포넌트의 이름은 choice_component
다.
태그 | 내용 |
---|---|
description | 컴포넌트 타이틀 |
required | 필수 여부 |
default | 기본값 |
type | 컴포넌트 타입 |
options | 배열 형태의 선택 옵션 |
boolean 타입
checkbox
형태의 입력을 받을 수 있다. 값을 선택하여 true
혹은 false
형태의 값을 입력할 수 있다.
YAML
1 2 3 4 5 6 7
workflow_dispatch: inputs: check_component: description: 'True or False' required: true default: true type: boolean
위 컴포넌트의 이름은 check_component
다.
태그 | 내용 |
---|---|
description | 컴포넌트 타이틀 |
required | 필수 여부 |
default | 기본값 |
type | 컴포넌트 타입 |
string, number 타입
input
형태의 입력을 받을 수 있다. string
과 number
모두 임의의 값을 직접 입력하는 형태다.
의도된 사항인지 모르겠으나, number
타입을 지정해도 문자열 입력이 가능하며, 스크립트에서도 정상적으로 문자열이 표현된다. 별다른 차이가 없다고 봐도 무방.
이 문서에선 string
을 예시로 든다, number
타입도 동일하게 사용 가능하다.
YAML
1 2 3 4 5 6 7
workflow_dispatch: inputs: text_component: description: '여기에 값 입력' required: true default: '' type: string
위 컴포넌트의 이름은 text_component
다.
태그 | 내용 |
---|---|
description | 컴포넌트 타이틀 |
required | 필수 여부 |
default | 기본값 |
type | 컴포넌트 타입 |
컴포넌트 변수 호출
아직 다루지 않았지만, 실제 워크플로에서 입력한 값을 아래와 같이 호출하여 사용할 수 있다.
YAML
1 2 3 4 5
- name: Run a multi-line script run: | echo ${{ inputs.choice_component }} echo ${{ inputs.check_component }} echo ${{ inputs.text_component }}
BASH
1 2 3
level1 true text
스크립트 상에서 ${{ inputs.변수명 }}
으로 호출 가능하다.
마치며
원래 스크립트 전체를 아우르는 사용법에 대해 다루려 했으나, 생각보다 이벤트 및 필터의 분량이 많아진 탓에 이 부분만 설명하고 넘어가기로 했다.
분량이 점점 많아지면서, 어찌나 귀찮던지...
대부분의 내용은 GitHub 공식문서의 내용을 토대로 작성한 것으로, 자세한 내용은 아래의 두 링크를 참조하자.
쓰다보니 순서가 안 맞는 거 같아서, 해당 글을 3장으로 옮기고, GitHub Actions의 구조 설명을 2장으로 뺐다.
🏷️ 태그
읽어주셔서 고마워요!
도움이 되셨다면, 공감이나 댓글을 달아주시는 건 어떤가요?
블로그 운영에 큰 힘이 됩니다.