ARCHIVES

태그

신고하기

상단 메뉴 페이지

기본 콘텐츠로 건너뛰기

[CI/CD] Fastlane, Jenkins를 이용해서 iOS, Android 를 배포한다.


CI/CD란?
Continuous Integration(지속적인 통합)
Continuous Delivery(지속적인 서비스제공) 
Continuous Deployment(지속적인 배포)
  • CI = 빌드 및 테스트 자동화
  • CD = 배포 자동화
엔터프라이즈 배포 앱이 늘어가고 있다.
안드로이드, 아이폰 빌드를 한번에 하기위해 구축
자동화 솔루션을 적용 해본다.

목표
1. 아이폰, 안드로이드 동시 배포
2. 운영 배포 전, 베타 배포 사이트 등록
3. 운영 빌드버전 자동으로 올라가며 배포

---
iPhone
 1. Git에서 브랜치를 체크아웃하고,
 2. Xcode로 빌드하고, 
 3. IPA를 추출하고,
 4. 배포 가능한 페이지에 업로드 하고,
 5. 슬랙으로 결과를 알려준다.

---
Android
 1. Git에서 브랜치를 체크아웃하고,
 2. Andorid로 빌드하고, 
 3. APK를 추출하고,
 4. 배포 가능한 페이지에 업로드 하고,
 5. 슬랙으로 결과를 알려준다.

빌드, 업로드, 노티는 Fastlane으로 해결할 수 있다.
체크아웃, 스케줄링은 Jenkins로 해결할 수 있다.

목적
Slack 과 Dropbox를 이용한 데브 배포
Firebase App Distribution 을 이용한 베타 배포
Email 을 사용한 운영 배포.


현재 내 PC는 M1 실리콘 이다.
이 글은 설치 기록에 가깝다.
=============================
사전 준비
1. 배포용 gmail 계정을 준비한다.
2. 빌드용 ios 계정을 준비한다.
3. email 전송용 outlook 계정을 준비한다.
=============================

0. 자바 설치
M1 이라면 arm빌드된 zulu 추천.

설치된 모든 자바 확인
$ /usr/libexec/java_home -V

Matching Java Virtual Machines (2):

    11.0.12 (arm64) "Azul Systems, Inc." - "Zulu 11.50.19" /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home

    1.8.0_302 (arm64) "Azul Systems, Inc." - "Zulu 8.56.0.23" /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home

$ java -version

openjdk version "1.8.0_302"

OpenJDK Runtime Environment (Zulu 8.56.0.23-CA-macos-aarch64) (build 1.8.0_302-b08)

OpenJDK 64-Bit Server VM (Zulu 8.56.0.23-CA-macos-aarch64) (build 25.302-b08, mixed mode)

jaehwanchoo@jhchooui-Mac ~ % 



1. homebrew를 설치한다.
homebrew 공식 설치 가이드 링크


2. jenkins 설치

홈브루 설치를 했다면 아래와 같이 설치가 가능 하다.
$ brew install jenkins-lts

젠킨스를 설치한다음 아래의 명령어로 젠킨스를 제어할 수 있습니다.

$ brew services start jenkins-lts // 젠킨스 시작
$ brew services stop jenkins-lts // 젠킨스 종료
$ brew services restart jenkins-lts //젠킨스 재시작
로컬 컴퓨터라면 http://localhost:8080 접속.

시작화면이 떴다.
붉은색 위치로 가서 초기 비밀 번호를 적어준다.
$ vi /Users/jaehwanchoo/.jenkins/secrets/initialAdminPassword

플러그인 선택이 나오면, 잘 모르니, 왠만하면 install suggested plugin 을 설치 하자




사용자를 만들고

시작 완료.




3. fastlane 설치

$ brew install fastlane
설치를 하면, 연관된 루비 및 야물 패키지가 같이 설치 된다.
M1에서 ruby, rbenv, rvm 등등 먼저 설치하면 안되는 경우가 있으니, 단독으로 설치 하자.


설치 완료 후 버전 확인 해보자.
$ fastlane env # 설치 버전 확인
현재 버전은 2.191.0 이다.

usage 사용법

공식 문서 링크 : https://docs.fastlane.tools/

1. Fastlane 초기화


iOS 프로젝트 홈 디렉토리로 간 후
$ fastlane init
위 명령어를 입력하면 간단하게 초기화 할 수 있다.

What would you like to use fastlane for?

1. 📸  Automate screenshots

2. 👩‍✈️  Automate beta distribution to TestFlight

3. 🚀  Automate App Store distribution

4. 🛠  Manual setup - manually setup your project to automate your tasks

?


초기화 실행시 위와 같이 용도에 따라 안내를 해주는데 나중에 수정할 수 있으니 어떤 것을 골라도 상관없다.

4번으로 일단 선택했다.

--- ✅ Successfully generated fastlane configuration ---

위 메시지가 뜬 뒤 엔터 몇번 쳐주면 초기화가 완료된다.


2. Fastlane 설정

2.1. 개발자 버전 설정

platform :ios do

  lane :dev do

    begin

        slack_message("APP_NAME 개발자 버전 배포를 시작 합니다.")

        build_app(

            scheme: "APP_NAME",

            configuration: "Debug",

            export_method: "development",

            output_directory: "./build/Debug",

            output_name: "APP_NAME-Debug.ipa",

            clean: true

        )

        slack_message("APP_NAME 개발자 버전 생성 완료!!")

    rescue => exception

        slack_error(exception)

    end

  end

end


def slack_message(message)

  slack(

    message: message,

    success: true,

    slack_url: "슬랙 주소",

    default_payloads: [:git_branch]

  )

end


개발용 배포 버전으로 xcode를 통해 넣을 수 있는 시료폰 만 받을 수 있는 버전이다.

2.2 엔터프라이즈 배포 버전

default_platform(:ios)


platform :ios do

  

  lane :pro do

    #빌드 넘버를 증가 시킨다.

    increment_build_number

    

    #버전 넘버 자동증가

    increment_version_number_in_plist(

        target: "APP_NAME",

        bump_type: "minor" # 자동증가

    )

    #버전 넘버 자동증가

    increment_version_number_in_plist(

        target: "ReachService",

        bump_type: "minor" # 자동증가

    )

    

    buildNumber = get_build_number

    versionNumber = get_version_number(

        target: "APP_NAME"

    )

        

    slack_message("APP_NAME 운영 버전 배포를 시작 합니다.")

    

    begin

        build_app(

            scheme: "APP_NAME",

            configuration: "Release",

            export_method: "enterprise",

            output_directory: "./build/Release",

            output_name: "APP_NAME-Release.ipa",

            clean: true

        )

        

        slack_send({"versionNumber": versionNumber, "buildNumber": buildNumber})

    rescue => exception

        slack_error(exception)

    end

    

  end

  

  lane :slack_send do |options|

    slack(

      message: "APP_NAME 성공적으로 빌드 되었습니다.",

      channel: "#CHANAL_NAME",

      slack_url: "슬랙주소",

      payload: {

        "versionNumber": options[:versionNumber],

        "buildNumber": options[:buildNumber]

      },

      default_payloads: [:git_branch, :last_git_commit_message]

    )

  end

  

end


def slack_message(message)

  slack(

    message: message,

    success: true,

    slack_url: "슬랙주소",

    default_payloads: [:git_branch]

  )

end


def slack_error(exception)

  slack(

    message: "<!here> fastlane 빌드 중 문제가 발생하였습니다.",

    success: false,

    slack_url: "슬랙주소",

    default_payloads: [:git_branch, :last_git_commit_message],

    attachment_properties: {

      fields: [

        {

            title: "에러 내역",

            value: exception

        }

      ]

    }

  )

end


완성된것은 아니지만 일단 이런식으로 빌드가 가능하다.
몇가지 개선사항은 문서를 보면서 진행 할 예정이다.

자동버전 증가를 위해서 바꿔줘야 하는 부분이 있다.


    Current Project Version

        현재 Build number 를 입력

    Versioning System

        Apple Generic 을 선택



개발된 앱은 Extention Rich Push Service를 사용했는데,
두개의 타겟 버전을 증가 시키는데, 기본 fastlane으로는 한계가 있었다.

fastlane addon 을 사용했다.
$ fastlane add_plugin versioning
콘솔에서 바로 추가가 가능하다.


에러 수정 추가.
xcode 와 xcode commenlin 연결이 안되어있으면 연결 해준다.

$ cd /Applications/
$ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer




Badge

앱을 내부배포할 때 dev, stage등 여러가지 앱 스킴을 사용하는 경우들이 있는데 이럴경우 어떤 버전이 설치되어 있는지 직관적으로 알 수 있는 방법이 없다. 
그래서 badge 라는 plugin을 사용하여 앱 아이콘에 뱃지를 넣어주어 직관적인 버전 확인이 가능하도록 해줄 수 있다. 
아래를 참고하여 플러그인을 설치하고, 관련된 모듈들을 설치하도록 하자.
더 자세한 내용은 아래 사이트를 참고하자
# badge
$ fastlane add_plugin badge
#
$ brew install imagemagick
$ brew install librsvg




3. Jenkins 설정


젠킨스 JDK 설정한다.
현재 사용하는 OS가 M1 이기 때문에, zulu-8.jdk 를 사용한다.
인텔이라면, open8.jdk 꼭 8버전을 설치 후 사용해야 한다.
IOS 빌드 의존 라이브러리 ruby-runtime, rvm 는 자바 1.8이 아니면 설치가 안된다.

3.1

젠킨스 설치 완료 후, 설정 파일을 수정하자.
$ vi /usr/local/opt/jenkins/homebrew.mxcl.jenkins.plist
필자는 homebrew로 설치 했기 때문에 해당 위치에 설정 파일이 있다.

아래의 굵은 글씨를 확인하자. 자바 1.8을 사용해 젠킨스를 실행 시킨다.

외부 IP 입력이 가능하도록 0.0.0.0 으로 변경한다.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

        <key>Label</key>

        <string>homebrew.mxcl.jenkins</string>

        <key>ProgramArguments</key>

        <array>

       <string>/usr/libexec/java_home</string>

       <string>-v</string>

       <string>1.8</string>

          <string>--exec</string>

          <string>java</string>


                <string>-Dmail.smtp.starttls.enable=true</string>

                <string>-jar</string>

                <string>/usr/local/opt/jenkins/libexec/jenkins.war</string>

           <string>--httpListenAddress=0.0.0.0</string>

           <string>--httpPort=9999</string>

        </array>

        <key>RunAtLoad</key>

        <true/>

</dict>

</plist>

이제 젠킨스를 재시작 하자.

$ brew services start jenkins // 젠킨스 시작

$ brew services stop jenkins // 젠킨스 종료

$ brew services restart jenkins //젠킨스 재시작


패키지 추가 설치

GitLab 인증관련 플러그인 3개, Rvm 플러그인
을 추가 설치 한다.

fastlane을 인지 못할 때, 환경설정 추가.

Name: Path
Value: /bin
:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin

젠킨스 언어관련 환경설정 또 추가.
Name: LC_ALL
Value: en_US.UTF-8
Name: LANG
Value: en_US.UTF-8

--------
이제 준비가 끝났다.

새로운 아이템을 만든다.
git 경로 적어준다.
gitlab에서 로그인 토큰 만드는 법
로그인 토큰 등록
Excute Shell 등록을 해서 fastlane 명령어 호출 완료.


젠킨스를 사용시 
rvm.env 파일이 생성된다.

커밋 명령어에 오류가 나기 때문에,
commit_version_bump
push_to_git_remote

.gitignore 파일을 생성하여, 커밋 무시 목록을 만든다.
# Desktop Services Store
.DS_Store
# no .env files
*.env
# ignore all files in the build/ directory
build/


fastlane 콘솔에서는 push_to_git_remote 한줄만 적어도 커밋이 가능하지만,
jenkins에서는 푸시 주소를 모두 적어 주어야 한다.
push_to_git_remote(
remote: "origin", # optional, default: "origin"
local_branch: "HEAD", # optional, aliased by "branch", default: "master"
remote_branch: "develop", # optional, default is set to local_branch
force: true, # optional, default: false
tags: true # optional, default: true
)


운영 배포를 아래와 같이 하고 싶으면 옵션 전달을 구현 한다.
# fastlane release bump_type:patch

https://docs.fastlane.tools/actions/increment_version_number/
increment_version_number(
  bump_type: "patch" # Automatically increment patch version number
)
increment_version_number(
  bump_type: "minor" # Automatically increment minor version number
)
increment_version_number(
  bump_type: "major" # Automatically increment major version number
)



참고: 링크1 - 매일 아침7시에 배포를 원한다.
참고: 링크2 - 시리야 앱 배포해줘
참고: 링크3 - iOS 빌드 과정을 손쉽게 자동화 하자
참고: 링크4 - M1 자동화
참고: 링크5 - M1 삽질기.

참고
https://dev-yakuza.posstree.com/ko/react-native/fastlane/

참고
https://littleshark.tistory.com/36

댓글