React Native) Fastlane으로 배포를 자동화해보자 (Android)

2ast·2022년 11월 3일
1

지난번 Fastlane으로 배포를 자동화해보자 (IOS)에 이어 이번에는 fastlane을 이용해 android의 배포 자동화를 해보려고한다.

사전 준비

ios에서 앱 암호를 발급받아 환경변수로 fastlane에 제공해준 것과 같이 android 자동화를 위해서는 서비스 어카운트라는 것을 만들어 접근권한을 부여해주어야 한다. 해당 과정은 다음과 같다.

  1. 우선 google play console에 접속하여 API 엑세스 탭으로 접근하면 '서비스 계정'이라는 항목이 나오는데, 여기서 '서비스 계정 만드는 방법 알아보기' 버튼을 누른다. 이때 보여지는 가이드에서 Google Colud Platform 링크를 눌러 클라우드 플랫폼 페이지로 이동한다.

  2. 링크를 누르면 자동으로 서비스 계정 탭으로 이동하는데, 여기서 상단의 'CREATE SERVICE ACCOUNT' 문구를 눌러 새로운 서비스 계정을 생성한다.

  3. 서비스 계정을 만드는 과정은 총 3단계로 이루어져 있는데, 이 중 1,2 단계만 완료하면 된다. 첫번째 단계에서 이름, 아이디, 설명을 입력하라고 하는데, 원하는대로 아무렇게나 입력하면 된다.(아이디 같은 경우도 입력한 문구를 기반으로 자동생성해준다.) 그리고 두번째 단계에서는 서비스 계정(Service Accounts) > 서비스 계자 사용자(Service Account User) 순서로 설정해주면 된다.

  4. 다시 이전 페이지로 돌아오면 아래와 같이 새로운 서비스 계정이 만들어진 것을 확인할 수 있다. 이제 새로 만들어진 서비스 계정에 Email 부분을 눌러 세부 설정으로 접근한다.

  5. 세부 페이지 상단 탭에서 KEYS를누른 뒤, ADD KEY>Create New Key를 선택한다. 그러면 아래와 같이 Key type 선택 화면이 뜨는데, JSON을 선택한 채로 CREATE를 누르면 json 파일 하나가 다운로드 된다. 이 파일은 잘 보관해놨다가 프로젝트 폴더 내부 원하는 루트에 배치해주면 된다.

  6. 이제 다시 google play console로 돌아오면 서비스 계정 항목에 새로운 서비스 계정이 나타난 것을 확인할 수 있다. 처음에는 스크린샷과 달리 '엑세스 권한 부여'라는 문구가 있을 것이다. '엑세스 권한 부여' 버튼을 눌러 어떤 권한을 줄 것인지 선택할 수 있다. 나는 fastlane을 통해 배포를 자동화하고, 앱 정보도 수정할 수 있을 것이라 예상했기 때문에 출시와 앱 정보 탭의 모든 권한을 허용해주었다. 권한 부여 선택을 끝마치면 스크린샷과 같이 'Play Console 권한 보기'로 문구가 바뀌게 된다. 이 버튼을 눌러 세부 페이지로 이동한다.

  7. 권한 보기 페이지 내부에는 '앱 권한', '계정 권한', '권한 그룹'이라는 세개의 탭이 존재하는데, '앱 권한' 탭에서 애플리케이션 추가 버튼을 누르고 fastlane으로 자동배포할 앱을 선택하면 된다. 만약 앱 권한에 애플리케이션 추가 버튼이 보이지 않는다면, '권한 그룹' 탭으로 이동한 뒤 새로운 권한 그룹을 만들면 된다.

이렇게 해서 android 배포 자동화를 위한 사전 준비가 끝났다.

Fastlane 초기화

ios와 동일하게 android에서도 fastlane 초기화를 진행한다. android 폴더에서 fastlane init을 실행해준다.

cd android && fastlane init

초기화 과정에서 앱의 패키지명, 아까 다운받은 Key json파일의 경로, 스토어에서 metadata를 다운로드 받을 것인지 여부를 물어본다. 나의 경우 json파일을 android/fastlane 폴더에 위치시켰기 때문에 아래와 같이 경로를 지정해주었고, metadata는 'y'를 눌러 다운받기로 하였다.(metadata 부분은 나중에도 충분히 수정이 가능하기 때문에 건너뛰어도 된다고 한다.)

Path to the json secret file: fastlane/json파일이름

이렇게하면 초기화가 완료되고 android/fastlane 경로에 Appfile, Fastfile이 생성된다. 이번에도 지난번과 마찬가지로 dev-yakuza님의 블로그에서 코드를 참고해 Fastfile을 수정할 것이다.

default_platform(:android)

platform :android do
  def increment_version_code()
    path = '../app/build.gradle'
    re = /versionCode\s+(\d+)/

    s = File.read(path)
    versionCode = s[re, 1].to_i
    s[re, 1] = (versionCode + 1).to_s

    f = File.new(path, 'w')
    f.write(s)
    f.close
  end

  def increment_version_number(bump_type: nil, version_number: nil)
    path = '../app/build.gradle'
    re = /versionName\s+("\d+.\d+.\d+")/
    s = File.read(path)
    versionName = s[re, 1].gsub!('"','').split('.')

    major = versionName[0].to_i
    minor = versionName[1].to_i
    patch = versionName[2].to_i

    if (bump_type == 'major')
        major += 1
        minor = 0
        patch = 0
    elsif (bump_type == 'minor')
        minor += 1
        patch = 0
    elsif (bump_type == 'patch')
        patch += 1
    end

    if(version_number)
      s[re, 1] = "\"#{version_number}\""
    else
      s[re, 1] = "\"#{major}.#{minor}.#{patch}\""
    end

    f = File.new(path, 'w')
    f.write(s)
    f.close
    increment_version_code()
  end

  def updateVersion(options)
    if options[:version]
      version = options[:version]
    else
      version = prompt(text: "Enter the version type or specific version\n(major, minor, patch or 1.0.0): ")
    end

    re = /\d+.\d+.\d+/
    versionNum = version[re, 0]

    if (versionNum)
      increment_version_number(
        version_number: versionNum
      )
    elsif (version == 'major' || version == 'minor' || version == 'patch')
      increment_version_number(
        bump_type: version
      )
    else
      UI.user_error!("[ERROR] Wrong version!!!!!!")
    end
  end

  desc "Submit a new Beta Build to Crashlytics Beta"
  lane :beta do |options|
    updateVersion(options)

    gradle(task: "clean bundleRelease")
    upload_to_play_store(
      skip_upload_metadata: true,
      skip_upload_changelogs: true,
      skip_upload_screenshots: true,
      skip_upload_images: true,
      skip_upload_apk: true,
      track: 'internal'
    )
  end

  desc "Deploy a new version to the Google Play"
  lane :release do |options|
    updateVersion(options)

    gradle(task: "clean bundleRelease")
    upload_to_play_store(
      skip_upload_metadata: true,
      skip_upload_changelogs: true,
      skip_upload_screenshots: true,
      skip_upload_images: true,
      skip_upload_apk: true
    )
  end
end

ios와 비교해서 코드가 많이 길어졌는데, 이는 android에서 build number와 version number를 올리기 위해서는 android/app/build.gradle 파일을 직접 수정해야하기 때문이다. 그 외에 사용법은 ios 때와 동일하다. PROJECT_ROOT/android 경로에서 fastlane beta version:[options] 형태로 작성하면 된다.

//PROJECT_ROOT/android

fastlane beta version:1.1.1
or
fastlane beta version:major
or
fastlane beta version:minor
or
fastlane beta version:patch

트러블 슈팅

위 코드로 테스트 배포를 진행하는 도중 아래와 같이 에러가 발생했다.

increment_version_number': [!] undefined method `gsub!' for nil:NilClass

ruby에서 gsub은 문자열을 치환해주는 역할을 하는 메서드인데, 에러 내용으로 미루어보아 build.gradle 파일의 versionName 변수로부터 값을 가져오는데 문제가 생긴 것으로 보였다. 직접 build.gradle 파일의 versionName을 확인해보니 1.3과 같이 major와 minor까지만 서술되어 있고, Patch단의 number는 빠져있었다. 이를 1.3.0과 같이 3자리로 바꿔주니 에러 없이 동작했다.

versionName "1.3"

to

versionName "1.3.1"

결과

cd android && fastlane beta version:patch
.
.
.
[21:25:48]: Successfully finished the upload to Google Play

+------+----------------------+-------------+
|             fastlane summary              |
+------+----------------------+-------------+
| Step | Action               | Time (in s) |
+------+----------------------+-------------+
| 1    | default_platform     | 0           |
| 2    | clean bundleRelease  | 100         |
| 3    | upload_to_play_store | 43          |
+------+----------------------+-------------+

[21:25:48]: fastlane.tools finished successfully 🎉

beta 명령어로 실행했기 때문에 play console의 '출시 > 내부 테스트' 탭으로 이동하면 정상적으로 배포가 완료된 모습을 확인할 수 있다.

참조 링크 1: https://millo-l.github.io/ReactNative-fastlane/
참조 링크 2: https://dev-yakuza.posstree.com/ko/react-native/fastlane/

profile
React-Native 개발블로그

0개의 댓글