본문으로 바로가기
CI/CD

Automatic Capacitor IOS build with GitHub actions with certificate

GitHub 앱에 대한 CI/CD PIPELINE 설정하기 (2024, 5분)

마틴 도나디우

마틴 도나디우

컨텐츠 마케터

Automatic Capacitor IOS build with GitHub actions with certificate

CI/CD를 설정하는 Capacitor 앱에 대한 복잡성과 시간이 많이 걸립니다. 다음을 알아야합니다.

__CAPGO_KEEP_0__ 빌드 __CAPGO_KEEP_1__ __CAPGO_KEEP_2__ 사용을 추천합니다. Capgo 빌드 Capgo CLI native Capacitor builds. 이 Fastlane 가이드는 기존 GitHub Actions pipeline을 유지하는 팀을 위해 보존되지만, 새로운 iOS 빌드는 Capgo CLI을 사용하여 Fastlane, Xcode 런너, 인증서 및 업로드 스크립트를 유지 관리하지 않도록 하세요.

Capgo Build for CI/CD by Capgo

Fastlane, Xcode 런너, 인증서, 배포 프로파일 및 업로드 스크립트 유지 관리를 생략하세요. Capgo Build 기존 CI/CD pipeline에서 signed native iOS 빌드를 실행합니다:

  • pipeline과 함께 작동합니다.: Capgo Build를 GitHub Actions, GitLab CI, Jenkins, 또는 로컬 스크립트에서 웹 빌드 후 트리거하세요. npx cap sync.
  • 인증서에서 서명: App Store Connect 키, 인증서, 배포 프로파일, 비밀번호 및 팀 ID를 CI 비밀에 저장하세요.
  • native 런너 유지 관리를 생략하세요.: Capgo Build는 유지 관리된 Apple 빌드 환경을 제공하므로 macOS 런너, Xcode 이미지를 관리하거나 Fastlane 경로를 관리하지 않도록 하세요.
  • 물품 및 제출: QA에서 서명 된 물품 다운로드하거나 Capgo CLI를 통해 릴리즈 빌드를 제출합니다.

가격

  • Capgo 플랜은 월 $12부터 시작됩니다.
  • OTA 업데이트와 월 15개 정도의 네이티브 빌드가 포함됩니다.
  • 추가 빌드 분량은 분당 크레딧으로 청구됩니다.

Capgo 빌드를 CI/CD에서 설정하세요.

수동 설정 안내서

다음과 같은 단계를 수행하세요:

iOS에 대한 지속적인 배포를 위해 Fastlane과 GitHub 액션 및 인증서를 사용합니다.

준비 사항

이 튜토리얼을 계속하기 전에 다음을 확인하세요:

  • iOS 개발 환경에서 Fastlane을 설치하십시오. 설치되어야 합니다. 개발 머신에 설치되어야 합니다.
  • iOS 개발자 프로그램 회원이되어야 합니다.

가격에 대한 중요한 정보

가격 GitHub 액션

https://github.com/features/actions

서비스는 '무료'까지의 한도에 따라 선택한 기계에 따라 이 글에서는 macOS를 사용하겠습니다.
iOS 개발 환경에서 Fastlane을 설치하십시오. 설치되어야 합니다. 스크린샷에서 가격과 제한을 확인할 수 있습니다. (가격은 이 튜토리얼이 작성된 시점의 가격이며 미래에 변경될 수 있습니다.)

요구 사항과 가격에 대한 경고를 받은 후 계속하세요.

주의: 이 포스트에서는 앱 스토어 연결에서 앱을 생성한 것으로 가정합니다. 중요한 정보는 Fastlane에 의해 복사됩니다!

이 튜토리얼에서 배울 내용

포스트에서 따르는 단계

  1. 앱 스토어 연결 API을 Fastlane과 함께 사용하는 방법
    • 요구 사항:
      • 앱 스토어 연결 API 키 생성
      • 앱 스토어 연결 API 키 사용
  2. Fastlane 파일 복사
  3. GitHub 액션 구성

1. 앱 스토어 연결 API을 Fastlane과 함께 사용하는 방법

2021년 2월부터 모든 사용자가 App Store Connect에 로그인하기 위해 2단계 인증 또는 2단계 확인이 필요합니다. 이 추가 보안 기능은 Apple ID에 대한 보안을 강화하여 계정에 대한 접근을 제한합니다.
From Apple Support

요구 사항

Fastlane이 App Store Connect API에 앱을 업로드할 수 있도록 하려면, 다음 세 가지 정보를 제공해야 합니다. 세 가지: 발급자 ID

  1. 키 ID
  2. 키 파일 또는 키 내용
  3. App Store Connect __CAPGO_KEEP_0__ 키를 얻는 방법

Obtaining an App Store Connect API Key

three

  1. 로그인 앱 스토어 연결.

  2. 선택 사용자 및 액세스.

앱 스토어 연결 사용자 액세스

3 — 통합 탭을 선택하세요.

앱 스토어 연결 API 통합

  1. API 키 생성을 클릭하거나 (+) 버튼을 클릭하세요.

앱 스토어 연결 API 키 생성

  1. 키 이름을 입력하세요. 키 이름은 키 자체의 일부가 아니며, 사용자만 참조할 수 있습니다.

앱 스토어 연결 API 키 이름

6 — 액세스 아래에서 키에 대한 역할을 선택하세요. 키에 적용되는 역할은 팀 내 사용자에 대한 역할과 동일합니다. 자세한 내용은 역할 권한자동으로 iOS 빌드를 위한 Capacitor GitHub 액션 . 우리는 선택을 추천합니다..

  1. 앱 관리자

An API key’s access cannot be limited to specific apps.

__CAPGO_KEEP_0__ 키의 액세스는 특정 앱으로 제한할 수 없습니다.

새 키의 이름, 키 ID, 다운로드 링크 및 기타 정보가 페이지에 나타납니다.

앱 스토어 연결 다운로드 키
필요한 세 가지 정보를 모두 여기에서 가져올 수 있습니다.APPLE_ISSUER_ID 1. 이슈 ID. (
비밀)APPLE_KEY_ID 2. 키 ID. (
3을 클릭하여 "다운로드 API 키"를 클릭하여 API 개인 키를 다운로드하세요. 개인 키가 다운로드되지 않은 경우 다운로드 링크만 표시됩니다. 애플은 개인 키의 복사본을 유지하지 않습니다. 따라서 개인 키를 한 번만 다운로드할 수 있습니다.

🔴 Store your private key in a safe place. You should never share your keys, store keys in a code repository, or include keys in client-side code.

애플 스토어 연결 API 키

API 키 파일(다운로드한 p8 파일), 키 ID, 발급자 ID가 JWT 토큰 인증을 위해 필요합니다. 이 정보를 Fastlane에 전달하는 방법은 여러 가지가 있습니다. Fastlane의 새로운 액션을 사용하여 전달하는 방법을 선택했습니다. 다른 방법은 Fastlane 문서에서 확인할 수 있습니다. 이 방법을 보여주고 있는 이유는 CI에서 가장 쉽게 작업할 수 있는 방법이라고 생각하기 때문입니다. app_store_connect_api_key. CI에서 환경 변수를 설정할 수 있기 때문에. 다운로드한 p8 파일을 Base64로 변환하고 비밀로 저장하세요 (__CAPGO_KEEP_0__ 키를 사용하여 애플 스토어 연결을 Fastlane과 관리할 수 있습니다. 좋습니다!

2. 인증서APPLE_KEY_CONTENT).

base64 -i APPLE_KEY_CONTENT.p8 | pbcopy

Now we can manage the App Store Connect with Fastlane using the API key, great!

설정

을 클릭하세요. 을 클릭하세요. > 계정 > 애플 아이디 > 팀을 선택하세요.

Code 서명 식별자

클릭하여 인증서 관리.

인증서가 아직 없으시다면 인증서를 새로 생성할 수 있습니다.

클릭하여 + 그리고 선택하세요. 애플 배포

애플 배포

그런 다음 키 체인에 인증서를 다운로드하기 위해 키 체인에 가야합니다. 인증서를 파일로 다운로드할 수 있습니다. .p12 이를 수행하려면 키 체인에 가서 로그인 키 체인으로 switch하고 다음 탭으로 이동해야합니다.

로그인 로그인 키 체인 인증서.

인증서

그런 다음 인증서에서 원하는 인증서를 선택할 수 있습니다. (인증서의 날짜를 확인하세요.)

그런 다음 인증서의 개인 키를 오른쪽 클릭하고 선택하세요. Export.

파일 형식 선택 개인 정보 교환 (.p12).

인증서가 다운로드 될 것입니다. .p12 터미널에서 파일을 열어 Base64로 변환하기 위해 다음 명령어를 사용하세요:

이것이 당신의

base64 -i BUILD_CERTIFICATE.p12 | pbcopy

비밀입니다. 또한 인증서의 비밀번호를 제공하실 때, 비밀번호가 당신의 BUILD_CERTIFICATE_BASE64 비밀입니다. P12_PASSWORD 3. 배포 프로파일

열기

애플 개발자 Open 그리고 올바른 팀을 선택하세요.

그 다음에 새로운 프로필을 만들기 위해 클릭하세요. +

새로운 프로필 만들기

그리고 선택하세요. 앱 스토어 연결.

앱 스토어 연결 선택

그 다음에 올바른 앱을 선택하세요. 주의해야 합니다. 와일드 카드 사용하면 서명이 실패할 것입니다.

올바른 앱 선택

올바른 인증서를 선택하세요. (만료일을 확인하세요. 오늘 날짜와 월이 같아야 합니다.) 그리고 클릭하세요. 올바른 인증서 선택.

마지막으로 프로필 이름을 입력하고 클릭하세요.

그리고 올바른 팀을 선택하세요. 생성.

이 이름은 Fastlane에서 프로필을 식별하는 데 사용됩니다. 값은 APPLE_PROFILE_NAME.

프로필 생성

프로필을 생성하여 .mobileprovision 파일로 다운로드할 수 있습니다.

프로필 다운로드

프로필을 Base64로 변환하고 비밀로 저장하세요 (BUILD_PROVISION_PROFILE_BASE64).

base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy

4. Fastlane 파일 복사

Fastlane은 Ruby 라이브러리로 모바일 개발을 자동화하는 데 사용됩니다. Fastlane을 사용하면 Android Studio에서 수행하는 일반적인 작업을 자동화할 수 있습니다. Fastlane은 많은 기능을 제공하지만 이 튜토리얼에서는 Fastlane의 핵심 기능만 사용할 것입니다.

Create the Fastlane folder at the root of your Capacitor/Ionic project and add the Fastfile there:

  • 폴더: <project-root>/fastlane/
  • 파일: <project-root>/fastlane/Fastfile

이것은 동일한 수준입니다. package.json, capacitor.config.*, 그리고 ios/ 폴더입니다. 이것을 내부에 생성하지 마십시오. ios/App/.

platform :ios do
  desc 'Export ipa and submit to TestFlight'
  lane :beta do
    keychain_info = { keychain_name: "ios-build-#{Time.now.to_i}.keychain", keychain_password: SecureRandom.uuid }
    
    begin
      setup_signing(keychain_info)
      bump_build_number
      build_app_with_signing(keychain_info)
      submit_to_testflight
    ensure
      cleanup_keychain(keychain_info)
    end
  end

  private_lane :setup_signing do |options|
    create_keychain(
      name: options[:keychain_name],
      password: options[:keychain_password],
      unlock: true,
      timeout: 0,
      lock_when_sleeps: false, 
      add_to_search_list: true
    )
    import_cert(options)
    install_profile
    update_project_settings
  end

  lane :bump_build_number do
		file = File.read('../package.json')
		data_hash = JSON.parse(file)
		api_key = app_store_connect_api_key(
      key_id: ENV['APPLE_KEY_ID'],
      issuer_id: ENV['APPLE_ISSUER_ID'],
      key_content: ENV['APPLE_KEY_CONTENT'],
      is_key_content_base64: true,
      duration: 1200,
      in_house: false
    )
		build_num = app_store_build_number(
      api_key: api_key,
			app_identifier: ENV['BUNDLE_IDENTIFIER'],
			live: false
    )
		build_num = build_num + 1
		UI.message("Bumped build number to #{build_num}")
		increment_build_number(
			build_number: build_num,
			xcodeproj: "./ios/App/App.xcodeproj",
			skip_info_plist: true
		)
	end

  private_lane :import_cert do |options|
    cert_path = "#{Dir.tmpdir}/build_certificate.p12"
    File.write(cert_path, Base64.decode64(ENV['BUILD_CERTIFICATE_BASE64']))
    import_certificate(
      certificate_path: cert_path,
      certificate_password: ENV['P12_PASSWORD'] || "",
      keychain_name: options[:keychain_name],
      keychain_password: options[:keychain_password],
      log_output: true
    )
    File.delete(cert_path)
  end  
  
  private_lane :cleanup_keychain do |options|
    delete_keychain(
      name: options[:keychain_name]
    )
  end  

  private_lane :install_profile do
    profile_path = "#{Dir.tmpdir}/build_pp.mobileprovision"
    File.write(profile_path, Base64.decode64(ENV['BUILD_PROVISION_PROFILE_BASE64']))
    UI.user_error!("Failed to create provisioning profile at #{profile_path}") unless File.exist?(profile_path)
    ENV['PROVISIONING_PROFILE_PATH'] = profile_path
    install_provisioning_profile(path: profile_path)
    File.delete(profile_path)
  end

  private_lane :update_project_settings do
    update_code_signing_settings(
      use_automatic_signing: false,
      path: "./ios/App/App.xcodeproj",
      code_sign_identity: "iPhone Distribution",
      profile_name: ENV['APPLE_PROFILE_NAME'],
      bundle_identifier: ENV['BUNDLE_IDENTIFIER'],
      team_id: ENV['APP_STORE_CONNECT_TEAM_ID']
    )
    update_project_team(
      path: "./ios/App/App.xcodeproj",
      teamid: ENV['APP_STORE_CONNECT_TEAM_ID']
    )
  end

  private_lane :build_app_with_signing do |options|
    unlock_keychain(
      path: options[:keychain_name],
      password: options[:keychain_password],
      set_default: false
    )
    build_app(
      workspace: "./ios/App/App.xcworkspace",
      scheme: "App",
      configuration: "Release",
      export_method: "app-store",
      output_name: "App.ipa",
      export_options: {
        provisioningProfiles: {
          ENV['BUNDLE_IDENTIFIER'] => ENV['APPLE_PROFILE_NAME']
        }
      },
      xcargs: "-verbose",
      buildlog_path: "./build_logs",
      export_xcargs: "-allowProvisioningUpdates",
    )
  end   

  private_lane :submit_to_testflight do
    api_key = app_store_connect_api_key(
      key_id: ENV['APPLE_KEY_ID'],
      issuer_id: ENV['APPLE_ISSUER_ID'],
      key_content: ENV['APPLE_KEY_CONTENT'],
      is_key_content_base64: true,
      duration: 1200,
      in_house: false
    )
    pilot(
      api_key: api_key,
      skip_waiting_for_build_processing: true,
      skip_submission: true,
      distribute_external: false,
      notify_external_testers: false,
      ipa: "./App.ipa"
    )
  end
end

5. 비밀 설정

GitHub .env Actions는 다음 단계에서 구성한 저장소 비밀을 사용합니다. 로컬 파일이 필요하지 않습니다. 만약 로컬에서 Fastlane을 실행하거나 테스트하고 싶다면.

로컬 테스트를 위해 <project-root>/fastlane/.env next Fastfile를 생성하십시오. 이것을 커밋하지 마십시오. fastlane/.env 에 추가하십시오. (또는 이미 무시된 것을 확인하십시오). 첫 번째 (또는 이미 무시된 것을 확인하십시오). 여기서 예시입니다. .gitignore APP_STORE_CONNECT_TEAM_ID를 가져오기

APP_STORE_CONNECT_TEAM_ID=UVTJ336J2D
BUNDLE_IDENTIFIER=ee.forgr.testfastlane
# See previous section for these secrets
BUILD_CERTIFICATE_BASE64=
BUILD_PROVISION_PROFILE_BASE64=
APPLE_KEY_ID=
APPLE_ISSUER_ID=
APPLE_KEY_CONTENT=
P12_PASSWORD=
APPLE_PROFILE_NAME=

Getting the APP_STORE_CONNECT_TEAM_ID

Go to 개발자 센터 밑으로 스크롤하여 Membership details 섹션을 찾으세요. Team ID 이는 APP_STORE_CONNECT_TEAM_ID secret

app-store-connect-team-id

Getting the BUNDLE_IDENTIFIER

  1. Xcode를 열어보세요
  2. 프로젝트 탐색기에서 App 그것을 더블 클릭하세요
  3. 그런 다음 탭을 클릭하세요 Signing and Capabilities
  4. Copy the value of the Bundle identifier이 값을 설정해야 하는 BUNDLE_IDENTIFIER secret.
bundle-identifier-xcode

6. Build Processing

In GitHub Actions, 사용한 CI/CD 워크플로우의 분량에 따라 요금이 청구됩니다.私の經驗에 따르면, 앱 스토어 연결에서 빌드를 처리하는 데 10–15 분 정도 걸립니다. 개인 프로젝트의 경우, 빌드당 예상 비용은 $0.08/min x 15 mins = $1.2

또는 더 비용이 들 수 있습니다. 프로젝트의 구성 및 의존성에 따라 다릅니다. 개인 프로젝트의 비용에 대한 걱정은 없으시다면, __CAPGO_KEEP_0__

Actions에서 skip_waiting_for_build_processing 까지 true이 방법은 빌드 시간을 줄여 App Store Connect가 빌드를 완료하는 것을 기다리지 않도록 합니다.

그러나, 이 방법을 사용하면 앱의 준수 정보를 App Store Connect에서 수동으로 업데이트해야 합니다.

This optimization is mainly useful for private projects where build minutes cost money. For public/free projects, the build minutes are free so there’s no need to enable this setting. See GitHub’s 가격 정보를 확인하려면 7. __CAPGO_KEEP_0__ 설정

GitHub 설정

GitHub의 비밀을 복사하고 GitHub 저장소의 비밀에 붙여넣으세요.

__CAPGO_KEEP_0__로 이동하세요. .env GitHub 설정

__CAPGO_KEEP_0__ 설정 __CAPGO_KEEP_0__ 설정 &gt; 비밀 및 변수 &gt; 액션 &gt; 새 리포지토리 비밀

github-secrets

2. BUILD_CERTIFICATE_BASE64 - Base64 인코딩된 인증서.

3. BUILD_PROVISION_PROFILE_BASE64 - Base64 인코딩된 배포 프로파일.

4. BUNDLE_IDENTIFIER - 앱의 번들 식별자.

5. APPLE_KEY_ID — 앱 스토어 연결 API 키 🔺키 ID.

6. APPLE_ISSUER_ID — 앱 스토어 연결 API 키 🔺발급자 ID.

7. APPLE_KEY_CONTENT 애플 스토어 연결 API 키 🔺 키 내용 .p8, 체크 하세요

8. GitHub 워크플로 파일을 구성하세요

GitHub 워크플로 디렉토리를 생성하세요

cd .github/workflows

내부 폴더에서 workflow 파일 이름을 build-upload-ios.yml그리고 다음을 추가하세요

name: Build source code on ios

on:
  push:
    tags:
      - '*'

jobs:
  build_ios:
    runs-on: macOS-latest
    steps:
      - uses: actions/checkout@v6
      - name: Set Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: npm
      - name: Install dependencies
        id: install_code
        run: npm ci
      - name: Build
        id: build_code
        run: npm run build
      - uses: actions/cache@v5
        with:
          path: ios/App/Pods
          key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-pods-
      - name: Sync
        id: sync_code
        run: npx cap sync
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.0'
          bundler-cache: true
      - uses: maierj/fastlane-action@v3.1.0
        env:
          APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
          BUNDLE_IDENTIFIER: ${{ secrets.BUNDLE_IDENTIFIER }}
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
          APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
          APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
          APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          APPLE_PROFILE_NAME: ${{ secrets.APPLE_PROFILE_NAME }}
        with:
          lane: ios beta
      - name: Upload release bundle
        uses: actions/upload-artifact@v6
        with:
          name: ios-release
          path: ./App.ipa
          retention-days: 10

이 워크플로가 각 GitHub 태그 태그, 자동화 태그를 필요로 하시면, 자동 빌드 및 릴리즈와 GitHub 액션 첫 번째.

그런 다음 이 워크플로우는 NodeJS 의존성을 가져와서 설치하고 JavaScript 앱을 빌드합니다.

매번 새로운 커밋을 보내면 테스트 플라이트에서 릴리스가 빌드됩니다.

앱은 Ionic을 사용하지 않아도 되며, Capacitor의 기본만 필수입니다. 오래된 Cordova 모듈을 사용할 수 있지만 Capacitor의 JS 플러그인은 선호됩니다.

8. 워크플로우를 트리거합니다.

커밋을 생성합니다.

만들어집니다. 커밋합니다.커밋을 생성하면, 저장소에서 활성화된 워크플로우를 볼 수 있습니다.

워크플로우를 트리거합니다.

브랜치에 새로운 커밋을 푸시하거나 main 워크플로우를 트리거합니다. development 자동 빌드를 트리거합니다.

커밋으로 시작합니다.

몇 분 후에 App Store Connect 대시보드에 빌드가 사용 가능합니다.

테스트 플라이트 대시보드

9. 로컬 머신에서 배포할 수 있나요?

가능합니다. 그리고 매우 간단합니다.

Xcode를 사용하여 앱을 빌드하고 서명할 수 있습니다.

CI/CD 설정 가이드

CI/CD 플랫폼의 대안

라이브 업데이트 및 배포

감사합니다.

이 블로그는 다음 기사에 기반합니다.

Keep going from Automatic Capacitor IOS build with GitHub actions with certificate

Capgo IOS 빌드와 인증서를 사용하는 Capgo 액션으로 자동 Capgo IOS 빌드 Automatic Capacitor IOS build with GitHub actions with certificate CI/CD를 자동화하기 위해 연결하세요. Capgo CI/CD 제품 워크플로우에서 Capgo CI/CD를 사용하세요. Capgo 네이티브 빌드 제품 워크플로우에서 Capgo 네이티브 빌드를 사용하세요. Capgo 통합 제품 워크플로우에서 Capgo 통합을 사용하세요. CI/CD 통합 제품 워크플로우에서 CI/CD 통합을 사용하세요. GitHub 액션 통합 제품 워크플로우에서 GitHub 액션 통합을 사용하세요.

Capacitor 앱에 대한 즉시 업데이트

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

웹层 버그가 활성화된 상태에서, 앱 스토어 승인까지 기다리지 않고 __CAPGO_KEEP_0__를 통해 패치를 배포하세요. 사용자는 배경에서 업데이트를 받으며 네이티브 변경 사항은 일반적인 검토 경로를 유지합니다.

시작하기

최신 블로그

Capgo은 전문적인 모바일 앱을 만들기 위해 필요한 최고의洞察력을 제공합니다.