본문 바로가기
iOS/CICD

CI/CD with Github Actions

by Bokoo14 2024. 9. 19.

0. 환경(Runner) 설정

Docker를 활용한 방법

Docker는 개발 환경을 컨테이너로 묶어 일관된 환경에서 작업을 처리할 수 있어, CI/CD 파이프라인 최적화에 유용

A. Docker 이미지로 환경 통합

  • Docker 이미지를 생성하여 앱의 빌드 환경을 미리 설정하고, 이를 여러 작업에 재사용
  • 각 빌드마다 동일한 환경을 유지하므로, 종속성 문제나 설정 오류를 줄일 수 있으며, 빌드 시간이 단축
  • GitHub Actions에서 Docker 이미지를 사용하는 방법:
    • GitHub Actions 워크플로우에서 docker build를 통해 이미지 빌드
    • 빌드된 이미지를 docker run으로 컨테이너 내에서 테스트 및 배포 진행

B. 자체 호스팅 서버에 Docker 실행

  • self-hosted runner를 사용하여 로컬 또는 클라우드에서 Docker를 실행하는 것도 비용 절감에 도움이 될 수 있습니다.
  • AWS, GCP, Azure 같은 클라우드 서비스에서 Docker 기반의 가상 서버를 설정하고, 이를 CI/CD 서버로 사용하여 워크플로우를 처리할 수 있습니다. 이를 통해 필요한 리소스를 유연하게 조절할 수 있다.

클라우드 인프라 사용

자체 호스팅 외에도, 클라우드 환경을 활용해 직접 가상 환경을 관리

  • AWS EC2 인스턴스: EC2에 macOS 환경을 설정하여 GitHub Actions의 self-hosted runner로 사용하는 방법. 고정 비용이 아닌 종량제 요금제를 사용할 수 있어, 필요할 때만 인스턴스를 띄워 비용을 절감할 수 있다.
  • Google Cloud: GCP의 VM을 이용해 macOS나 Linux 빌드 환경을 설정하고, 필요한 시간에만 작동하게 함

self-hosted  runner

self-hosted로 설정 (GitHub Actions에서 워크플로우를 실행할 때 GitHub이 제공하는 클라우드 기반의 runner를 사용하는 대신, 사용자가 직접 관리하는 서버나 컴퓨터를 runner로 사용하는 것)

Self-Hosted Runner의 장점으로는 Github-hosted Runner와 달리 사용 비용이 전혀 없기 때문에 배포작업이 많은 경우 유용한 기능이다. 하지만 사용하는 시점에 Github와 연결이 되어있어야 하고 로컬머신에 대한 관리가 추가로 필요하다는 단점이 있다. 배포하는 상황에 따라서 적절히 로컬 머신을 연결하여 배포용 서버로 사용하면 좋다.

 

Github의 Settings에서 self-hosted runner를 등록하여 실행할 수 있다.

 

사용 예시

로컬에 “actions-runner”폴더 생성이 완료되면, ./run.sh 명령어를 통해 runner를 idle 상태로 바꿀 수 있다.

status가 Offline일 경우는 listen하지 못한다.


1. CI

깃허브 액션을 통해 commit 혹은 pr단계에서 빌드 및 Unit Test/E2E Test 자동화하여 코드 품질 향상 및 안정성을 확보한다.

develop 브랜치에 Push 혹은 PR이 발생하면, 빌드 자동화 및 Unit/E2E Test가 작동한다.

[flow]
1. develop브랜치에 commit 혹은 PR이 올라온다.
2. Build
3. XCTest (Unit Test)

 

  • xcodebuild build : 프로젝트를 빌드하는 데 집중하며, 테스트는 실행하지 않으며, 빌드가 되는지만 확인
  • xcodebuild clean test: 프로젝트 클린 빌드 후, 모든 유닛 테스트를 실행하여 테스트가 통과하는지 확인
  • clean : 클린 빌드
  • test : 지정된 스킴을 사용하여 테스트 실행
  • project ./fnb-b2c.xcodeproj : 사용할 Xcode 프로젝트 파일 지정
  • -scheme fnb-b2c : 빌드 및 테스트에 사용할 스킴 지정
  • -destination 'platform=iOS Simulator,name=iPhone 15,OS=latest' : 테스트를 실행할 시뮬레이터와 그 환경을 지정

실행 결과

필요한 package 설치 후, 빌드 및 유닛 테스트를 실행

 

참고

 


2. CD

release/* 브랜치에 커밋 혹은 PR 발생 시, 자동으로 빌드, 테스트, 테스트플라이트로 배포되는 프로세스로, 릴리즈의 안정성과 신뢰성을 높일 수 있다. (수동 배포로 생기는 휴먼 에러 방지)

 

TestFlight/App Store 배포를 위해서는 “Code Signing -> Archive -> Export ipa -> App Store 연결 -> 배포” 과정이 필요하다.

자동 배포 과정을 통해 개발자는 깃허브에 푸시하는 것만으로도 테스트플라이트에 배포할 수 있다

 

[flow]
1. release/*브랜치에 push 혹은 PR이 올라온다.
2. 키체인 생성
3. Code Signing (.p12 파일 및 .moblieprovision 파일 필요)
4. 관련 써드파티 라이브러리 설치
5. Archive
6. ipa를 Test Flight에 배포한다.
7. 배포 성공 여부를 Slack과 연동하여 notification을 제공한다.

 

2.1 release/* 브랜치에 push 혹은 PR 생성

 

2.2 키체인 생성

가상 환경에서의 keychain 생성

 

mac에서 키체인에 인증서를 저장하여 접근하는 것과 동일하게, 가상환경에서도 키체인을 생성하고 키체인에 인증서를 저장하고 접근하여야 한다.

 - name: Configure Keychain 
        # 키체인 초기화 - 임시 키체인 생성
        run: |
          security create-keychain -p "" "$KEYCHAIN"
          security list-keychains -s "$KEYCHAIN"
          security default-keychain -s "$KEYCHAIN"
          security unlock-keychain -p "" "$KEYCHAIN"
          security set-keychain-settings

 

2.3.1 Certification & Provisioning

self-hosted에서는 이미 사용자의 맥북에 certification 및 provisioning이 설정되어 있을 것이라 필요없는 과정이지만 가상환경에서 work-flow를 돌리는 상황에서는 초기 세팅부터 새로 하기 때문에 Certificate 및 Provisioning을 통해 앱을 배포하기 위한 인증 과정은 필수적이다.

  • 인증서 (Certificate): iOS 앱을 서명하기 위해 필요한 디지털 인증서. 개발 및 배포를 위해 별도의 인증서를 발급받아야 한다.
  • 프로비저닝 프로파일 (Provisioning Profile): 앱이 특정 장치에서 실행될 수 있도록 허용하며, 인증서와 앱 ID, 앱의 권한 등을 포함한다.

Certification 및 provisioning 참고 문서: https://yanoljafnbsolution.atlassian.net/wiki/spaces/GOUR/pages/8244706

 

2.3.2 Certification 발급 및 저장 (.p12 파일)

키체인 접근 > Apple Distribution 인증서와 개인키를 모두 선택한 후 2개 항목 내보내기

 

해당 과정을 통해 만들어진 .p12 파일이다.

내보내기를 할 때, 암호를 입력해야 한다. Yanolja1225!로 통일한다.

이 암호는 추후 깃허브의 secrets에 CERT_EXPORT_PWD로 저장해둔다.

 

2.3.3 Provisioning Profile 발급 및 저장 (.mobileprovision 파일)

https://developer.apple.com/account/resources/profiles/list

 

로그인 - Apple

 

idmsa.apple.com

 

애플 개발자 계정에 접속하여 Provisioning Profile을 발급하고 저장하는 과정이다.

 

2.3.4 Certification파일(.p12)과 Provisioning Profile(.mobileprovision) 암호화

GPG 암호화(GNU Privacy Guard (GPG)를 이용한 파일 암호화 방법)를 통해 p12파일과 mobileprovision파일 암호화하여 저장

만들어진 .p12파일과 .mobileprovision파일을 그대로 깃허브에 올리면 안되므로, gnupg2를 사용하여 암호화를 진행하여야 한다.

  1. brew install gnupg2 명령어를 통해 gnupg2 설치
  2. gpg -c totoro.p12 명령어를 통해 .p12파일 암호화. 추후 복호화를 위해 해당 암호가 필요하다.
  3. gpg -c totoro.mobileprovision 명령어를 통해 .p12파일 암호화. 추후 복호화를 위해 해당 암호가 필요하다.
 

해당 과정을 통해 암호화된 .p12.gpg 파일 및 .mobileprovision.gpg파일을 얻을 수 있다.

.p12.gpg파일과 .moblieprovision.gpg 파일은 .github/secrets 폴더에 저장해둔다.

암호화된 두 파일은 workflow과정에서 복호화되어 사용된다.

 

      - name : Configure Code Signing
        run: |
          # certificate 복호화
          gpg -d -o "$DECRYPTED_CERT_FILE_PATH" --pinentry-mode=loopback --passphrase "$CERT_ENCRYPTION_KEY" "$ENCRYPTED_CERT_FILE_PATH"
          # provisioning 복호화
          gpg -d -o "$DECRYPTED_PROVISION_FILE_PATH" --pinentry-mode=loopback --passphrase "$PROVISIONING_ENCRYPTION_KEY" "$ENCRYPTED_PROVISION_FILE_PATH"
          
          # security를 사용하여 인증서와 개인 키를 새로 만든 키 체인으로 가져옴
          security import "$DECRYPTED_CERT_FILE_PATH" -k "$KEYCHAIN" -P "$CERT_EXPORT_KEY" -A
          security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN"
          
          # Xcode에서 찾을 수 있는 프로비저닝 프로필 설치하기 위해 우선 프로비저닝 디렉토리를 생성
          mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
          # 디버깅 용 echo 명령어
          echo `ls .github/secrets/*.mobileprovision`
            # 모든 프로비저닝 프로파일을 rename 하고 위에서 만든 디렉토리로 복사하는 과정
            for PROVISION in `ls .github/secrets/*.mobileprovision`
            do
              UUID=`/usr/libexec/PlistBuddy -c 'Print :UUID' /dev/stdin <<< $(security cms -D -i ./$PROVISION)`
            cp "./$PROVISION" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
          done

 

distribution certificate (인증서) 을 이용한 code signing (코드 서명) 과 provisioning profiles 과정은 해당 블로그를 참고 https://sujinnaljin.medium.com/ci-cd-github-actions-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-testflight-%EC%97%85%EB%A1%9C%EB%93%9C-%EC%9E%90%EB%8F%99%ED%99%94-8ecdbeb227a3

 

[CI/CD] Github Actions 를 이용한 TestFlight 업로드 자동화

release branch로 push 하면 TestFlight 업로드하기

sujinnaljin.medium.com

 

 

2.3.5 깃허브 secrets에 workflow에서 필요한 암호 저장

  • CERT_EXPORT_PWD : p12 파일 생성 시 사용한 비밀번호
  • CERTS_ENCRYPTION_PWD : .p12파일을 gpg로 파일 암호화할 때 사용한 암호. 복호화할때 필요
  • PROVISION_ENCRYPTION_PWD : .mobileprovision파일을 gpg로 파일 암호화할 때 사용한 암호. 복호화할때 필요

2.3.6 코드 서명 (Code Signing)

가상 환경에 p12파일과 mobileprovision파일을 설치하는 과정이다. 추후 다른 job에서 이 파일로 code signing한다.

(Certificate 및 Provisioning을 통해 Code Signing과정을 해야만 앱스토어에 앱을 배포할 수 있다.)

위에서 암호화했던 .p12.gpg 파일과 .mobileprovision.gpg 파일을 복호화하고 저장한다.

      - name: Configure Code Signing
        run: |
          # certificate 복호화
          gpg -d -o "$DECRYPTED_CERT_FILE_PATH" --pinentry-mode=loopback --passphrase "$CERT_ENCRYPTION_KEY" "$ENCRYPTED_CERT_FILE_PATH"
          # provisioning 복호화
          gpg -d -o "$DECRYPTED_PROVISION_FILE_PATH" --pinentry-mode=loopback --passphrase "$PROVISIONING_ENCRYPTION_KEY" "$ENCRYPTED_PROVISION_FILE_PATH"

          # security를 사용하여 인증서와 개인 키를 새로 만든 키 체인으로 가져옴
          security import "$DECRYPTED_CERT_FILE_PATH" -k "$KEYCHAIN" -P "$CERT_EXPORT_KEY" -A
          security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN"

          # Xcode에서 찾을 수 있는 프로비저닝 프로필 설치하기 위해 우선 프로비저닝 디렉토리를 생성
          mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
          # 디버깅 용 echo 명령어
          echo `ls .github/secrets/*.mobileprovision`
            # 모든 프로비저닝 프로파일을 rename 하고 위에서 만든 디렉토리로 복사하는 과정
            for PROVISION in `ls .github/secrets/*.mobileprovision`
            do
              UUID=`/usr/libexec/PlistBuddy -c 'Print :UUID' /dev/stdin <<< $(security cms -D -i ./$PROVISION)`
            cp "./$PROVISION" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
          done

 

 

2.4 Pod Install

iOS의 서드파티 라이브러리를 설치하고 프로젝트에 통합한다.

 

2.5 Archive

iOS앱을 아카이브한다. 앱을 빌드하고, 배포 가능한 .ipa 파일을 생성한다.

이 파일은 App Store 혹은 TestFlight에 배포 가능하다.

 

2.6 ipa를 TestFlight 배포

release/1.0.16과 같이 release로 시작하는 브랜치에 Push 혹은 PR이 발생하게 된다면, Test Flight에 자동배포되며, 슬랙 알림이 간다.

TestFlight 배포를 위해서는 “Code Signing -> Archive -> Export ipa -> App Store 연결 -> 배포” 과정이 필요하다.

TestFlight 배포 자동화를 위해서는 Code SigningApp Store연결 부분을 미리 설정해두어야 한다.

직접 깃허브에 올릴 수 없는 민감한 정보들은 프로젝트의 Setting > action > secrets에 따로 저장하여 보호한다.

  • Code Signing을 위한 secrets값들 (iOS)
    • CERTS_ENCRYPTION_PWD
    • PROVISIONING_ENCRYPTION_KEY
    • CERT_EXPORT_PWD
  • App Store 배포를 위한 secrets값들 (iOS)
    • APPSTORE_API_KEY_ID
    • APPSTORE_API_PRIVATE_KEY
    • APPSTORE_ISSURER_ID
  • 슬랙 연동을 위해 필요한 secrets값들
    • SLACK_CHANNEL_ID
    • SLACK_WEBHOOK_URL

참고

2.7 슬랙 알림 설정

  • https://api.slack.com/apps 에 접속하여 "Create an App" 버튼을 클릭
  • “From scratch“옵션을 선택하고 앱 이름과 워크 스페이스 yanolja로 설정 후, “Create App“ 클릭
  • 슬랙 관리자의 승인 필요 (5분내로 승인 완료됨)
 

웹훅 생성

Incoming Webhooks > Add New Webhook to Workspace 클릭

해당 페이지가 나타난다면 App Home > App Display Name을 edit한다.

 
 

참고: https://velog.io/@dulcis-hortus/slackbot-%EC%84%A4%EC%B9%98%ED%95%A0-%EB%B4%87-%EC%82%AC%EC%9A%A9%EC%9E%90%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4

 

[slackbot] 설치할 봇 사용자가 없습니다

다른 블로그 포스팅 보고 진행하다가 Install a Workspace 눌렀는데 이런 에러가 떴나요? 어서 오세요. 😎

velog.io

 

 

슬랙 채널과 연동

알림을 받고 싶은 채널을 선택 후, “허용“ 클릭

 

웹훅 생성 완료

슬랙과 연동할 수 있는 웹훅이 생성되었다.

 

생성한 WebhookURL은 깃허브의 Setting > action > secrets에 따로 저장하여 workflow에서 사용한다.

SLACK_CHANNEL_ID : 생략

SLACK_WEBHOOK_URL : https://hooks.slack.com/services/생략

 

참고

 


3. iOS에서 CI/CD 도입 전 후 비교

CI/CD 도입 전 수동 배포를 통해 배포를 진행하여 수동으로 앱을 ipa파일로 아카이브하고, 이 파일을 수동으로 앱스토어에 배포하는 과정을 거쳐야 하는데 보통 앱 하나 당 5~10분 걸린다.

배포 자동화 워크플로우 도입 후, 한번의 배포에 96%(10분 → 20초)의 배포 시간 감소

[참고] iOS 수동 배포 프로세스

https://velog.io/@cm961115/iOS-TestFlight%EC%97%90-%EC%88%98%EB%8F%99-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0

 

[iOS] TestFlight에 수동 배포하기

Xcode로 iOS앱을 TestFlight에 수동 배포해보자

velog.io

 


4. 도입 후 사례

CI/CD 도입 후, 하루에 3개의 앱을 배포해야 하는 경우 발생

개발자는 깃허브에 release브랜치에 push만 하면 자동으로 배포할 수 있어 배포 시간 단축수동 배포로 인한 휴먼 에러 방지


5. 배포 시간 줄이기

https://blog.lemonbase.team/github-actions-배포-시간-줄여볼까-5725b92e36d9

 

Github Actions 배포 시간 줄여볼까?

1) 제품 개발 생산성 향상 2)인프라 비용 절감 3) Workflow 모듈화를 통한 재사용성 향상 등 3마리 토끼를 모두 잡은 개선 작업들을 공유합니다 💪

blog.lemonbase.team

 

'iOS > CICD' 카테고리의 다른 글

CI/CD란?  (0) 2024.09.19