Logo

GitHub Actions에서 워크플로우 재사용하기

GitHub Actions을 사용하다 보면 시간이 지남에 따라 워크플로우가 점점 복잡해지고, 그에 따라 중복되는 부분이 생기며 결국 워크플로우의 유지보수가 어려워지게 되는데요.

이번 포스팅에서는 GitHub Actions에서 워크플로우를 재사용하여 이러한 중복 설정 문제를 해결해보도록 하겠습니다.

실습 워크플로우 생성

실습을 위해서 자바스크립트 프로젝트의 전형적인 워크플로우 파일을 하나 작성해보았습니다. main 브랜치로 새로운 커밋(commit)이 유입되면 애플리케이션을 빌드하여 배포하는 작업을 수행되도록 하겠습니다.

name: Our Deployment
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: check out
        uses: actions/checkout@v3
      - name: set up node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"
          cache: npm
      - name: install
        run: npm ci
      - name: test
        run: npm test
      - name: build
        run: npm run build
      - name: deploy
        run: npm run deploy

6개의 단계(step)로 이루어진 deploy 작업(job)은 우선 프로젝트의 코드를 체크아웃 받고, 그 다음 Node.js와 npm 패키지를 설치하고, 테스트와 빌드 후에 마지막 배포까지 수행하게 됩니다.

GitHub Actions를 사용하여 자바스크립트 프로젝트에서 CI를 구성하는 방법은 관련 포스팅을 참고 바랍니다.

환경 별로 작업 분리하기

실제 프로젝트에서 애플리케이션을 배포할 때는 보통 개발, QA, 상용처럼 여러 환경에 배포하게 되죠?

이렇게 환경 별로 배포를 하기 위해서 deploy 작업을 deploy-dev, deploy-qa, deploy-prod 이렇게 3개의 작업으로 분리해보겠습니다.

name: Our Deployment
on:
  push:
    branches: [main]
jobs:
  deploy-dev:
    environment: dev    runs-on: ubuntu-latest
    steps:
      - name: check out
        uses: actions/checkout@v3
      - name: set up node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"
          cache: npm
      - name: install
        run: npm ci
      - name: test
        run: npm test
      - name: build
        run: npm run build
      - name: deploy
        run: npm run deploy

  deploy-qa:
    needs: [deploy-dev]    environment: qa    runs-on: ubuntu-latest
    steps:
      - name: check out
        uses: actions/checkout@v3
      - name: set up node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"
          cache: npm
      - name: install
        run: npm ci
      - name: test
        run: npm test
      - name: build
        run: npm run build
      - name: deploy
        run: npm run deploy

  deploy-prod:
    needs: [deploy-qa]    environment: prod    runs-on: ubuntu-latest
    steps:
      - name: check out
        uses: actions/checkout@v3
      - name: set up node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"
          cache: npm
      - name: install
        run: npm ci
      - name: test
        run: npm test
      - name: build
        run: npm run build
      - name: deploy
        run: npm run deploy
      - name: notify        run: echo 'Deployment completed in prod! 🎉'

워크플로우 파일이 상당히 길어졌지만 사실 이 3개의 작업 간에는 대부분의 단계는 대동소이합니다.

작업 간에 다른 부분은 environment 속성을 통해 각 작업의 다른 배포 환경을 지정하는 것 밖에 없고요. deploy-dev, deploy-qa, deploy-prod 순으로 작업이 수행되도록 needs 속성을 사용하여 작업 간의 의존 관계를 설정해주고 있습니다.

GitHub Actions에서 작업 간에 실행 순서 제어하는 자세한 방법은 별도 포스팅에서 다루고 있습니다.

워크플로우 화면에 가시면 아래와 같이 3개이 작업이 순차적으로 실행된 것을 보실 수 있으실거에요.

separate-job-by-env

재사용 가능한 워크플로우 생성

위와 같이 유사한 작업을 구성하기 위해서 기존 작업을 복사해서 붙여넣기하는 대신에 워크플로우를 재사용할 수 있는데요. GitHub Actions에서 제공하는 재사용 워크플로우를 활용하여 워크플로우의 불필요한 중복을 방지함으로써 유지보수성을 향상시킬 수 있습니다.

그럼 실습 워크플로우 내의 3개의 작업에서 반복적으로 설정되는 부분을 추출하여 재사용 가능한 워크플로우를 한번 만들어볼까요? 재사용 워크플로우는 workflow_call이라는 이벤트에 반응하며 입력 인자를 정의해줄 수 있습니다.

name: Our Reusable
on:
  workflow_call:    inputs:      env:        type: string        required: true      notify:        type: boolean        default: false
jobs:
  deploy:
    environment: inputs.env    runs-on: ubuntu-latest
    steps:
      - name: check out
        uses: actions/checkout@v3
      - name: set up node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"
          cache: npm
      - name: install
        run: npm ci
      - name: test
        run: npm test
      - name: build
        run: npm run build
      - name: deploy
        run: npm run deploy
      - name: notify
        if: inputs.notify        run: echo 'Deployment completed in ${{ inputs.env }}! 🎉'

입력 인자로 넘어온 문자열 자료형의 env 값을 그대로 environment 속성에 설정해주고, 불리언 자료형의 notify 값이 true로 넘어왔을 때만 notify 단계를 실행하고 있습니다.

재사용 가능한 워크플로우 호출

이제 위에서 만든 재사용 워크플로우를 기존 실습 워크플로우에 적용해 볼 차례인데요.

uses 속성을 통해서 각 작업에 재사용 워크플로우가 위치한 경로를 지정해줍니다. 그리고 with 속성을 통해서 입력 인자를 명시해주면 됩니다.

name: Our Deployment
on:
  push:
    branches: [main]
jobs:
  deploy-dev:    uses: ./.github/workflows/reusable.yml    with:      env: dev
  deploy-qa:    needs: [deploy-dev]    uses: ./.github/workflows/reusable.yml    with:      env: qa
  deploy-prod:    needs: [deploy-qa]    uses: ./.github/workflows/reusable.yml    with:      env: prod      notify: true

상용 배포에 대해서만 알람이 오도록 deploy-prod 작업에서만 notifytrue로 주고 있습니다.

다시 워크플로우 화면에 가시면 동일한 3개의 작업이 재사용 워크플로우를 통해 실행된 것을 확인할 수 있으실 거에요.

use-reusable-workflow

실습 코드

본 포스팅에서 작성한 YAML 파일과 워크플로우 실행 결과는 아래 코드 저장소에서 확인하실 수 있습니다.

https://github.com/DaleSchool/github-actions-reusable-workflows

마치면서

지금까지 간단한 실습을 통해서 GitHub Actions에서 어떻게 재사용 가능한 워크플로우를 만들고 사용하는지 알아보았습니다. 재사용 워크플로우를 잘 활용하셔서 워크플로우를 효과적으로 구성하고 관리하실 수 있으셨으면 좋겠습니다.

GitHub Actions 관련 포스팅은 GitHub Actions 태그를 통해서 쉽게 만나보세요!