logo
Published on

Github Actions 사용해보기

Authors
  • Name
    Twitter

Github Actions란?

Github ActionsGithub 저장소를 기반으로 소프트웨어 개발 Workflows를 자동화 할 수 있는 도구입니다. CI/CD를 포함해 여러 작업들을 수행할 수 있습니다.

여기서 말하는 CI는 테스트와 빌드를 자동으로 할 수 있다는 의미이며 CD는 서버에 배포를 자동으로 할 수 있다는 의미입니다.

Github Actions 공식 문서

Github Actions 장점

  • Github 저장소에 함께 포함되어 있기 때문에 CI를 위한 서버가 따로 필요없다.
  • YAML 파일만으로도 설정이 가능하기 때문에 간편하고 쉽다.
  • 다른 사람들이 만든 여러 Workflow들을 사용할 수 있다.

다른 CI/CD 도구와의 차이점

주로 많이 쓰이는 CI/CD 도구로는 Jenkins가 있는데 이와 비교해보면 Jenkins는 별도의 서버를 구축해야하기 때문에 상대적으로 초기 구축 과정이 힘들지만 구축만 해놓으면 서버 운영 비용을 제외하면 비용이 무료입니다.

Github Actions는 별도의 서버가 필요하지 않지만 private 저장소를 이용할 경우 과금이 발생할 수 있습니다.

사용 한도

  • Workflow는 저장소 하나당 최대 20개까지 등록 가능
  • Workflow 안에 존재하는 Job 단위 당 최대 6시간 동안 실행가능, 초과 시 자동으로 중지
  • public 저장소는 무료이며 private 저장소는 과금 발생
  • Github Free는 한 달에 500MB 스토리지와 실행 시간 2,000분까지 제공
  • Github Pro는 한 달에 1G 스토리지와 실행 시간 3,000분까지 제공 자세한 사용료는 다음 참고: Github Actions 사용료

Workflow 시작

Workflow를 만들고자 하는 저장소의 Actions로 가서 만들 수 있다. Github가 해당 저장소를 분석해서 적절히 제공하는 Workflow 템플릿를 이용하거나 다른 사용자들이 만들어서 Github 마켓플레이스에 공유한 것을 가져와서 쓰는 방법이 있다. 직접 Workflow를 만들 수 도 있다.

YAML 파일 구성

다음은 yml 파일 예시이다.

name: CI

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

  jobs:
    build:
      runs-on: ubuntu-latest

      steps:
      - uses: actions/checkout@v2

      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
  • name: Workflow 이름 지정
name: CI
  • on: 해당 Workflow가 어떤 이벤트에 대해서 실행할 건지 지정할 수 있다. push나 pull_request 같은 이벤트와 crontab 같은 반복 스케줄도 사용할 수 있다.
on:
  push:
    branches: [master]
  pull_request:
    branches: [master]
  • jobs
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
  • 하나의 Workflow는 다양한 Job으로 구성됩니다.
  • 여러 Job이 있을 경우, 병렬로 실행됩니다.
  • build 밑으로 작업 OS를 설정하고 여러 steps을 차례로 진행시키는 구조입니다.
  • 이미 만들어진 액션을 uses에 등록해서 사용할 수 있습니다. 자세한 설정 방법은 여기를 참고하면 좋습니다.

간단한 테스트 자동화 예시

Github Action을 이용하여 간단하게 NestJS 테스트를 자동화하는 예시입니다.

  1. NestJS로 프로젝트 생성 후 Github 저장소에 올리기
  2. Actions로 들어가서 워크플로우를 직접 생성하기
  3. YAML 파일 작성하기

Workflow 이름 및 트리거 지정

name: PR일 때만 테스트

on:
  pull_request:
    branches:
      - test # test라는 브랜치에 PR 올릴 시 동작

name으로 Workflow 이름을 정하고 Workflow를 실행할 트리거를 지정한다. 위의 경우 test라는 브랜치에 PR을 올릴 경우에만 동작하게 된다.

Job 이름 & OS 환경 지정하기

jobs:
  build-test:
    runs-on: ubuntu-latest

job이름을 build-test로 지정해준다. 나중에 해당 이름이 쓰이므로 기억해두자. runs-on을 통해 OS환경을 지정한다. ubuntu-latest OS환경에서 job이 동작하게 된다.

Node 설치하기

steps:
  - uses: actions/checkout@v2
  - name: Setup Node
    uses: actions/setup-node@v1
    with:
      node-version: '14.x'

actions/checkout@v2를 사용해 Github 저장소에 있는 코드들을 가져옵니다. actions/setup-node@v1을 사용해 node를 설치합니다. 버전은 14.x입니다.

npm 설치 및 테스트 실행하기

- name: npm install
  run: npm install

- name: test start
  run: npm run test:cov

npm 설치 후 NestJS 프로젝트 package.json에 설정되어 있는 npm run test:cov 명령어를 통해 테스트를 실행합니다.

If 테스트 실패 시

- name: if fail
  uses: actions/github-script@v4.0.2
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    script: |
      const ref = "${{github.ref}}"
      const pull_number = Number(ref.split("/")[2])
      await github.pulls.createReview({
        ...context.repo,
        pull_number,
        body:"테스트코드를 다시 확인해주세요.",
        event: "REQUEST_CHANGES"
      })
      await github.pulls.update({
        ...context.repo,
        pull_number,
        state: "closed"
      })
  if: failure() # 해당 명령어를 추가하면 이전 step에서 실패 했을 경우에만 이 step이 동작하게 됨

만약 위의 테스트가 실패하였을 경우 해당 step이 실행되게 됩니다. actions/github-scriptGithub actions를 javascript 코드를 통해 제어할 수 있는 액션 툴 입니다. 필요한 파라미터 값인 github-token은 위와 같이 고정하면 기본적으로 현재 저장소에 지정되어 있는 저장소 bot용 github-token이 지정되게 됩니다.

const ref = "${{github.ref}}";
const pull_number = Number(ref.split("/")[2]);

pull request number 가져오기

await github.pulls.createReview({
...context.repo,
pull_number,
body: "테스트코드를 다시 확인해주세요.",
event: "REQUEST_CHANGES",
});

리뷰 생성하기 테스트코드를 다시 확인해주세요. 라는 메시지가 자동으로 생성됩니다.

await github.pulls.update({
  ...context.repo,
  pull_number,
  state: "closed",
});

merge 못하도록 Closed 하기

전체 코드

아래는 전체 실행 코드입니다.

name: PR일 때만 테스트

on:
  pull_request:
    branches:
      - test # test라는 브랜치에만 PR 올릴 시 동작

jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Node
        uses: actions/setup-node@v1
        with:
          node-version: '14.x'

      - name: npm install
        run: npm install

      - name: test start
        run: npm run test:cov

      - name: if fail
        uses: actions/github-script@v4.0.2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const ref = "${{github.ref}}"
            const pull_number = Number(ref.split("/")[2])
            await github.pulls.createReview({
              ...context.repo,
              pull_number,
              body:"테스트코드를 다시 확인해주세요.",
              event: "REQUEST_CHANGES"
            })
            await github.pulls.update({
              ...context.repo,
              pull_number,
              state: "closed"
            })
        if: failure() # 해당 명령어를 추가하면 이전 step에서 실패 했을 경우에만 이 step이 동작하게 됨

merge closed를 하기 위해 branch rule 설정하기

Settings에 Branches에서 방금 설정했던 job이름인 build-test를 설정한다.

여기까지 했다면 test 브랜치에 PR을 할 때마다 Github actions가 동작하고 만약 테스트 코드가 실패할 경우 **테스트코드를 다시 확인해주세요.**라는 메시지가 표시되며 merge를 못하도록 PR이 closed 될 것이다.