본문 바로가기
Flutter CICD

GitHub Actions으로 Flutter CI/CD 구축하기 - GitHub Secret 설정

by 6cess 2024. 1. 2.

1, GitHub Secrets 추가

Github Actions에서 제공하는 가상 환경에서 빌드하기 전에 먼저 빌드에 필요한 인증 관련 파일들과 api key 등이 필요하다.

이를 코드로 직접 올리는 것은 보안상 위험하므로 GitHub Secrets으로 등록하여 사용한다.

이때 바이너리 파일을 직접 업로드할 수 없으므로 텍스트 형식으로 암호화 하여 등록하고 가상환경에서 빌드 시 복호화하여 사용한다.

1, GitHub Secrets 추가하는 방법

GitHub Repo > settings > Secrets and Variables > Actions 탭 → New repository secret 클릭

입력할 값의 name과 Secret 입력

2, 바이너리 파일을 텍스트형식으로 암호화하는 방법

Github Secrets에 keystore, p12, provisioning profile과 같은 바이너리 파일을 바로 등록할 수 없기에 텍스트 형식으로 암호화하여 시크릿에 등록한 후 깃허브 액션 가상 환경에서 다시 복호화하는 방식으로 사용해야 한다.

base64 나 gpg 로 암호화하는 방식이 많이 사용되며 여기서는 base64만 안내한다.

1) 암호화 방법(로컬에서)

# base64 < 인코딩할 파일 경로 > 만들 파일 path
base64 <~/.android/debug.keystore> ~/Downloads/debug_keystore_base64.txt

2) 복호화 방법(깃허브 액션 가상환경에서)

# echo -n "디코딩할 파일 경로" | base64 --decode -o 만들 파일 path
echo -n "$P12_DISTRIBUTION_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH

3, Android 빌드를 위한 secret 등록

  • Debug용 keystore (ANDROID_DEBUG_KEYSTORE_BASE64)
  • Release용 keystore (ANDROID_RELEASE_KEYSTORE_BASE64)

Debug용 keystore

프로젝트에서 사용하는 debug.keystore을 확인하여 해당 프로젝트에 등록된 본인의 것을 암호화하여 GitHub Secrets에 ANDROID_DEBUG_KEYSTORE_BASE64이라는 secret을 생성하여 txt파일 내용을 복붙한다.

Release용 keystore

플레이스토어 실제 배포를 위해서는 플레이스토어에 등록된 release용 keystore를 사용해야 한다. 아래는 내 프로젝트의 release 배포 관련 build.gradle 설정이다.

signingConfigs {
        release {
            storeFile file('../keystore/key.jks')
            storePassword file('../keystore/keystore.password').text.trim()
            keyPassword file('../keystore/keystore.password').text.trim()
            keyAlias 'key'
        }
    }

프로젝트 내부 디렉토리에서 .jks 파일과 password파일을 참조하여 사인하는 형태이다. 하지만 현재 gitignore 전략은 keystore.password는 git으로 공유 관리하고 key.jks 만 gitignore에 등록하여 로컬에서만 위치시키는 방식이다. 그러므로 key.jks만 debug.keystore와 동일하게 base64로 인코딩하여 github secret에 ANDROID_RELEASE_KEYSTORE_BASE64라는 이름으로 secret을 생성해 사용한다. 나는 기존의 설정대로 진행하지만 웬만하면 보안상 둘 다 깃허브 시크릿의 등록하여 사용하는 것을 추천한다.

4, iOS 빌드를 위한 secret 등록

  • Certification 파일 (IOS_P12_DISTRIBUTION_CERTIFICATE_BASE64)
  • Certification 파일 추출 시 비밀번호 (IOS_P12_DISTRIBUTION_CERTIFICATE_PASSWORD)
  • Provisioning profile 파일들 (IOS_DISTRIBUTION_PROVISIONING_PROFILE_BASE64, IOS_LOCAL_NOTIFICATION_PROFILE_BASE64)
  • ExportOptions.plist 파일 (IOS_EXPORT_OPTIONS_BASE64)
  • 가상환경에서 생성될 임의의 로컬 키체인 암호 (IOS_RUNNER_LOCAL_KEYCHAIN_PASSWORD)

주의) iOS빌드에 필요한 파일들을 가져올 때 까다로운 것은 Xcode가 제공해주는 autoSign기능으로 인해 생성된 Certificate 파일과 Provisioning profile 파일은 사용할 수 없다. 왜냐하면 Github actions 가상환경에서는 애플 계정으로 로그인하여 xcode autosign 기능을 사용할 수 없기 때문이다. autosign에 사용되는 파일들이 아닌지 잘 확인하여 새로 생성하거나 다른 파일들을 사용해야 한다.

1) Certification 암호화 파일 & 비밀번호 메모

키체인에서 프로젝트에 해당하는 인증서 우클릭 후 .p12 형식으로 export 하여 암호화한다.

해당 p12파일을 base64로 암호화하여 IOS_P12_DISTRIBUTION_CERTIFICATE_BASE64라는 이름으로 github secret에 등록한다.

추출 시 입력한 비밀번호 또한 IOS_P12_DISTRIBUTION_CERTIFICATE_PASSWORD라는 이름으로 secret에 등록한다.

1-1) Distribution Certification 파일이 없을 경우

보통의 환경에서는 xcode에서 자동으로 생성해주는 Certificate 파일만 있기 때문에 Distribution 파일을 새로 생성해주어야 한다.

애플 개발자 센터에서 생성할 수도 있고 xcode에서도 생성할 수 있으나 xcode에서 생성할 경우 필요한 추가 세팅들을 해준다. 애플 개발자 센터에서 직접 생성할 경우 놓치게 되는 세팅이 있을 수 있으니 xcode 추천

Xcode의 settings > Accounts 탭에서 해당되는 계정과 Team을 선택한 후 ‘Manage Certificates’ 클릭

+버튼 클릭 후 Apple Distribution 클릭, 이후 키체인에서 생성된 Certificate파일을 확인할 수 있다.

2) Provisioning profile 파일

현재 나의 프로젝트의 타겟은 Runner(app id : com.wazzang.gongsacok)와 ImageNotification(app id : com.wazzang.gongsacok.ImageNotification) 두개가 있다.

각 타겟이 사용하는 Provisioning profile 파일이 필요하다.

로컬 환경에 저장된 Provisioning profile 파일은 /Users/username/Library/MobileDevice/Provisioning Profiles 디렉토리에 있다.

이 파일들 또한 base64로 암호화한 후 각각 IOS_DISTRIBUTION_PROVISIONING_PROFILE_BASE64과 IOS_LOCAL_NOTIFICATION_PROFILE_BASE64 이름으로 github secrets으로 등록해준다.

2-1) Provisioning profile 파일이 없을 경우

만약 로컬에 필요한 Povisioning profile 파일이 없거나 autosign용 파일 밖에 없을 경우 애플 개발자 센터에서 직접 생성해줘야 한다.

https://developer.apple.com/account 에서 프로파일 클릭

 

+버튼 클릭

 

해당되는 설정(TestFlight과 앱스토어 출시를 위해서는 App store 설정)

 

해당되는 App ID를 선택

타겟별로 Provisioning Profile 파일이 필요할 수도 있으니 타겟의 app ID가 다를 경우 그에 해당하는 App ID 선택

 

해당되는 Certificate 파일 선택

배포 시 사용하기 위해 생성한 Certificate을 선택

3) ExportOptions.plist 파일 생성

ios 빌드 시 어떤 Certificate을 쓰고 어떤 profile을 쓸지에 대한 정보가 담겨져 있는 파일이다. 그러므로 가상환경과 같이 autosign을 하지 못하는 환경에서는 반드시 필요하다.

이 파일을 얻기 위해 가장 간단한 방법은 가상환경에 설정할 certificate, provisioning profile 설정을 그대로 로컬환경의 xcode에 세팅해놓고 프로젝트를 build 하여 빌드 파일을 export하면 된다.

먼저 모든 타겟의 Automatically manage signing 설정을 해제한다.

 

autosign용이 아닌 준비된 profile로 설정한다.(xcode 버그로 반영이 안될 때가 있는데 그때는 automatically manage signing을 다시 체크했다 해제하면 제대로 반영되는 경우가 있다.)

Profile과 연결된 certificate가 준비한 certificate이 맞는지 확인한다.

 

product 탭 > archive 실행 후

 

Distribute app 클릭

 

custom 선택

 

App Store Connect 선택

 

export 설정으로 배포한다.

 

그러면 아래와 같이 생성되는데 이중에 우리는 ExportOptions.plist를  깃허브 시크릿에 등록하면 된다.

다른 파일들과 마찬가지로 base64로 ExportOptions.plist를 암호화하여 IOS_EXPORT_OPTIONS_BASE64 라는 이름으로 github secrets에 등록한다.

4) 키체인 생성 시 사용할 암호 설정

가상환경에서 사용할 임의의 암호를 깃허브 시크릿에 IOS_RUNNER_LOCAL_KEYCHAIN_PASSWORD 이름으로 등록한다.

5, TestFlight 배포를 위한 secret 등록

  • AppStore Connect API key ID (APP_STORE_CONNECT_API_KEY_ID)
  • AppStore Connect API private key (APP_STORE_CONNECT_API_PRIVATE_KEY_BASE64)
  • AppStore Connect IssuerID (APP_STORE_CONNECT_ISSUER_ID)

1) AppStore Connect API Key 생성

 

키 ID 값을 깃허브 시크릿에 APP_STORE_CONNECT_API_KEY_ID 이름으로 등록한다.

 

2) AppStore connect api private key 

다운로드를 눌러 p8 파일을 얻은 다음 이를 base64로 암호화하여 APP_STORE_CONNECT_API_PRIVATE_KEY_BASE64라는 이름으로 깃허브 시크릿에 등록한다.

3) APP_STORE_CONNECT_ISSUER_ID

Issuer ID를 깃허브 시크릿에 APP_STORE_CONNECT_ISSUER_ID 라는 이름으로 등록한다.

 

6, Google Drive API

  • GCP 프로젝트의 서비스 계정 키값 (GOOGLE_SERVICE_ACCOUNT_CREDENTIALS)
  • 구글 드라이브 폴더 id (GOOGLE_DRIVE_DEV_FOLDER_ID, GOOGLE_DRIVE_STAGE_FOLDER_ID)

1) GCP 설정 및 서비스 계정 키값 등록

해당 프로젝트 GCP에서 Google Drive API를 사용하도록 설정

 

좌측 상단 햄버거 버튼 > IAM 및 관리자 > 서비스 계정

 

 

서비스 계정 만들기

 

나머지 설정은 무시하고 완료 서비스 계정 이메일 ID는 구글 드라이브 접근 권한에 등록해줘야 하므로 메모

 

 

키 관리로 이동

 

 

키 추가  후
받은 키 값을 GOOGLE_SERVICE_ACCOUNT_CREDENTIALS라는 이름으로 깃허브 시크릿에 등록.

 

2) 구글 드라이브 공유 목표 폴더의 접근 권한 설정 및 폴더 id 등록

구글 드라이브에서 apk 파일을 업로드할 폴더에서 공유 버튼 클릭

 

서비스 계정 이메일 id 등록

 

폴더 id을 url에서 추출하여 깃허브 시크릿에 GOOGLE_DRIVE_DEV_FOLDER_ID 라는 이름으로 등록

drive/folders/ 뒤의 문자열이 폴더 id 값

 

7, Github Secret 최종 목록

dev, stage, release 환경별로 추가될 수 있다.

 

다음에는 이어서 GitHub Actions을 활용하여

가상 환경에서 apk, ipa 파일을 각각 구글 드라이브와 테스트플라잇에 자동으로 업로드하는

ci/cd를 구현하는 방법을 안내하겠다.