Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

GitHub Actions 워크플로우 사용하기

2018년에 GitHub Actions가 처음 발표되고 간단히 Actions를 사용하는 방법에 관해 글을 올렸다.

전체적인 배경이나 컨셉 등은 유지되었지만 일단 사용법이 완전히 달라졌다. 일단 GUI로 설정하는 부분이 사라졌고 HCL에서 YAML로 바뀌었다. 내가 좋아하던 HCL이 도입되어 좋아했지만 여러 상황에 한계를 느꼈는지 요즘 인프라스트럭처를 설정할 때 많이 사용하는 YAML로 바뀌었다. 그래서 혹 검색을 통해서 내 글에 유입될 사람들이 걱정만 하다가 YAML로 바뀐 지는 1년이 되었지만, GitHub Actions를 사용하는 글을 다시 정리한다.

GitHub Actions

GitHub Actions는 CI/CD에 모두 사용할 수 있다. CI로 쓴다는 의미는 테스트 실행이나 빌드 검사, 컨벤션 검사를 통해 코드가 의도대로 동작하고 잘 작성되었는지를 확인할 수 있다는 의미이고 CD는 서버에 배포하거나 레지스트리에 발행하는 등의 행위를 할 수 있다는 의미이다. CI 서비스는 Travis CI, circleci, Azure DevOps등 많이 있지만, 설정을 대부분 비슷하기 때문에 CI 서비스 설정을 해봤다면 어렵지 않게 설정할 수 있다.

GitHub 문서에 잘 나와 있는데 언어별로 다 설정할 수는 없음으로 간단한 Node.js 프로젝트의 CI를 설정해 보자.

GitHub에서 제안하는 워크플로우 템플릿

저장소의 액션 메뉴에 들어가면 저장소 주 언어에 따라서 추천 템플릿을 제공한다. YAML 파일이므로 직접 작성해도 되지만 처음 사용한다면 템플릿을 기반으로 수정하는 게 좋다.

템플릿을 선택하니 보여주는 YAML 파일

템플릿을 선택하면 GitHub에서 제공하는 기본적인 CI가 설정된 파일을 제공하고 여기서 필요에 따라 수정하고 바로 커밋할 수 있다. 위에서 선택한 Node.js 템플릿 파일은 아래와 같이 생겼다.

# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [10.x, 12.x, 14.x]

    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test

문법을 모두 설명하긴 어려우므로 위 예제 파일을 간단히 살펴보자.

name: Node.js CI

name은 이 워크플로우의 이름이다. GitHub Actions에서는 다수의 워크플로우를 설정할 수 있는데 파일마다 하나씩 설정할 수 있다. 이해하기 쉬운 이름을 주면 되고 Actions에서 아래처럼 표시가 된다.

workflow에 보이는 설정한 CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

on은 필수값으로 워크플로우가 어떤 이벤트에 대해서 실행될지를 지정할 수 있다. 위에서는 pushpull_reqeustmaster 브랜치에 대해서 설정한 것인데 간단하게 on: [push, pull_request]로 설정하는 것도 가능하다.

jobs:
  build:

jobs에서 위에서는 jobs.build로 되어 있는데 실제 문법은 jobs.<job_id>가 된다. build는 임의로 지정한 이름이고 아무 이름이나 지정할 수 있다. 여기서는 build라는 잡 하나만 있지만 이름처럼 여러 개의 잡을 설정할 수 있다는 의미이다.

runs-on: ubuntu-latest

runs-on은 잡을 실행할 운영체제로 Windows, Linux, macOS를 지정할 수 있고 노드를 직접 운영하는 경우에는 self-hosted를 지정할 수도 있다.

strategy:
  matrix:
    node-version: [10.x, 12.x, 14.x]

strategy는 위 설정처럼 같은 잡을 여러 버전의 환경에서 실행하고 싶을 때 행렬을 구성한다. 위에서는 Node.js 10, 12, 14버전에서만 실행했지만 os까지 지정하면 더 복잡한 행렬을 구성할 수도 있다.

steps:
  - uses: actions/checkout@v2
  - name: Use Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v1
    with:
      node-version: ${{ matrix.node-version }}
  - run: npm ci
  - run: npm run build --if-present
  - run: npm test

jobs.<job_id>.steps가 잡의 실제 동작을 정의하는 부분이다.

jobs.<job_id>.steps.uses는 각 스텝에서 사용할 액션을 지정한다. 액션은 Marketplace에서 찾을 수 있는데 이미 다른 회사나 사람들이 만들어서 올려둔 액션을 가져다가 설정만 해서 사용할 수 있다.

위에서는 Checkout 액션Setup Node.js environment 액션 사용한 것이다. 이름에서 알 수 있듯이 저장소의 소스 코드를 체크아웃해서 가져오고 원하는 Node.js 버전을 설정한 것이다.

jobs.<job_id>.steps.run은 시스템의 shell에 명령어를 실행하는 부분이다. - run: npm ci처럼 한 줄로 쓸 수 있지만, 다음처럼 이름을 지정할 수도 있다. 이는 UI에서 각 스텝에 표시되는 이름이므로 적절하게 사용하면 된다.

- name: Install Dependencies
  run: npm install

이렇게 설정한 스텝은 GitHub에서 다음과 같이 표시된다.

설정한 Job에서 실행된 step

Workflow syntax for GitHub Actions 문서를 참고하면 다양한 설정을 할 수 있다.

이 파일은 .github/workflows 아래 생성해서 넣으면 되는데 GitHub 사이트에서 직접 만들어도 되고 로컬에서 YAML 파일을 만들어서 올려도 된다. 워크플로우 파일이 생기면 자동으로 Actions이 설정되므로 쉽게 사용할 수 있다. 회사에서 Azure DevOps도 쓰고 있는데 분명 둘이 같은 시스템은 아닌데 쓰다 보면 묘하게 비슷하게 느껴지는 부분이 꽤 있다.

CI의 사용성은 보기에는 편해 보이지만 막상 쓰다 보면 불편하거나 설정이 어려운 부분이 생기고 이상한 문제를 만나서 시간을 꽤 허비하게 되는 게 어느 CI를 쓰거나 비슷하게 느껴지는 편이다. 그런데도 GitHub Actions의 가장 큰 장점은 GitHub에 붙어있다는 점이고 이 부분만으로도 다른 CI 서비스에 큰 위협이 될 만하다고 본다. 내가 쓰는 프로젝트도 점점 GitHub Actions로 넘어가고 있다.

마지막으로 GitHub Actions의 가격정책을 보면 공개 저장소에서는 무료로 사용할 수 있고 비공개 저장소에서는 매월 2,000분의 실행 시간까지는 무료로 사용할 수 있다.

2020/11/12 22:16 2020/11/12 22:16