Git & Github

[Git & Github] Github Action์œผ๋กœ TestFlight ์—…๋กœ๋“œ ํ•ด๋ณด๊ธฐ(3)

๊ฒฝํ‘ธ 2022. 6. 16. 18:30
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š”~

 

์˜ค๋Š˜์€ Github Action์œผ๋กœ TestFlight์— ๋ฐฐํฌํ•˜๋Š” ๊ณผ์ •์˜ ๋งˆ๋ฌด๋ฆฌ ํฌ์ŠคํŒ…์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค : )

 

[ ์ผ๋‹จ ์ง€๋‚œ ํฌ์ŠคํŒ… - ์‚ฌ์ „ ์ค€๋น„ ]

 

[Git & Github] Github Action์œผ๋กœ TestFlight ์—…๋กœ๋“œ ํ•ด๋ณด๊ธฐ(2)

์•ˆ๋…•ํ•˜์„ธ์œ ~ ์ €๋ฒˆ ํฌ์ŠคํŒ…์— ์ด์–ด์„œ TestFlight์— ์–ด๋–ป๊ฒŒ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ณ  ์—ฌ์œ ๊ฐ€ ๋œ๋‹ค๋ฉด ์ œ๊ฐ€ ๊ฒช์—ˆ๋˜ ์ด์Šˆ์— ๋Œ€ํ•œ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…๋„ ํ•จ๊ป˜ ๊ธฐ๋กํ•ด๋ณผ๊ฒŒ์š”! ์ž์ž ์ €๋ฒˆ ํฌ์ŠคํŒ…์—์„œ Github Action์œผ

pooh-footprints.tistory.com

 

yml ํŒŒ์ผ ์ˆ˜์ •

- Github ๋‚ด์—์„œ ์ˆ˜์ •์„ ํ•˜์…”๋„ ๋˜๊ณ  .github/workflows์— ๊ฐ€์‹œ๋ฉด [์ •ํ•˜์…จ๋˜ ์ด๋ฆ„].yml ๊ณผ ๊ฐ™์ด ํ•ด๋‹น ํŒŒ์ผ์ด ์กด์žฌํ•˜๋‹ˆ ์ˆ˜์ •ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

- ๊ธฐ์กด์— ์ž‘์„ฑํ•˜์…จ๋˜ yml ํŒŒ์ผ์ด ์ œ ํฌ์ŠคํŒ…์„ ๋ณด์…จ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ์ •๋ฆฌ๋˜์–ด ์žˆ์„ ๊ฑฐ์˜ˆ์š”.

# Actions ํƒญ์— ํ‘œ์‹œ๋  Workflow ์ด๋ฆ„
name: CI

# Workflow๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ Event ๋ชฉ๋ก
on: # ํŠธ๋ฆฌ๊ฑฐ
  # ํ•˜๋‹จ ์ฝ”๋“œ์— ๋”ฐ๋ผ develop ๋ธŒ๋žœ์น˜์— Push ๋˜๋Š” Pull Request ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์— Workflow๊ฐ€ ์‹คํ–‰
  push:
    branches: [main]
	# ํŠน์ •ํ•œ Branch์— ํ‘ธ์‰ฌ๋˜์—ˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฐ€๋ น feature/*๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋จ
  pull_request:
    branches: [main]

  # ํ•ด๋‹น ์˜ต์…˜์„ ํ†ตํ•ด Actions ํƒญ์—์„œ Workflow๋ฅผ ์‹คํ–‰
  workflow_dispatch:

# Workflow์˜ ํ•˜๋‚˜ ์ด์ƒ์˜ Job 
jobs:
  # Job ์ด๋ฆ„์œผ๋กœ, build๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ Job์ด ํ‘œ์‹œ
  build:
    # Runner๊ฐ€ ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ์„ ์ •์˜
    runs-on: macos-latest # iOS์˜ ๊ฒฝ์šฐ, ๋‹น์—ฐํžˆ macOS์—์„œ ์‹คํ–‰ํ•ด์•ผ๊ฒ ์ฅฌ~

    # build Job ๋‚ด์˜ step ๋ชฉ๋ก
    steps:
      # uses ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด Action์„ ๋ถˆ๋Ÿฌ์˜ด
      # ์—ฌ๊ธฐ์—์„œ๋Š” ํ•ด๋‹น ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ check-out ๋ฐ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” Action์„ ๋ถˆ๋Ÿฌ์˜ด.
      - uses: actions/checkout@v2
      # ์‹คํ–‰๋˜๋Š” ์ปค๋งจ๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ, Workflow์— ํ‘œ์‹œ
      - name: Build
        run: echo Hello, world!

      # ํ•˜๋‚˜์˜ ์ปค๋งจ๋“œ๊ฐ€ ์•„๋‹Œ ์—ฌ๋Ÿฌ ์ปค๋งจ๋“œ๋„ ์‹คํ–‰ ๊ฐ€๋Šฅ
      - name: Run tests
        run: |
          # Xcodebuild๋ฅผ ํ†ตํ•ด์„œ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ๋ฅผ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!
          xcodebuild test -project "$XC_PROJECT" -scheme "$XC_SCHEME" -destination 'platform=iOS Simulator,name=iPhone 13'
          
          
# uses: Repository์˜ ์ฝ”๋“œ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“œ๋Š” ๋ช…๋ น์–ด
# name: ์ž‘์—…์˜ ์ด๋ฆ„
# run: ์ปดํŒŒ์ผ๋Ÿฌ๋กœ ๋นŒ๋“œํ•˜๋Š” ๋ช…๋ น์–ด

 

 

์ด์ œ ์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ ์ค€๋น„ํ–ˆ๋˜ ํŒŒ์ผ๋“ค์„ ์Šคํฌ๋ฆฝํŠธ ์†์— ๋„ฃ์–ด์ฃผ๋ฉด ๋งˆ๋ฌด๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ €ํฌ๊ฐ€ ์ค€๋น„ํ–ˆ๋˜ ํŒŒ์ผ๋“ค์—๋Š”

DistributionCertificate, Distribution Provisioning Profile ์ด ์žˆ๊ณ 

Password๊ฐ€ ์ €์žฅ๋œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค ( secrets ) ์ด ์žˆ์—ˆ์ฃ .

 

1. ๊ธฐ๋ณธ ์„ธํŒ…

name: TID Automation release

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: macos-latest

 

๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ–ˆ๋˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ์•„๋ณด๊ณ  ์ง€๋‚˜๊ฐ€๋ณผ๊ฒŒ์š”.

 

ํ•ด๋‹น Action์˜ ์ด๋ฆ„์„ ์ •ํ•˜๊ณ 

on ์€ ํŠธ๋ฆฌ๊ฑฐ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ํ–ˆ์—ˆ์ฃ ?

 

๋”ฐ๋ผ์„œ main์ด๋ผ๋Š” branch์— Push ๋˜์—ˆ์„ ๋•Œ

ํ˜น์€ main์ด๋ผ๋Š” branch์— PR์ด ์™”์„ ๋•Œ

 

๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ์— ํ•ด๋‹น Action์ด ์‹คํ–‰๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

 

๊ฐœ์ธ ์•ฑ์—์„œ๋Š” ํ˜„์žฌ [main] branch๋ฅผ release๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ด๋’€์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„์ด ์‚ฌ์šฉํ•˜๊ณ  ๊ณ„์‹œ๋Š” ๋ฐฐํฌ์šฉ ๋ธŒ๋žœ์น˜์— ์ ์šฉํ•˜์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™๋„ค์š” : )

 

2. ๊ฐ€์ƒ ํ™˜๊ฒฝ ์„ค์ •

env: # ๊ฐ€์ƒํ™˜๊ฒฝ
      XC_VERSION: ${{ '13.1' }}
      XC_PROJECT: ${{ 'usket_TID.xcodeproj' }}
      XC_SCHEME: ${{ 'usket_TID' }}
      XC_ARCHIVE_PATH: ${{ 'usket_TID.xcarchive' }}
      KEYCHAIN: ${{ 'usket.keychain' }}
      
      ENCRYPTED_CERTS_FILE_PATH: ${{ '.github/secrets/GithubActionKey.p12.gpg' }}
      DECRYPTED_CERTS_FILE_PATH: ${{ '.github/secrets/GithubActionKey.p12' }} # ์–ด๋””์— ๋ณตํ˜ธํ™” ํ•  ๊ฒƒ์ธ์ง€ ๋ช…์‹œ

      ENCRYPTED_PROVISION_FILE_PATH: ${{ '.github/secrets/GithubAction.mobileprovision.gpg' }}
      DECRYPTED_PROVISION_FILE_PATH: ${{ '.github/secrets/GithubAction.mobileprovision' }} # ์–ด๋””์— ๋ณตํ˜ธํ™” ํ•  ๊ฒƒ์ธ์ง€ ๋ช…์‹œ

      CERTS_EXPORT_PWD: ${{ secrets.CERTS_EXPORT_PWD }}
      CERTS_ENCRYPTION_PWD: ${{ secrets.CERTS_ENCRYPTO_PWD }}
      PROFILES_ENCRYPTO_PWD: ${{ secrets.PROFILES_ENCRYPTO_PWD }}

 

์—ฌ๊ธฐ์„œ๋Š” ๊ฐ€์ƒ ๋จธ์‹ ์—์„œ ์‹คํ–‰ํ•  ๋•Œ ํ•„์š”ํ•œ Xcode ๋ฐ ๊ธฐ์กด์— ์ƒ์„ฑํ–ˆ๋˜ ํ‚ค์ฒด์ธ๊ณผ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋“ฑ์„ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค.

XC๋กœ ์‹œ์ž‘ํ•˜๋Š” Xcode์— ๊ด€ํ•œ ์„ค์ •๋“ค์ด ์žˆ๊ณ 

KEYCHAIN๊ณผ ๊ธฐ์กด์— ์•”ํ˜ธํ™”ํ•ด ๋‘์—ˆ๋˜ ํŒจ์Šค์›Œ๋“œ๋“ค์„ ๋“ฑ๋กํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

 

3. Step ( ๊ฐ€์ƒ ํ™˜๊ฒฝ์—์„œ ๋™์ž‘ )

์ผ๋‹จ ์ฝ”๋“œ ์ „๋ฌธ๋ถ€ํ„ฐ ๋ณด์—ฌ๋“œ๋ฆฌ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

steps:
      - name: Setting checkout
        uses: actions/checkout@v3
          
      - name: Select Xcode Version
        run: "sudo xcode-select -s /Applications/Xcode_$XC_VERSION.app"

      - name: Configure Keychain 
        run: | 
          security create-keychain -p "" "$KEYCHAIN" 
          security list-keychains -s "$KEYCHAIN" 
          security default-keychain -s "$KEYCHAIN" 
          security unlock-keychain -p "" "$KEYCHAIN"
          security set-keychain-settings -lut 1200
          security list-keychains
          
      - name : Configure Code Signing
        run: | 
          gpg -d -o "$DECRYPTED_CERTS_FILE_PATH" --pinentry-mode=loopback --passphrase "$CERTS_ENCRYPTION_PWD" "$ENCRYPTED_CERTS_FILE_PATH"
          gpg -d -o "$DECRYPTED_PROVISION_FILE_PATH" --pinentry-mode=loopback --passphrase "$PROFILES_ENCRYPTO_PWD" "$ENCRYPTED_PROVISION_FILE_PATH"
          security import "$DECRYPTED_CERTS_FILE_PATH" -k "$KEYCHAIN" -P "$CERTS_EXPORT_PWD" -A
          security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN"
          mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
          echo `ls .github/secrets/*.mobileprovision`
          # ํ”„๋กœํŒŒ์ผ๋“ค์„ renameํ•˜๊ณ  ์ƒˆ๋กœ๋งŒ๋“  ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌ
          for PROVISION in `ls .github/secrets/*.mobileprovision`
            do
              UUID=`/usr/libexec/PlistBuddy -c 'Print :UUID' /dev/stdin <<< $(security cms -D -i ./$PROVISION)`
            cp "./$PROVISION" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
            done
      - name: Archive App
        working-directory: usket_TID
        run: | 
          xcodebuild clean archive -project "$XC_PROJECT" -scheme "$XC_SCHEME" -configuration release -archivePath "$XC_ARCHIVE_PATH" 
          
      - name: Export App
        working-directory: usket_TID
        run:  |
          xcodebuild -exportArchive -archivePath "$XC_ARCHIVE_PATH" -exportOptionsPlist ExportOptions.plist -exportPath . -allowProvisioningUpdates
          ls
          
#       ์›๋ž˜ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” Github Action ์˜คํ”ˆ์†Œ์Šค 	
#       - name: Upload app to TestFlight
#         uses: apple-actions/upload-testflight-build@v1
#         with:
#           app-path: 'usket_TID.ipa'
#           issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
#           api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}
#           api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}

      - name: Install private API key P8
        env:
          APPSTORE_API_PRIVATE_KEY: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}
          APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }}
        run: | 
          mkdir -p ~/private_keys
          echo -n "$APPSTORE_API_PRIVATE_KEY" | base64 --decode --output ~/private_keys/AuthKey_$APPSTORE_API_KEY_ID.p8
          ls
          
      - name: Upload app to TestFlight
        env:
          APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }}
        run: |
          cd usket_TID
          ls
          xcrun altool --output-format xml --upload-app -f usket_TID.ipa -t ios --apiKey $APPSTORE_API_KEY_ID --apiIssuer ${{ secrets.APPSTORE_ISSUER_ID }}

 

์ด์ œ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

(1) Github Action - checkout

- name: Setting checkout
  uses: actions/checkout@v3

 

Github Action์—์„œ ์ œ๊ณตํ•˜๋Š” checkout์„ ์ด์šฉํ•ด ํ•˜์œ„ ์ž‘์—…๋“ค์„ ์ง„ํ–‰ํ•  ์˜ˆ์ •์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•„์ˆ˜์ ์œผ๋กœ ๋“ค์–ด๊ฐ€์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

(2) Xcode ์„ค์ •

 - name: Select Xcode Version
   run: "sudo xcode-select -s /Applications/Xcode_$XC_VERSION.app"

 

์•ž์„œ ๋งŒ๋“ค์–ด๋’€๋˜ ๋ณ€์ˆ˜๋ฅผ ๋„ฃ์–ด ํ•ด๋‹น ๋ฒ„์ „์˜ Xcode๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

 

(3) ํ‚ค์ฒด์ธ ์„ค์ •

- name: Configure Keychain 
    run: | 
      security create-keychain -p "" "$KEYCHAIN" 
      security list-keychains -s "$KEYCHAIN" 
      security default-keychain -s "$KEYCHAIN" 
      security unlock-keychain -p "" "$KEYCHAIN"
      security set-keychain-settings -lut 1200
      security list-keychains

 

ํ‚ค์ฒด์ธ์„ ์ƒ์„ฑํ•˜๊ณ  ๊ธฐ์กด์˜ ๋ณ€์ˆ˜์— ๋„ฃ์–ด์ฃผ๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ security set-keychain-settings -lut 1200

์ด ์ปค๋งจ๋“œ๋Š” ํ‚ค์ฒด์ธ์˜ ์ œํ•œ์‹œ๊ฐ„์„ ๋งํ•˜๋Š”๋ฐ ์ €๋Š” 1200์ดˆ๋กœ ์„ค์ •ํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. 

์—ฌ๋Ÿฌ๋ถ„๋“ค๋„ ์ผ๋‹จ ์ง„ํ–‰ํ•ด ๋ณด๊ณ  ํƒ€์ž„์•„์›ƒ์ด ๋‚œ๋‹ค๋ฉด ์›ํ•˜๋Š” ์‹œ๊ฐ„๋งŒํผ ์ œํ•œ์‹œ๊ฐ„์„ ๋Š˜๋ ค์ฃผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

(4) Signing

- name : Configure Code Signing
    run: | 
      gpg -d -o "$DECRYPTED_CERTS_FILE_PATH" --pinentry-mode=loopback --passphrase "$CERTS_ENCRYPTION_PWD" "$ENCRYPTED_CERTS_FILE_PATH"
      gpg -d -o "$DECRYPTED_PROVISION_FILE_PATH" --pinentry-mode=loopback --passphrase "$PROFILES_ENCRYPTO_PWD" "$ENCRYPTED_PROVISION_FILE_PATH"
      security import "$DECRYPTED_CERTS_FILE_PATH" -k "$KEYCHAIN" -P "$CERTS_EXPORT_PWD" -A
      security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KEYCHAIN"
      mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
      echo `ls .github/secrets/*.mobileprovision`
      # ํ”„๋กœํŒŒ์ผ๋“ค์„ renameํ•˜๊ณ  ์ƒˆ๋กœ๋งŒ๋“  ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌ
      for PROVISION in `ls .github/secrets/*.mobileprovision`
        do
          UUID=`/usr/libexec/PlistBuddy -c 'Print :UUID' /dev/stdin <<< $(security cms -D -i ./$PROVISION)`
        cp "./$PROVISION" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
        done

 

๊ธฐ์กด์— GnuGP ๋ณด์•ˆ ์„ค๋ฃจ์…˜์„ ์ด์šฉํ•ด gpg๋ผ๋Š” ์ปค๋งจ๋“œ๋กœ ์•”ํ˜ธํ™”ํ–ˆ๋˜ ๊ฒƒ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”?

gpg -d๋Š” dectypt๋กœ ์ €ํฌ๊ฐ€ ์„ค์ •ํ•ด ๋‘” Path๋กœ๋ถ€ํ„ฐ ์•”ํ˜ธ๋ฅผ ๋ฐ›์•„ ๋””์ฝ”๋“œํ•˜์—ฌ ์ ์šฉํ•ด ์ค๋‹ˆ๋‹ค.

 

๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์œ„์˜ ์•”ํ˜ธ๋“ค์„ ์ด์šฉํ•ด ํ‚ค์ฒด์ธ์„ ์ƒ์„ฑํ•˜๊ณ  ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋ณต์‚ฌํ•ด ์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

(5) ์•„์นด์ด๋ธŒ ๋ฐ ipaํŒŒ์ผ ๋งŒ๋“ค๊ธฐ

โ€ป ipa๋Š” iOS ์•ฑ ํŒŒ์ผ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

 

 - name: Archive App
    working-directory: usket_TID
    run: | 
      xcodebuild clean archive -project "$XC_PROJECT" -scheme "$XC_SCHEME" -configuration release -archivePath "$XC_ARCHIVE_PATH" 

  - name: Export App
    working-directory: usket_TID
    run:  |
      xcodebuild -exportArchive -archivePath "$XC_ARCHIVE_PATH" -exportOptionsPlist ExportOptions.plist -exportPath . -allowProvisioningUpdates
      ls

 

์—ฌ๊ธฐ์„œ ์ € ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” working-directory๋ฅผ ์ ์–ด์คฌ๋Š”๋ฐ 

Github์— ํ”„๋กœ์ ํŠธ ํด๋”์˜ ์ƒ์œ„ ํด๋”์— git์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์‹ค์ˆ˜ ๋•Œ๋ฌธ์— ์ ์–ด์คฌ์Šต๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„์€ ์ ์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์•„์š” : )

 

์ด์ œ ์•„์นด์ด๋น™์„ ์ง„ํ–‰ํ•˜๊ณ  ์•„์นด์ด๋ธŒ์—์„œ ipaํŒŒ์ผ์„ ExportOptions.plist๋ฅผ ์ด์šฉํ•ด ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

(6) TestFlight

์ €๋Š” ์ด ๋ถ€๋ถ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์„œ 130๋ฒˆ ์ •๋„ Action์„ ๋Œ๋ ค๊ฐ€๋ฉด์„œ ์˜ค๋ฅ˜๋ฅผ ์ฐพ๊ณ  ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค : (

 

์ผ๋‹จ ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด ๋ณด์‹œ๊ณ  ์•ˆ๋œ๋‹ค ์‹ถ๊ฑฐ๋‚˜ ์ €์™€ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋‹ค๋ฉด ์‚ฌ์šฉํ•ด ๋ณด์„ธ์š”!

 

์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•, Github Action ์˜คํ”ˆ์†Œ์Šค ์‚ฌ์šฉํ•˜๊ธฐ

์ฝ”๋“œ ์ „๋ฌธ์— ๋ณด๋ฉด ์ฃผ์„ ์ฒ˜๋ฆฌ๋œ ๋ถ€๋ถ„์ด ์žˆ๋˜ ๊ฒƒ์„ ํ™•์ธํ•˜์…จ์„ ํ…๋ฐ

๋ฐ”๋กœ ๊ทธ ์ฃผ์„ ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒ๋‹ˆ๋‹ค.

 

- name: Upload app to TestFlight
 uses: apple-actions/upload-testflight-build@v1
 with:
   app-path: 'usket_TID.ipa'
   issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
   api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}
   api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}

 

๋งŒ๋“ค์–ด๋‘” ipaํŒŒ์ผ์˜ ๊ฒฝ๋กœ ๋ฐ ์ €์™€ ํ•จ๊ป˜ ์„ค์ •ํ–ˆ๋˜ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•ด์„œ ๋Œ๋ ค์ฃผ๋ฉด ๋ฐ”๋กœ ๋“ฑ๋ก์ด ๋˜์‹ค ๊ฑฐ์˜ˆ์š”.

 

๋งŒ์•ฝ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์˜จ๋‹ค๋ฉด

The file 'AuthKey_***.p8' could not be found in any of these locations

 

์ œ๊ฐ€ ๊ฒช์—ˆ๋˜ ์˜ค๋ฅ˜๋ž‘ ๊ฐ™์€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. 

 

๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•, ์ œ๊ฐ€ ๋งŒ๋“ค๊ฒŒ์š”.

์ดˆ๊ธฐ์— ์˜ค๋ฅ˜ ๋ฉ”์„ธ์ง€์™€ ๊ด€๋ จ๋œ ๋‚ด์šฉ์„ ํƒ์ƒ‰ํ•˜๋‹ค ๋ณด๋‹ˆ

Xcode 13 ์ด์ƒ๋ถ€ํ„ฐ ๋ฐœ๊ฒฌ๋˜๋Š” ์ด์Šˆ์ธ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ๋‚ด์šฉ์ด ์žˆ์–ด

Xcode์˜ ๋ฒ„์ „์„ ๋ณ€๊ฒฝํ•ด๋ดค์ง€๋งŒ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ถ”๊ฐ€์ ์œผ๋กœ Action ์ž์ฒด์˜ ๋นŒ๋“œ ๋ฒ„์ „์— ๋ฌธ์ œ ์žˆ์„์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ธ€์ด ์žˆ์–ด

๋ฒ„์ „์„ ๋ณ€๊ฒฝํ•ด๊ฐ€๋ฉฐ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์•„์‰ฝ๊ฒŒ๋„ ์ด๋˜ํ•œ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

 

p8์ด ๋ญ”์ง€๋ถ€ํ„ฐ ๋‹ค์‹œ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.

p8์€ ์• ํ”Œ ๊ฐœ๋ฐœ์ž ๊ณ„์ •์—์„œ ๋‹ค์šด๋กœ๋“œํ•ด ์˜จ ๋น„๊ณต๊ฐœ ํ‚ค๋ฅผ ๋งํ•˜๋Š” ๊ฒƒ์ด์—ˆ๊ณ 

action์—์„œ๋Š” ์ด๋ฅผ ์ด์šฉํ•ด ๊ฐ€์ƒํ™˜๊ฒฝ์—์„œ ์•ฑ์Šคํ† ์–ด ์ปค๋„ฅํŠธ API๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ์ž…๋ ฅํ–ˆ๋˜ ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. (APPSTORE_API_PRIVATE_KEY)

 

์ด๋Ÿฐ ์ €๋Ÿฐ ํ—›๋ฐœ์งˆ ๋„์ค‘

์ฐธ๊ณ ํ–ˆ๋˜ ๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ์—์„œ ์ง„ํ–‰ํ–ˆ๋˜ base64 ์ธ์ฝ”๋”ฉ์ด ๊ธฐ์–ต์ด ๋‚ฌ๊ณ 

์ด๊ฒƒ์ด ๋ฌธ์ œ์˜ ์›์ธ์ผ ๊ฒƒ์ด๋ผ๋Š” ํ™•์‹ ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ธ์ฝ”๋”ฉ๋œ ํ‚ค๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์œผ๋ฉฐ ๊ฒฝ๋กœ๋„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ฒฐ๊ตญ ์ถ”๊ฐ€์ ์ธ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ํ•œ ์Šคํฌ๋ฆฝํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 - name: Install private API key P8
    env:
      APPSTORE_API_PRIVATE_KEY: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}
      APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }}
    run: | 
      mkdir -p ~/private_keys
      echo -n "$APPSTORE_API_PRIVATE_KEY" | base64 --decode --output ~/private_keys/AuthKey_$APPSTORE_API_KEY_ID.p8

  - name: Upload app to TestFlight
    env:
      APPSTORE_API_KEY_ID: ${{ secrets.APPSTORE_API_KEY_ID }}
    run: |
      cd usket_TID
      xcrun altool --output-format xml --upload-app -f usket_TID.ipa -t ios --apiKey $APPSTORE_API_KEY_ID --apiIssuer ${{ secrets.APPSTORE_ISSUER_ID }}

 

๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  base64๋กœ ๋””์ฝ”๋”ฉํ•˜์—ฌ ์ €์žฅํ•œ ์ดํ›„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด ๊ณผ์ •์„ ์ง„ํ–‰ํ•˜๊ณ  ๋‚˜๋‹ˆ ๋“œ๋””์–ด TestFlight์— ์„ฑ๊ณต์ ์œผ๋กœ ์—…๋กœ๋“œ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค : - )

 

 


 

 

์ถ”ํ›„์—๋Š” ํ…Œ์ŠคํŠธ๊นŒ์ง€ ์ง„ํ–‰ํ•˜๋Š” ํฌ์ŠคํŒ…์œผ๋กœ ์ฐพ์•„๋ต™๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์ด๋งŒ ๐Ÿ‘‹๐Ÿป ๐Ÿ‘‹๐Ÿป ๐Ÿ‘‹๐Ÿป

๋ฐ˜์‘ํ˜•