ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [CI/CD] Github Action활용한 aab/apk Play Store 업로드
    Android(+ Kotlin) 2023. 8. 24. 14:29

    서론

    먼저 간략히 CI/CD에 대한 개념을 짚고 넘어가려고 합니다.

    CI(Continuous Integration) - 지속적인 병합

    CD(Continuous Delivery) - 지속적인 배포

     

    여러 개발자가 하나의 서비스를 개발하다 보면 작업 코드를 합쳐야 하고 합친 작업물을 배포하는 것까지 자동화를 통해 관리성을 증가시켜 주기 위합니다.

     

    작업된 코드를 저장/병합 관리하며 "형상관리" 용어를 사용 하며 다양한 솔루션들이 있었으나, 현재 저는 git 빼곤 기억나는게 없을 정도로 git이 최고라고 생각한다.(그 중 가장 접하기 쉬운 github이라 생각한다.)

     

    CI/CD 에서 오늘 작성할 영역은 지속적인 배포를 위한 단계(CD)에 대한 내용을 정리해보려고 합니다.

     

    본론

    1. 간략 단계 설명

    2. github action yml 파일 생성 전 준비물?(google play store 서비스 키, release전용 keystore)

    3. github action yml 파일 작성하기

     

    1. 간략 단계 설명

    github action 단계 설명

    2. github action yml 파일 생성 전 준비물

    - play store service key

    서비스 키 생성 방법 설명은 아래 링크를 통해 참조하자

    https://charko.tistory.com/23

    - release 전용 keystore

    빌드 진행시 keystore를 사용하여 aab를 제작할 때 keystore 파일을 참조하여야 한다.

    github repository에 파일이 존재할경우 해당 패스를 지정하면 된다.

    하지만 gihub권한을 가진 모두가 keystore에 접근이 가능하기에 이 부분에 대한 디테일한 권한을 부여하기가 어려워 질 수 있다.

     

    keystore 파일을 github secret에 저장하여 사용하면 위 문제를 해결할 수 있다.

    scret에서는 String형태만 저장할 수 있음으로 keystore 파일을 String 형태로 인코딩하여 저장합니다.

    secret에 저장된 것을 디코딩하여 파일로 제작하고 제작된 파일을 참조하여 aab 를 만들 수 있다.

     

    먼저 String 형태의 base64로 변환을 해보자

    openssl base64 < {keystore} | tr -d '\n' | tee {keystore.txt}

    (Mac에서는 openssl을 이미 사용 할 수 있습니다.)

     

    변환된 txt를 github secret에 넣습니다.

    secret의 장점은 작성은 가능하나 해당 시크릿 정보를 누구도 확인할 수 없다. (수정하여 덮어씌우기 가능)

     

    https://github.com/marketplace/actions/base64-to-file

     

    base64-to-file - GitHub Marketplace

    Takes a base64-encoded string and writes to a file

    github.com

    위 마켓 플레이스를 활용하여 base64를 다시 디코딩하여 keystore로 변환할 수 있습니다.

     

    name: Decode Keystore
    id: decode_keystore
    uses: timheuer/base64-to-file@v1.2
    with:
    	fileName: '{release.keystore}'
    	fileDir: '{./keystore/ - path}' 
    	encodedString: ${{ secrets.RELEASE_KEYSTORE }}

    위와 같은 yml파일을 통해 변환할 수 있습니다.

    fileName : 변환된 파일이름

    fireDir : 변환된 파일 저장 path

    encodedString : github secret 저장 정보(base64의 인코딩 된)

     

     

    3. github action yml 파일 완성하기

    위 단계까지 마무리가 되었다면 작성의 모든 준비가 끝났습니다.

    이제 yml파일을 작성을 해보자

     

    베이스 영역, keystore 디코딩 영역, play store 업로드 영역 3곳의 영역에 대해서만 언급하고 사이사이 필요한 영역들은 사용자 따라 진행을 추천드립니다.

     

    - 베이스

    깃헙 액션을 선택 후 new workflow를 선택했을 때 선택 영역이 나타납니다. 저는 "android"를 검색하여 Android CI를 선택하여 베이스를 생성합니다.

    자바 환경설치와 gradle 빌드까지의 코드가 자동 설정되어 있습니다.

    name: Android
    
    on:
      push:
        branches: [ "master" ]
      pull_request:
        branches: [ "master" ]
    
    jobs:
      build:
    
        runs-on: ubuntu-latest
    
        steps:
        - uses: actions/checkout@v3
        - name: set up JDK 11
          uses: actions/setup-java@v3
          with:
            java-version: '11'
            distribution: 'temurin'
            cache: gradle
    
        - name: Setup Android SDK
          uses: android-actions/setup-android@v2
    
        - name: Grant execute permission for gradlew
          run: chmod +x gradlew
        - name: Build with Gradle
          run: ./gradlew build

    위와 같이 on 영역은 사용자마다 정책을 만들어 사용하고

    jobs에 대해서 대략적인 설명을 진행합니다.

     

    actions/checkout@v3 - 선택된 브랜치 체크아웃

    actions/setup-java@v3 - java 환경 세팅 -> 저는 현재 java 11버전 기준으로 제작되어 해당 버전으로 진행

    android-actions/setup-android@v2 - 기본 sdk설치 (별도로 추가진행)

     

    run: chmod +x gradlew - 기본적으로 프로젝트의 gradlew의 실행권한이 존재하지 않습니다. 실행권한을 주어야 합니다.

    run: ./gradlew build - 실질적인 빌드 입니다. 해당 영역은 사용자마다 달라질것으로 판단됩니다.

    (keystore repo에 존재하지 않고 secret에 설정했을 때 아래 작업을 먼저 수행 후 gradlew 시행)

     

     

    (repo내 keystore가 존재한다면 아래 영역은 작업할 필요 없음)

    base64 -> keystore 파일 디코딩

    - name: Run Workflow
      id: write_file
      uses: timheuer/base64-to-file@v1.2
      with:
        fileName: '{filename}'
        fileDir: '{filepath}'
        encodedString: ${{ secrets.SOME_ENCODED_STRING }}

    fileName - 변환 후 파일 이름

    fileDir - 변환 후 저장 될 패스

    endcodedString - github secret에 저장된 네임

     

     

    gradlew를 통해 aab가 생성된 후

    play store upload 진행합니다.

     

    https://github.com/marketplace/actions/upload-android-release-to-play-store

     

    Upload Android Release to Play Store - GitHub Marketplace

    An action to upload a signed Android release (.apk or .aab) to the Google Play Store Developer Console

    github.com

    위의 마켓플레이스를 사용합니다. (스타가 가장많아서..)

    - uses: r0adkll/upload-google-play@v1
      with:
      	serviceAccountJsonPlainText: ${{ SERVICE_ACCOUNT_JSON }}
      	packageName: {com.example.MyApp}
      	releaseFiles: {app/build/outputs/bundle/release/app-release.aab}
     	track: {production/internal 등..}
     	status: {inProgress/completed/draft 등..}
     	inAppUpdatePriority: 2
     	userFraction: 0.33 // 점진적 배포를 위한 비율(inProgress와 함께 사용)

    serviceAccoutJsonPlainText - 위 google play store 서비스 키를 주입합니다. (github의 scret활용하는것을 추천합니다.)

    packageName - 업로드 할 앱의 패키지 이름

    releaseFiles - gadlew을 통해 생성된 파일(gradle 버전에 따라, 혹 명령어에 따라 앱 이름은 변경될 수 있습니다.)

    track - 프로덕트 / 내부테스트 기타 테스트 방식이 존재합니다. 필요에 따라 트렉세팅하면 됩니다.

    status - 점진 배포, 풀 배포, 임시 기타 상태를 만들 수 있습니다.

    inAppupdatePriority - 업데이트 우선순위(저는 정확한 의도는 잘 몰라 필수 설정값이 아니여서 사용하지 않습니다.)

    userFraction - 위 status의 inProgress가 되어 있다면 필수 값이며 아니라면 필수는 아닙니다.

     

    기타 여러 옵션이 존재합니다. 해당 영역들은 추가로 위 링크를 참조하여 가이드를 확인하면 좋을것 같습니다.

     

    실질적으로 업로드 동작을 통해 play store에 aab를 업로드 할 수 있습니다.

     

    결론

    "master 브랜치로 푸시가 될때" github action을 통해 aab를 생성하여 play store로 업로드 하게 된다면 개발자로써 신경 쓸 영역이 줄어들게 됩니다.

    회사마다 정책이 있을것이며 그 정책에 맞추어 진행되고 있을것 같다. 내부적인 규칙을 잘 만들고 규칙을 통해 신경쓸 수 있는 것을 줄여가면 좋을것이다.

     

    끝.

    댓글

Designed by Tistory.