본문 바로가기

iOS

[iOS] Fatslane + Github Actions로 CI/CD 파이프라인 구축하기 (2편 - Github Actions 살펴보기)

[iOS] Fastlane + Github Actions로 CI/CD 파이프라인 구축하기 (1편 - CI/CD란 무엇일까?)


Github Actions란?

Github Actions는 Build, test, deploy 등의 종합적인 Workflow를 자동화할 수 있는 CI/CD 플랫폼이다. 코드 리뷰, 브랜치 관리, 이슈 우선순위 관리 등의 다양한 WorkFlow에 적용할 수 있다고 한다. 공식 문서 링크로 이동하면 Github Actions에 대한 전반적인 내용을 확인할 수 있다.

 

Github Actions는 Events와 Workflow를 중심으로 자동화가 이루어지는 것이 가장 큰 특징이다. 사용자가 미리 정의한 Workflow는 특정 Github Events들이 발생하는 것을 감지하고 실행될 수 있다.

 

Github Events란 사용자들이 깃허브를 이용하면서 만들어내는 이벤트들로, push, pull request, issue 생성 등이 있을 것이다. 각각의 이벤트들에 원하는 Actions들을 만들어서 자동으로 trigger되도록 하면 수많은 반복작업들을 자동화하여 생산성을 높일 수 있다.

이러한 Events의 예시를 설명하자면 다음과 같은데, 링크를 타고 들어가보면 각 이벤트가 아래 사진의 형식으로 설명되어 있는 모습을 볼 수 있다.


예시)
branch_protection_rule : 브랜치 프로텍션 룰이 생성되거나 삭제되는 경우
create : 브랜치나 태그가 생성되었을 때
delete : 브랜치나 태그가 삭제되었을 때
deployment : deployment가 진행되었을 때
discussion : discussion이 생성되거나, 편집되거나, 삭제되거나, 핀되거나 등등...
fork : 누군가가 레포를 fork했을 때
이외에도 issues, issue_comment, label, merge_group, pull_request_review, push, schedule, watch, workflow_call... 등의 이벤트들이 있다.

 

비용

위 사진에서 보듯이 Public 레포의 경우에는 전면 무료이고, Private 레포의 경우 한정된 용량을 제공하여 유료 결제를 할 경우 사용량을 늘릴 수 있다.

MarketPlace

다른 CI/CD 툴과 비교했을 때 Github Actions의 가장 큰 장점을 하나 꼽으라면 MarketPlace가 있을 것이다. 이미 만들어진 Actions들을 편리하게 Searching 할 수 있고, 이를 원하는 프로젝트에 적용할 수 있다.

Github Actions 직접 적용해보기(링크)

1. 디렉토리 생성 : Github Actions를 적용하고자 하는 레포에 들어가서 .github/workflows 디렉토리를 만든다.

2. 이 경로에서 원하는 이름을 가진 yml 파일을 생성한다. "github-actions-test.yml"로 만들었다. 이 파일의 내용을 아래와 같이 채워 넣어주자
3. 내용은 push 이벤트가 발생할 때, 아래의 jobs를 실행한다는 의미이다. ${{}} 형식을 이용해서 원하는 파라미터의 값을 호출할 수 있고, uses 라는 필드를 이용해서 기존에 깃허브에 존재하는 workflow들을 실행할 수 있다.

name: GitHub Actions Test
on: [push]
jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
      - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v3
      - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
      - run: echo "🖥️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: |
          ls ${{ github.workspace }}
      - run: echo "🍏 This job's status is ${{ job.status }}."

4. 여기서 propose new file을 누르고 PR을 Merge해주면 Workflow가 생성된다!

5. 결과 확인 : Actions 탭에 들어가서 결과를 확인할 수 있다. 가장 먼저 실행된 workflow의 목록을 볼 수 있고, 각 workflow를 클릭하면 각 runs에 대해 확인할 수 있다. 여기서 Jobs 아래의 workflow를 선택하면 세부적인 logs를 확인할 수 있다.

다시 돌아와서, Github Actions의 흐름 살펴보기

레포에서 Event가 발생하면 Github Actions workflow가 트리거되는데, 이러한 workflow는 하나 또는 그 이상의 Jobs를 가진다. Jobs는 순차적 또는 병렬로 실행될 수 있는데, 각 Job들은 각각의 virtual machine에서 실행되어 이 가상 머신들을 Runner라고 부른다. Job의 핵심은 각 Job들이 각각의 가상 머신에서 실행된다는 점이다. 그리고 하나의 Job은 다시 여러 개의 step를 가지는데, 이 steps도 하나 또는 여러개의 tasks 또는, 하나의 action을 실행시킬 수 있다. 그리고 action은 다양한 workflow에서 재사용 가능하다.

Job의 순차 또는 병렬적인 실행에 대해 조금 더 설명하자면, 다양한 아키텍쳐에서의 병렬적인 build의 예시를 들 수 있다. 앱을 배포하기 전에 다양한 아키텍쳐에서 build를 확인하고, 이 작업들이 모두 완료된 후에서야 packaging 작업이 실행되도록 만들 수 있다. 이러한 일은 job의 dependencies를 설정하는 것으로 가능하다.

 

위에서 tutorial을 진행해보면 알 수 있듯, workflows는 하나의 YAML 파일에 의해 정의된다. Workflow는 이벤트에 의해 trigger 시키거나, 수동으로 실행하거나, 정해진 스케쥴에 의해 실행시킬 수 있다. 하나의 레포는 여러개의 workflow를 가질 수 있기 때문에 test, build, deployment에 필요한 다양한 workflow를 구비해 놓고 적절하게 사용할 수 있다.

name: learn-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

위의 예시를 보면 알 수 있듯, run 스크립트 안에는 커맨드 라인 툴에서 동작 가능한 명령어들을 지정할 수 있다. 순차적으로 명령어를 실행하며 build 테스트에 필요한 명령어들을 자동으로 실행하여 runner에서 동작시킨다.

env:
  DAY_OF_WEEK: Monday

jobs:
  greeting_job:
    runs-on: ubuntu-latest
    env:
      Greeting: Hello
    steps:
      - name: "Say Hello Mona it's Monday"
        if: ${{ env.DAY_OF_WEEK == 'Monday' }}
        run: echo "$Greeting $First_Name. Today is $DAY_OF_WEEK!"
        env:
          First_Name: Mona

또한 위와 같이 Custom 변수를 이용할 수도 있고, if 문과 같은 context도 사용할 수 있다. test 환경에 따라 다양한 처리를 해줄 수 있게 되는 것이다.