Github Action이란?
※ 이 글은 안드로이드 개발자 관점에서 작성됨
어떤 서비스를 하나 만들었다. 이제 배포를 해야 하는데, 안드로이드의 경우 예전엔 apk, 지금은 aab 파일을 만들어서 플레이 스토어에 올려야 한다. 그 전에 소스코드 변경이 있으면 테스트 돌리고, 린트 검사 등등 자질구레한 작업이 몇 개 생길 수 있다. 그리고 aab 파일을 만들어서 스토어에 올려 심사 걸고, 심사 통과하면 게시 버튼을 눌러 스토어에 배포하는 등 배포 한 번 할 때마다 귀찮은 일들을 쳐내야 한다. 그래서인지 깃허브 레포지토리에서 할 수 있는 작업들을 자동화할 수 있도록 만들어진 것이 Github Action이다. 공식문서에서 설명하는 Github Action은 아래와 같다.
https://docs.github.com/ko/actions/learn-github-actions/understanding-github-actions
Github Action은 빌드, 테스트, 배포 파이프라인을 자동화할 수 있는 지속적 통합 / 배포(CI/CD) 플랫폼이다. 레포지토리에 대한 모든 Pull Request를 빌드, 테스트하는 workflow를 생성하거나 merge된 Pull Request를 프로덕션에 배포할 수 있다. Github Action은 DevOps를 넘어 레포지토리에서 다른 이벤트가 발생할 때 workflow를 실행할 수 있다. 누가 저장소에 새 이슈를 만들 때마다 적절한 레이블을 자동 추가하는 workflow를 실행할 수 있다. 리눅스, 윈도우, MacOS 가상 머신을 제공해서 workflow를 실행하거나 자체 데이터 센터 또는 클라우드 인프라에서 자체 호스팅 러너를 호스팅할 수 있다
한마디로 깃허브가 만든 무료 CI/CD 플랫폼이다. Pull Request(이하 PR)가 생성되거나 레포지토리에 코드 push가 발생했을 때 등 어떤 이벤트가 발생할 경우 사전에 정의한 작업들을 실행시키는 것이다.
Github Action의 구성요소는 아래와 같다.
- Workflow
- Event
- Job
- Action
- Runner
이제 각각이 뭔지 공식문서와 다른 글들을 찾아보면서 확인해 본다.
Workflow
workflow는 하나 이상의 작업을 실행하는 구성 가능한 자동화 프로세스다. 레포지토리에 체크인한 YAML 파일에 의해 정의되며 레포지토리의 이벤트에 의해 트리거될 때 실행되거나 수동으로 or 정의된 일정에 따라 트리거될 수 있다. workflow는 레포지토리의 .github/workflows 디렉토리에 정의되며 레포지토리에는 각각 다른 작업 집합을 수행할 수 있는 여러 workflow가 있을 수 있다. PR을 작성하고 테스트하는 하나의 workflow, 릴리스가 생성될 때마다 앱을 배포하는 다른 workflow 등을 가질 수 있다
https://dev.to/github/whats-the-difference-between-a-github-action-and-a-workflow-2gba
workflow는 어떤 것(이벤트 등)이 발생한 후에 일어나는 것 또는 모든 것이다. 이벤트가 발생한 후 workflow를 트리거할 수 있다. workflow를 수동 실행하거나 특정 시간에 실행되게 설정할 수도 있다. workflow는 yml 파일로 생성된다. 수동 실행되는 workflow와 시간 초과 workflow는 모두 event(Github Action의 구성요소)로 분류된다. 다음에 일어나는 일은 사용자가 정의한 일련의 단계다. workflow는 릴리스를 게시할 때 트윗을 보내거나 앱을 배포하거나, 이슈가 열리면 label을 추가하는 등 무엇이든 될 수 있다
깃허브 레포지토리에 어떤 이벤트가 발생할 경우, 그 후에 자동으로 실행될 작업들을 YAML 파일(yml 확장자)에 정의하면 그 YAML 파일이 workflow다. Github Action을 사용하기 위해 반드시 필요한 파일이다. 이 파일은 .github/workflows라는 폴더 안에 있어야 하며 YAML 파일은 여러 개 있을 수 있다. 일단 이렇게 이해하고 넘어가자.
Event
Event는 workflow 실행을 트리거하는 레포지토리의 특정 활동이다. 누가 PR을 만들거나 이슈를 열거나 커밋을 푸시할 때 활동(activity)이 깃허브에서 시작될 수 있다. REST API에 게시하거나 수동으로 일정에 따라 실행되게 workflow를 트리거할 수도 있다
PR / 이슈 생성, 푸시 등 레포지토리에서 뭔가 발생했을 때 "뭔가"를 이벤트라고 한다. 어떤 이벤트들이 있는지는 공식문서를 참고하면 된다.
Job
Job은 같은 runner에서 실행되는 workflow의 일련의 단계(a set of steps)다. 각 단계는 실행될 쉘 스크립트거나 실행될 조치(order)다. 단계는 순서대로 실행되며 서로 의존적이다. 각 단계는 같은 runner에서 실행되므로 한 단계에서 다른 단계로 데이터를 공유할 수 있다. 앱을 빌드하는 단계 뒤에 빌드된 앱을 테스트하는 단계가 있을 수 있다. 기본적으로 Job에는 종속성이 없으며 병렬로 실행된다. 종속성이 없는 서로 다른 아키텍처에 대한 여러 빌드 작업과 이런 작업에 종속된 패키징 작업이 있을 수 있다. build job은 병렬 실행되며 모두 성공하면 패키징 작업이 실행된다
https://dev.to/github/whats-the-difference-between-a-github-action-and-a-workflow-2gba
Job은 실행되는 workflow 안의 일련의 단계다. 각 단계는 실행할 스크립트거나 작업이다. 단계는 작성한 순서대로 실행되며 완료되는 이전 단계에 따라 달라진다. Job은 병렬 실행 가능하지만 step은 개별 실행해야 한다
https://www.daleseo.com/github-actions-basics/
Job이란 독립된 가상 머신 또는 컨테이너에서 돌아가는 하나의 처리 단위를 의미한다. 하나의 workflow는 여러 작업으로 구성되며 적어도 하나의 작업은 있어야 한다. 모든 작업은 기본적으로 동시 실행되며 필요 시 작업 간에 의존 관계를 설정해서 작업이 실행되는 순서를 제어할 수도 있다
Job은 YAML 파일 안에서 수행해야 하는 여러 작업들을 묶어놓은 것이라고 볼 수 있겠다. 어찌 보면 함수처럼 어떤 작업들을 할지 정해둔 Job을 만든 다음, 이 Job들을 적절한 순서대로 이어붙이면 하나의 workflow가 완성되는 것이다. workflow가 Github Action의 구성요소 중 가장 상위 개념인데, 이 상위 개념을 구성하는 요소기 때문에 Job을 어떻게 설정하느냐가 중요하겠다.
Action
Action은 복잡하지만 자주 반복되는 작업을 수행하는 Github Action 플랫폼용 커스텀 애플리케이션이다. Action을 써서 workflow 파일에 작성하는 반복되는 코드량을 줄이는 데 도움이 된다. Action은 레포지토리를 가져오거나 빌드 환경에 대한 도구 체인을 설정하거나 클라우드 공급자에 대한 인증을 설정할 수 있다. 고유 작업을 작성하거나 Github Marketplace의 workflow에서 사용할 Action을 찾을 수 있다
https://dev.to/github/whats-the-difference-between-a-github-action-and-a-workflow-2gba
Action은 workflow 안에서 발생하는 일(things) 중 하나다. Action은 반복이 필요한 복잡한 작업을 수행하는 데 사용된다. 따라서 Action을 쓰면 workflow를 작성하는 데 필요한 시간, 반복 코드를 줄일 수 있다
요약하면 Action은 반복되는 작업을 안 하게 해주는 애플리케이션이다. 설명만 보면 뭐라는 거야 싶은데 밑에서 Github Action 공식문서의 예제를 보면서 확인한다.
Runner
Runner는 트리거될 때 workflow를 실행하는 서버다. 각 Runner는 한 번에 하나의 작업을 실행할 수 있다. 깃허브는 우분투 리눅스, 윈도우, MacOS Runner를 제공해서 workflow를 실행한다. 각 workflow 실행은 새로 프로비저닝된 새 가상 머신에서 실행된다...(중략)...다른 OS가 필요하거나 특정 하드웨어 구성이 필요하면 자체 Runner를 호스팅할 수 있다
https://dev.to/github/whats-the-difference-between-a-github-action-and-a-workflow-2gba
Runner는 workflow가 트리거되면 workflow를 실행하는 서버 프로세스다. 각 Runner는 한 번에 하나의 Job만 실행할 수 있고 해당 Job은 위에서 언급한 단계 모음이다
Runner는 workflow가 동작하기 위한 서버다. 생각해 보면 당연히 서버가 필요하다. 서버 없이 어떻게 깃허브 레포지토리의 소스코드들을 가져오는 Action을 실행하고, 필요하다면 슬랙 웹훅을 연동해서 apk 파일도 다운로드해야 하는데, 이런 작업을 하려면 서버는 무조건 필요하다.
다행히도 서버 호스팅을 내가 하지 않아도 깃허브가 알아서 해 준다. 우분투 리눅스, 윈도우, MacOS 3가지는 기본 지원이니 이 중에 원하는 것을 사용하면 되겠다.
각 요소들을 간단하게 확인했으니 이제 Github Action 공식 홈페이지에 있는 예제 코드를 확인해 본다.
name: learn-github-actions
run-name: ${{ github.actor }} is learning GitHub Actions
on: [push]
jobs:
check-bats-version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '14'
- run: npm install -g bats
- run: bats -v
이것이 workflow라고 부르는 YAML 파일에 들어갈 코드다. 중요한 것은 YAML 고유의 들여쓰기 린트가 있는데, 이것을 매우 잘 지켜서 작성해야 한다. 컴파일 에러도 발생하지 않고, 잘못된 들여쓰기로 작성해서 커밋했다간 곧바로 Github Action이 실패하면서 에러를 뿜어낸다.
코드를 하나씩 확인한다.
- name : PR 창에서 확인할 수 있는 workflow의 이름을 설정하는 곳이다. Github Action을 적용한다면 이런 화면을 볼 수 있다.
총 3가지 workflow가 통과됐다는 문구 밑의 "Build Develop APK..."를 볼 수 있다. 저곳에 "name:" 오른쪽에 입력한 문자열이 표시된다. 필수 입력은 아니라고 Github Action 공식문서에선 말하지만 이름이 없다면 구분하기 귀찮을 테니 가급적이면 간단하게라도 쓰는 게 좋다.
- run-name : 깃허브 레포지토리에 들어가면 Action 탭을 볼 수 있다. 이걸 눌렀을 때 왼쪽에 workflow들의 목록이 표시되는데, 이 목록에서 표시할 이름이다. 이것 또한 필수 입력사항은 아니기 때문에 생략해도 된다. 솔직히 위의 name 만으로도 충분히 구별되기 때문에 이건 굳이 안 써도 될 것 같다.
- on : workflow가 언제 실행되는지를 작성한다. 이 조건이 갖춰지면 workflow가 작동을 시작하기 때문에 트리거한다고 말하는 듯하다. 예제에선 "on: [push]"라고 적었는데, 이것은 레포지토리에 git push 명령어로 소스코드를 push 했을 때 작동하게 한다는 의미다. 물론 push 뿐 아니라 "pull_request"라고 쓰면 PR이 열리거나 수정됐을 때 작동하게 할 수도 있다. 활용법은 많이 있으니 공식문서와 깃허브에 널린 코드들을 확인하고 내 상황에 맞는 걸 쓰면 된다.
- jobs : workflow에서 실행할 작업들을 정의하는 곳이다. 밑에 띄어쓰기를 2번 해서 다음 단어를 작성하는데, 이 들여쓰기가 보이는 순간부터 들여쓰기 린트를 신경써야 한다. jobs 안에 여러 작업을 정의해서 병렬 실행되게 할 수 있다. 아래는 또 다른 예시다.
name: Example workflow
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Run build
run: make
test:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Run tests
run: make test
"jobs:" 밑에 build, test라는 2개의 Job을 정의했다."needs" 키워드를 사용하면 Job 사이의 종속성을 정의해서 다른 Job이 완료될 때까지 특정 Job을 기다리게 할 수도 있다. 아래와 같은 형태로는 사용할 수 없다. 직접 작성해 보면 컴파일 에러가 발생한다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Run build
run: make
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Run tests
run: make test
- runs-on : Runner를 설정하는 곳이다. ubuntu-latest라고 적었는데, 이것은 최신 버전의 우분투 리눅스 환경에서 workflow를 실행하겠다는 뜻이다. 오늘 날짜인 23.05.10 기준으로 사용할 수 있는 Runner의 종류는 아래와 같다.
- steps : Job 안에서 수행할 작업들을 단계별로 설정한다. "uses:"를 써서 어떤 Action을 사용하겠다고 명시하는데, 필요하다면 "name"을 써서 어떤 Action을 사용할 건지에 대해 주석 달듯이 작성할 수 있다.
안드로이드의 경우 Gradle 버전이 7.4.1 이상인 경우 Github Action을 사용하려면 JDK 11을 사용 설정해야 한다. 그 때 아래와 같이 작성할 수 있다.
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
"uses"만 보면 어떤 걸 하는지 잘 모르는 경우도 있기 때문에 언젠가 읽을 나와 다른 사람을 생각해서 name은 꼭 써준다.
- run : 실행하고 싶은 명령어를 입력하는 곳이다. 예제 코드에선 npm을 통해 bats 패키지를 설치해서 bats에 포함된 명령어들의 버전을 출력한다고 작성돼 있다.
안드로이드의 경우 Gtihub Action에서 apk 파일을 만들려면 gradlew의 권한을 조정해야 한다. 이 때 아래와 같이 작성할 수 있다.
- name: Grant execute permission for gradlew
run: chmod +x gradlew
이런 식으로 "jobs:" 밑에 여러 작업들을 블록 쌓듯이 작성해 내려가면 된다. 슬랙 웹훅을 연결해야 하는 경우엔 레포지토리의 Settings > Secrets and variables > Actions > Secrets 탭에서 만들어 두고 Github Action에서 가져와 사용할 수 있다.
Github Action에서 사용 가능한 Action의 종류는 아래 링크로 들어가면 확인할 수 있다. Gtihub Marketplace로 바로 이동한다.
https://github.com/marketplace?type=actions