개인공부/CI&CD

Github actions: 테스트 자동화 (with Slack)

soon327 2021. 12. 4. 02:57


Github actions: Basic(with YAML)
위 글에서 YAML문법과 workflow의 기본구성에대해 알아보았다. 이번 글에서는 직접 워크플로우를 작성해보도록 하겠다. 😎

👨🏻‍💻 워크플로우 작성하기

이번 글에서는 테스트자동화를 위한 workflow를 작성해보도록 하겠다.
먼저 어떠한 순서로 작업들이 이루어질지 구상해보고 실제 코드로 옮겨 작성해보자.

  1. 이벤트 및 작업환경 설정
  2. main 브랜치로 체크아웃
  3. Node.js 환경설정
  4. npm 캐싱
  5. 패키지 설치
  6. 테스트 실행
  7. PR 시, 테스트 실패할 경우 자동 closed 및 comment 작성
  8. 슬랙에 알림

0. 이벤트 및 작업환경 설정

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [ 12.x,14.x,16.x ]

main브랜치에 push,pull_request 이벤트가 발생할 경우 jobs가 실행되도록 설정하였고
같은 작업들이 3가지 node 버전에서 실행되도록 strategy에 설정하였다.

1. main 브랜치로 체크아웃

      - name: checkout main branch
        uses: actions/checkout@v2

MarketPlace에서 checkout action을 사용하여 repository의 소스를 가져온다.

2. Node.js 환경설정

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
         node-version: ${{ matrix.node-version }}

setup-node action을 사용하여 node환경을 설정해준다. strategy의 matrix.node-version을 참조하여 설정해주었다.

3. npm 캐싱

      - name: npm cache
        uses: actions/cache@v2
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

GIthub의 러너는 각 작업에서 새로운 환경으로 실행되므로 작업들이 종속성을 재사용하는 경우 파일들을 캐싱하여 성능을 향상시킬 수 있다. 캐시를 생성하면 해당 저장소의 모든 워크 플로우에서 사용 가능하다.
위의 코드에서는 매번 node 모듈을 설치하지않고 ~/.npm 디렉토리를 캐시하여 작업 실행속도를 높였다.
cache action에서 사용법을 확인할 수 있다.

4. 패키지 설치 & 5. 테스트 실행

      - name: npm install
        run: npm install

      - name: npm test
        run: npm test

6. PR 시, 테스트 실패할 경우 자동 closed 및 comment 작성

      - name: if fail
        uses: actions/github-script@v5.0.0
        with:
          script: |
            const ref = "${{github.ref}}"
            const pull_number = Number(ref.split("/")[2])
            await github.rest.pulls.createReview({
              ...context.repo,
              pull_number,
              body:"테스트를 통과하지 못했습니다.😢 ",
              event: "REQUEST_CHANGES"
            })
            await github.rest.pulls.update({
              ...context.repo,
              pull_number,
              state: "closed"
            })
        if: failure() 

이 step에서는 github-script action을 사용하였다.
이 액션을 사용하면 다양한 Github API들을 쉽게 사용할 수 있다. 그 중 github과 context라는 변수를 자주 사용하게되는데,
github은 octokit객체이고, context는 현재 실행중인 워크플로우에 대한 컨텍스트 객체로 sha, action, workflow등의 정보를 참조할 수 있다.

github-script를 사용할 때 with 안에 github-token을 설정해주기도 하는데, 이는 필수값은 아니며 github-token을 따로 설정해주지 않을 경우 github에 설정해 둔 default token이 사용된다.

가장 아래의 if를 보면 failure()을 설정하면 "이 step은 다른 step이 중단될 경우에만 실행한다"라는 의미이다. 따라서 테스트가 모두 통과되지 않으면 이 작업이 실행되어 아래처럼 PR이 closed되고 코멘트가 자동으로 작성되게 된다.

7. 슬랙에 알림

      - name: build result to slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{job.status}}
          fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 
        if: always()

action-slack을 사용하여 슬랙에 알람을 보내도록 설정하였다.
이 설정을 위해서는 슬랙 채널에 App을 생성해야 하고 이 App에 Webhook을 추가하여 Webhook URL을 Secrets에 설정해주어야한다.

사전 설정

Slack Api으로 이동하여 create new App 버튼을 누른 뒤 연결할 슬랙 워크스페이스를 선택한다.

Building Apps for Slack / Add features and functionality / Incoming Webhooks 으로 이동하여

On으로 설정해준다.

이후 가장 하단의 Add New Webhook to Workspace 버튼을 클릭하면

webhook이 생성되는데 이 URL을 복사해준다.

복사한 URL을 github action을 생성하는 repository의 setting/secrets에 입력하여 설정해준다.
이 값을 env.SLACK_WEBHOOK_URL에 secrets.xxx로 접근하여 할당해주면 슬랙에 연결 완료!
이후 git action이 실행되면 아래처럼 슬랙에 알람이 가게된다.

슬랙에 보내지는 메시지는 원하는 형태로 커스텀마이징할 수도 있다. 😎

완성된 workflow

name: PR Test

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [ 12,14,16 ]

    steps:
      - name: checkout main branch
        uses: actions/checkout@v2

      # strategy의 matrix.node-version 참조
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
         node-version: ${{ matrix.node-version }}

      - name: npm cache
        uses: actions/cache@v2
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: npm install
        run: npm install

      - name: npm test
        run: npm test

      # PR 시, test 실패할 경우 close 후 comment남기기
      - name: if fail
        uses: actions/github-script@v5.0.0
        with:
          # 원하는 script 선언
          script: |
            const ref = "${{github.ref}}"
            const pull_number = Number(ref.split("/")[2])
            await github.rest.pulls.createReview({
              ...context.repo,
              pull_number,
              body:"테스트를 통과하지 못했습니다.😢 ",
              event: "REQUEST_CHANGES"
            })
            await github.rest.pulls.update({
              ...context.repo,
              pull_number,
              state: "closed"
            })
        if: failure() 

      - name: build result to slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{job.status}}
          fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 
        if: always()

🙏 참고

'개인공부 > CI&CD' 카테고리의 다른 글

Github actions: Basic (with YAML)  (0) 2021.12.01