iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
Mobile Development

我的 Flutter 進化論:30 天打造「Crew Up!」的架構之旅系列 第 25

Day 25 - iOS 上架挑戰實戰:從證書錯誤到 TestFlight 部署

  • 分享至 

  • xImage
  •  

大家好,歡迎來到第二十五天!在 Day 24,我們成功建立了 Android 平台的完整部署流程,從 Keystore 管理到 Firebase App Distribution 的自動化發布。今天,我們要面對 iOS 平台的部署挑戰,學習如何將 Crew Up 應用程式成功上架到 Apple App Store。

從專案開發的經驗來看,iOS 上架最大的挑戰不是理論,而是實際執行中遇到的各種問題。今天我們將分享在 Crew Up 專案中遇到的真實問題,以及如何一步步解決並建立穩定的上架流程。

🔧 iOS 上架前置準備

在深入問題解決之前,讓我們先了解 iOS 上架需要的基本設定。這些設定在 Crew Up 專案中都有實際應用:

1. Apple Developer 憑證設定

建立 iOS Distribution Certificate

在 Crew Up 專案中,我們需要建立正確的 Apple Distribution 證書。以下是我們實際使用的步驟:

步驟 1: 準備 Certificate Signing Request (CSR)

# 在 Mac 上建立 CSR
# 1. 開啟 Keychain Access
# 2. 選單:Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority
# 3. 填寫資訊:
#    - User Email Address: 您的 Apple ID email
#    - Common Name: 您的姓名或公司名稱
#    - CA Email Address: 留空
#    - Request is: Saved to disk
# 4. 選擇儲存位置並命名為 "CertificateSigningRequest.certSigningRequest"

步驟 2: 在 Apple Developer Portal 建立證書

  1. 前往 Apple Developer
  2. 使用您的 Apple ID 登入
  3. 左側選單:Certificates, Identifiers & Profiles
  4. 點擊 Certificates 標籤
  5. 點擊右上角的 "+" 按鈕建立新憑證

步驟 3: 選擇正確的證書類型

  1. Software 區域下選擇 Apple Distribution
  2. 重要: 不要選擇 "Apple Push Services" 或其他類型
  3. 點擊 Continue

步驟 4: 上傳 CSR 檔案

  1. 點擊 Choose File 按鈕
  2. 選擇剛才建立的 CertificateSigningRequest.certSigningRequest 檔案
  3. 點擊 Continue

步驟 5: 下載證書

  1. 證書建立完成後,點擊 Download 按鈕
  2. 檔案名稱通常為 distribution.cerios_distribution.cer
  3. 將檔案儲存到桌面或容易找到的位置

步驟 6: 安裝證書到 Keychain

  1. 雙擊下載的 .cer 檔案
  2. 系統會自動開啟 Keychain Access
  3. 確認證書出現在 login keychain 的 Certificates 分類中
  4. 證書名稱應該顯示為 "Apple Distribution: [您的公司名稱]"

步驟 7: 驗證證書安裝

# 檢查證書是否正確安裝
security find-identity -v -p codesigning

# 應該看到類似這樣的輸出:
# 1) ABC1234567890ABCDEF1234567890ABCDEF123456 "Apple Distribution: Your Company OU"

步驟 8: 匯出 .p12 檔案(包含私鑰)

  1. 在 Keychain Access 中找到 "Apple Distribution" 證書
  2. 右鍵點擊證書 > Export
  3. 選擇 Personal Information Exchange (.p12) 格式
  4. 設定密碼(請記住這個密碼,稍後需要用到)
  5. 儲存為 ios_distribution.p12

步驟 9: 轉換為 Base64 格式

# 方法 1: 直接轉換並複製到剪貼簿
base64 -i ios_distribution.p12 | pbcopy

# 方法 2: 轉換並顯示內容(用於檢查)
base64 -i ios_distribution.p12

# 方法 3: 轉換並儲存到檔案
base64 -i ios_distribution.p12 > ios_distribution_base64.txt

# 方法 4: 一行指令完成轉換和複製
cat ios_distribution.p12 | base64 | pbcopy

# 複製的內容將用於 GitHub Secret: IOS_CERTIFICATE

建立 Provisioning Profile

在 Crew Up 專案中,我們使用 pro.modernwizard.crewup 作為 App ID。以下是我們實際使用的步驟:

步驟 1: 確認 App ID 存在

  1. 前往 Apple Developer
  2. 左側選單:Certificates, Identifiers & Profiles
  3. 點擊 Identifiers 標籤
  4. 確認您的 App ID 已存在(例如:pro.modernwizard.crewup
  5. 如果不存在,點擊 "+" 建立新的 App ID

步驟 2: 建立新的 Provisioning Profile

  1. 點擊 Profiles 標籤
  2. 點擊右上角的 "+" 按鈕
  3. 選擇 App Store 類型(用於 App Store 上架)
  4. 點擊 Continue

步驟 3: 選擇 App ID

  1. 在 App ID 列表中選擇您的應用程式
  2. 點擊 Continue

步驟 4: 選擇 Distribution Certificate

  1. 選擇剛才建立的 Apple Distribution 證書
  2. 重要: 確保選擇的是 "Apple Distribution" 而非 "Apple Push Services"
  3. 點擊 Continue

步驟 5: 命名和產生 Profile

  1. Provisioning Profile Name 欄位輸入名稱(例如:Crew Up Distribution
  2. 點擊 Generate
  3. 等待 Profile 產生完成

步驟 6: 下載 Provisioning Profile

  1. 點擊 Download 按鈕
  2. 檔案名稱通常為 Crew_Up_Distribution.mobileprovision
  3. 將檔案儲存到桌面

步驟 7: 安裝 Provisioning Profile

  1. 雙擊下載的 .mobileprovision 檔案
  2. 系統會自動安裝到 ~/Library/MobileDevice/Provisioning Profiles/
  3. 檔案會以 UUID 重新命名

步驟 8: 驗證 Profile 安裝

# 檢查已安裝的 Provisioning Profiles
ls -la ~/Library/MobileDevice/Provisioning\ Profiles/

# 檢查 Profile 內容
security cms -D -i ~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision | grep -A 5 "Name"

步驟 9: 轉換為 Base64 格式

# 找到正確的 Profile 檔案(通常是最新的)
cd ~/Library/MobileDevice/Provisioning\ Profiles/
ls -lt *.mobileprovision | head -1

# 方法 1: 直接轉換並複製到剪貼簿
base64 -i YOUR_PROFILE.mobileprovision | pbcopy

# 方法 2: 轉換並顯示內容(用於檢查)
base64 -i YOUR_PROFILE.mobileprovision

# 方法 3: 轉換並儲存到檔案
base64 -i YOUR_PROFILE.mobileprovision > profile_base64.txt

# 方法 4: 一行指令完成轉換和複製
cat YOUR_PROFILE.mobileprovision | base64 | pbcopy

# 方法 5: 批次處理多個檔案
for file in *.mobileprovision; do
    echo "Processing: $file"
    base64 -i "$file" | pbcopy
    echo "Base64 content copied to clipboard for: $file"
done

# 複製的內容將用於 GitHub Secret: IOS_PROVISIONING_PROFILE

2. GitHub Secrets 設定

在 Crew Up 專案中,我們需要設定以下 GitHub Secrets 來支援 iOS 自動化部署:

iOS 相關 Secrets

IOS_CERTIFICATE (證書 Base64)

# 方法 1: 直接轉換並複製
base64 -i ios_distribution.p12 | pbcopy

# 方法 2: 轉換並檢查內容長度
base64 -i ios_distribution.p12 | wc -c

# 方法 3: 轉換並儲存到檔案(備份用)
base64 -i ios_distribution.p12 > certificate_base64.txt

# 方法 4: 驗證轉換結果
base64 -d certificate_base64.txt > verify.p12
file verify.p12  # 應該顯示 "data"

IOS_PROVISIONING_PROFILE (Profile Base64)

# 方法 1: 直接轉換並複製
cd ~/Library/MobileDevice/Provisioning\ Profiles/
base64 -i YOUR_PROFILE.mobileprovision | pbcopy

# 方法 2: 自動找到最新的 Profile
ls -t *.mobileprovision | head -1 | xargs base64 -i | pbcopy

# 方法 3: 批次轉換所有 Profiles
for profile in *.mobileprovision; do
    echo "=== $profile ==="
    base64 -i "$profile"
    echo ""
done

# 方法 4: 驗證 Profile 內容
base64 -i YOUR_PROFILE.mobileprovision | base64 -d | security cms -D

IOS_GOOGLESERVICE_INFO_PLIST (Firebase 配置 Base64)

# 方法 1: 直接轉換並複製
base64 -i ios/Runner/GoogleService-Info.plist | pbcopy

# 方法 2: 轉換並檢查內容
base64 -i ios/Runner/GoogleService-Info.plist | head -c 100

# 方法 3: 驗證轉換結果
base64 -i ios/Runner/GoogleService-Info.plist | base64 -d | plutil -p -

App Specific Password

  1. 前往 https://appleid.apple.com
  2. Sign-In and Security > App-Specific Passwords
  3. Generate Password
  4. 標籤輸入:GitHub Actions iOS CD
  5. 複製產生的密碼 (xxxx-xxxx-xxxx-xxxx)

Crew Up 專案需要的 GitHub Secrets 清單

  • IOS_CERTIFICATE: Base64 編碼的 .p12 檔案
  • IOS_CERTIFICATE_PASSWORD: .p12 檔案密碼
  • IOS_PROVISIONING_PROFILE: Base64 編碼的 .mobileprovision 檔案
  • APPLE_ID: Apple Developer 帳戶 email
  • APPLE_ID_PASSWORD: App Specific Password
  • APPLE_TEAM_ID: Apple Developer Team ID
  • IOS_GOOGLESERVICE_INFO_PLIST: iOS Firebase 設定檔案的 Base64 編碼

3. Firebase iOS 設定

在 Crew Up 專案中,我們需要設定 Firebase iOS 設定:

取得 GoogleService-Info.plist

  1. 從 Firebase Console 下載 iOS 的 GoogleService-Info.plist
  2. 執行 base64 -i ios/Runner/GoogleService-Info.plist | pbcopy
  3. 貼到 GitHub Secret IOS_GOOGLESERVICE_INFO_PLIST

📊 iOS 證書與 Provisioning Profile 關係圖

在深入問題解決之前,讓我們先理解 iOS 證書系統的工作原理。這個理解對解決 Crew Up 專案中遇到的問題非常重要:

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   Mac Keychain  │    │ Apple Developer  │    │   Provisioning  │
│                 │    │     Portal       │    │     Profile     │
├─────────────────┤    ├──────────────────┤    ├─────────────────┤
│ 1. 產生 CSR      │───▶│ 2. 上傳 CSR      │    │ 5. 建立 Profile  │
│    + 私鑰        │    │ 3. 核發證書(.cer) │◀───│    (包含證書)    │
│                 │◀───│ 4. 下載證書       │    │                 │
│ 6. 安裝證書      │    │                  │    │ 7. 下載 Profile  │
│    與私鑰配對    │    │                   │    │                 │
└─────────────────┘    └──────────────────┘    └─────────────────┘

流程說明

  1. Mac Keychain: 產生 CSR (Certificate Signing Request) 和私鑰
  2. Apple Developer Portal: 上傳 CSR,核發證書 (.cer)
  3. Mac Keychain: 安裝證書,與私鑰配對
  4. Apple Developer Portal: 使用證書建立 Provisioning Profile
  5. Mac: 安裝 Provisioning Profile 到系統

關鍵要點

  • 私鑰永遠不會離開 Mac,這是安全性的核心
  • 證書必須與私鑰配對才能用於簽名
  • Provisioning Profile 包含證書資訊,必須與實際證書匹配
  • Apple ID 必須一致,否則 Keychain 會拒絕安裝

🚨 iOS 上架實際問題與解決方案

完成上述設定後,我們滿懷信心地執行了第一次 iOS 建置。一切看起來都很完美:證書已安裝、Provisioning Profile 已配置、GitHub Secrets 已設定。然而,現實給了我們一個響亮的耳光...

問題 1:證書類型的致命陷阱

我們以為一切都設定完美,興奮地執行了第一次建置,結果卻迎來一個神秘的錯誤。看著 CI/CD 日誌中那串長長的證書資訊,我們困惑不已...

subject=UID=pro.modernwizard.crewup, CN=Apple Push Services: pro.modernwizard.crewup, OU=N7V3Q734KR, O=Modern Wizard OU, C=EE

這個錯誤訊息看起來很技術性,但關鍵在於 CN=Apple Push Services 這幾個字。我們最初使用的是 Apple Push Services 證書,但 iOS 上架需要的是 Apple Distribution 證書。這是一個常見的混淆點,也是我們遇到的第一個陷阱。

問題分析

Apple Developer Portal 中有多種證書類型,每種都有特定用途:

  • Apple Push Services: 僅用於推送通知服務
  • Apple Distribution: 用於 App Store 上架和 TestFlight 分發
  • iPhone Developer: 用於開發測試

解決方案

  1. 重新申請正確的證書類型

    • 在 Apple Developer Portal 中選擇 "Apple Distribution" 而非 "Apple Push Services"
    • 使用相同的 CSR 重新申請證書
  2. 驗證證書類型

    # 檢查證書內容
    openssl pkcs12 -in ios_distribution.p12 -nokeys -passin pass:"YOUR_PASSWORD" | grep "subject"
    
  3. 重新匯出 .p12 檔案

    • 在 Keychain Access 中找到正確的 "Apple Distribution" 證書
    • 右鍵 > Export > Personal Information Exchange (.p12)
    • 設定密碼並記住

問題 2:最隱密的敵人 - 0 valid identities found

解決了證書類型的問題後,我們滿懷信心地再次執行了建置,結果卻迎來了一個更神秘的錯誤:

0 valid identities found

這個錯誤訊息幾乎沒有提供任何線索。我們的證書和 Provisioning Profile 看起來都沒問題,但 CI/CD 環境就是找不到有效的簽名身份。在花了數小時追查後,我們終於發現了問題的根源,一個非常隱密卻極其常見的陷阱:開發者帳號不匹配。

問題分析

我們發現,私鑰是在本機產生的,永遠不會離開建立 CSR 的那台 Mac。問題在於:

因為私鑰被鎖在 A 帳號的鑰匙圈 (Keychain) 裡,所以當我們試圖安裝屬於 B 帳號的憑證時,系統根本無法將兩者配對,導致簽名身份無效。

為什麼會發生這個問題

私鑰是在本機產生的,永遠不會離開建立 CSR 的那台 Mac。這是導致 Apple ID 不匹配時出現「找不到私鑰」問題的根本原因。當您使用不同的 Apple ID 登入 Mac 時,Keychain 會將私鑰與該 Apple ID 關聯,導致證書無法正確配對。

具體表現

  • 雙擊 .cer 文件沒有反應
  • 手動拖拽到 Keychain Access 失敗
  • security import 命令執行成功但證書不顯示
  • security find-identity 找不到有效的簽名身份

解決步驟

  1. 確認正確的 Apple ID: 檢查 Apple Developer Portal 中實際使用的帳號
  2. 在 Mac 上登出錯誤帳號: 系統偏好設定 → Apple ID → 登出
  3. 登入正確的 Apple ID: 使用與 Developer Portal 相同的帳號登入
  4. 重新產生 CSR: 在正確的帳號環境下建立新的 Certificate Signing Request
  5. 重新申請證書: 使用新的 CSR 在 Developer Portal 申請證書
  6. 驗證證書安裝: 確認證書能正確顯示在 Keychain Access 中

重要提醒

  • 必須使用與 Apple Developer Portal 相同的 Apple ID 登入 Mac
  • CSR 必須在目標 Mac 上產生,且該 Mac 必須登入正確的 Apple ID
  • 證書的私鑰會自動存儲在登入帳號的 Keychain 中

驗證方法

# 檢查 Keychain 中的證書
security find-identity -v -p codesigning

# 應該看到類似這樣的輸出:
# 1) ABC1234567890ABCDEF1234567890ABCDEF123456 "Apple Distribution: Your Company OU"

問題 3:連鎖反應 - Provisioning Profile 的背叛

解決了證書問題後,我們以為終於可以順利建置了。但命運再次捉弄了我們,這次的錯誤訊息更加明確:

Provisioning profile "Crew Up Distribution" doesn't include signing certificate "Apple Distribution: Modern Wizard OU (***)"

這個錯誤訊息清楚地告訴我們問題所在:Provisioning Profile 不包含我們的簽名證書。原來,當我們更新證書後,Provisioning Profile 也需要同步更新。這就像是一個連鎖反應,一個問題解決了,卻引發了另一個問題。

問題分析

當我們更新了證書後,Provisioning Profile 也需要重新產生以包含新的證書。

為什麼會發生這個問題

Provisioning Profile 是一個包含證書、App ID 和設備資訊的設定檔。當您建立新的證書時,舊的 Provisioning Profile 仍然指向舊的證書,因此需要更新以包含新的證書。

解決方案

  1. 編輯 Provisioning Profile

    • 在 Apple Developer Portal 中編輯現有的 Provisioning Profile
    • 選擇新產生的 Apple Distribution 證書
    • 儲存並重新下載
  2. 更新 GitHub Secrets

    # 轉換新的 Provisioning Profile 為 Base64
    cd ~/Library/MobileDevice/Provisioning\ Profiles
    base64 -i YOUR_NEW_PROFILE.mobileprovision | pbcopy
    
    • 將新的 Base64 內容更新到 IOS_PROVISIONING_PROFILE Secret
  3. 驗證 Profile 內容

    # 檢查 Profile 包含的證書
    security cms -D -i YOUR_PROFILE.mobileprovision | grep -A 5 "DeveloperCertificates"
    

問題 4:最後一哩路的阻礙 - Fastlane 認證困境

經過重重困難,我們終於成功建置了 iOS App!但就在最後一步上傳到 TestFlight 時,又遇到了新的挑戰:

Missing password for user ***, and running in non-interactive shell

這個錯誤讓我們意識到,CI/CD 環境無法像我們在本地一樣互動式輸入密碼。原來,標準的 Apple ID 登入受雙重認證 (2FA) 保護,這在非互動式的 CI/CD 環境中是無法操作的。

問題分析

CI/CD 環境中無法互動式輸入密碼,需要使用 App-Specific Password 或 API Key。

為什麼會發生這個問題

標準的 Apple ID 登入受雙重認證 (2FA) 保護,這在非互動式的 CI/CD 環境中是無法操作的。因此需要使用 App-Specific Password,這是一個專門為自動化工具產生的密碼,不受 2FA 限制。

解決方案

  1. 確認 App Specific Password

  2. 修正 Fastfile 設定

    # Fastfile 中的修正
    upload_to_testflight(
      skip_waiting_for_build_processing: true,
      username: ENV["FASTLANE_USER"],
      team_id: ENV["APPLE_TEAM_ID"],
      app_identifier: "pro.modernwizard.crewup"
    )
    
  3. 確認 GitHub Actions 環境變數

    # GitHub Actions 環境變數
    env:
      FASTLANE_USER: ${{ secrets.APPLE_ID }}
      FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
      APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
      APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
    
  4. 驗證 Secrets 設定

    • 確認 APPLE_ID 是正確的 Apple ID email
    • 確認 APPLE_ID_PASSWORD 是 App Specific Password (格式:xxxx-xxxx-xxxx-xxxx)
    • 確認 APPLE_TEAM_ID 是正確的 Team ID

🔧 完整的 iOS 上架流程

1. 證書管理最佳實踐

證書類型區分

  • Apple Push Services: 僅用於推送通知
  • Apple Distribution: 用於 App Store 上架
  • iPhone Developer: 用於開發測試

私鑰管理

  • 私鑰必須與證書配對存在於 Keychain 中
  • CSR 必須在目標 Mac 上生成
  • 證書導出時必須包含私鑰

2. CI/CD 環境配置

環境變數設定

# .github/workflows/ci-cd.yml
- name: Build and Deploy iOS to TestFlight
  run: |
    echo "🔧 Environment variables:"
    echo "APPLE_ID: $APPLE_ID"
    echo "APPLE_TEAM_ID: $APPLE_TEAM_ID"
    echo "APPLE_ID_PASSWORD: [HIDDEN]"
    echo ""
    echo "📱 Running Fastlane beta..."
    cd ios
    bundle exec fastlane beta --verbose
  env:
    APPLE_ID: ${{ secrets.APPLE_ID }}
    APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
    APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}

GitHub Secrets 設定

  • APPLE_ID: 您的 Apple ID email
  • APPLE_ID_PASSWORD: App-Specific Password
  • APPLE_TEAM_ID: 您的 Team ID
  • IOS_CERTIFICATE: Base64 編碼的 .p12 證書
  • IOS_CERTIFICATE_PASSWORD: 證書密碼
  • IOS_PROVISIONING_PROFILE: Base64 編碼的 .mobileprovision

3. Fastlane 配置優化

Appfile 設定

# ios/fastlane/Appfile
apple_id(ENV["APPLE_ID"])
team_id(ENV["APPLE_TEAM_ID"])
app_identifier("com.yourcompany.app")

Fastfile 建置配置

# ios/fastlane/Fastfile
build_app(
  scheme: "production",
  workspace: workspace_path,
  configuration: "Release-production",
  export_method: "app-store",
  output_directory: output_dir,
  output_name: "Runner.ipa",
  clean: true,
  silent: false,
  include_bitcode: false,
  include_symbols: true,
  export_options: {
    provisioningProfiles: {
      "com.yourcompany.app" => "Your App Distribution"
    },
    signingStyle: "manual",
    teamID: ENV["APPLE_TEAM_ID"],
    method: "app-store"
  }
)

📊 除錯過程中的學習

1. 證書管理的重要性

  • Apple Push Services vs Apple Distribution 的區別
  • Apple ID 帳號一致性: 必須使用相同的 Apple ID 登入 Mac 和 Developer Portal
  • 私鑰必須與證書配對存在於 Keychain 中
  • CSR 必須在目標 Mac 上生成,且該 Mac 必須登入正確的 Apple ID

2. CI/CD 環境的限制

  • 無法進行互動式操作
  • 需要使用環境變數傳遞敏感資訊
  • Fastlane 有特定的環境變數命名規範

3. Apple 生態系統的複雜性

  • 證書、Provisioning Profile、Bundle ID 三者必須完全匹配
  • 任何一個環節出錯都會導致整個流程失敗

🎭 開發者常犯的錯誤

  1. 混淆證書類型: Push Services 證書不能用於 App Store 上架
  2. Apple ID 帳號不匹配: 登入 Mac 的 Apple ID 與 Developer Portal 使用的不同
  3. 忽略私鑰管理: 只下載證書而忘記導出私鑰
  4. Provisioning Profile 過期: 更新證書後忘記更新 Profile
  5. CI/CD 認證設定錯誤: 使用錯誤的環境變數名稱

🛠️ Base64 轉換實用工具

在 Crew Up 專案中,我們經常需要將 iOS 憑證轉換為 Base64 格式。以下是我們實際使用的工具:

快速轉換指令集合

通用 Base64 轉換

# 轉換並複製到剪貼簿
base64 -i filename.ext | pbcopy

# 轉換並顯示內容
base64 -i filename.ext

# 轉換並儲存到檔案
base64 -i filename.ext > filename_base64.txt

# 驗證轉換結果
base64 -d filename_base64.txt > verify.ext
file verify.ext

批次處理多個檔案

# 批次轉換目錄中的所有檔案
for file in *.p12 *.mobileprovision *.plist; do
    if [ -f "$file" ]; then
        echo "=== Converting: $file ==="
        base64 -i "$file" | pbcopy
        echo "Base64 content copied to clipboard for: $file"
        echo "Press Enter to continue with next file..."
        read
    fi
done

檢查 Base64 內容

# 檢查 Base64 字串長度
echo "YOUR_BASE64_STRING" | wc -c

# 檢查 Base64 字串是否有效
echo "YOUR_BASE64_STRING" | base64 -d > /dev/null && echo "Valid Base64" || echo "Invalid Base64"

# 預覽 Base64 內容(前 100 字元)
echo "YOUR_BASE64_STRING" | head -c 100

自動化腳本範例

#!/bin/bash
# iOS 憑證 Base64 轉換腳本

echo "🔐 iOS Certificate Base64 Converter"
echo "=================================="

# 檢查 .p12 檔案
if [ -f "ios_distribution.p12" ]; then
    echo "📱 Converting iOS Distribution Certificate..."
    base64 -i ios_distribution.p12 | pbcopy
    echo "✅ Certificate Base64 copied to clipboard"
else
    echo "❌ ios_distribution.p12 not found"
fi

# 檢查 Provisioning Profile
PROFILE_DIR="$HOME/Library/MobileDevice/Provisioning Profiles"
if [ -d "$PROFILE_DIR" ]; then
    LATEST_PROFILE=$(ls -t "$PROFILE_DIR"/*.mobileprovision 2>/dev/null | head -1)
    if [ -n "$LATEST_PROFILE" ]; then
        echo "📋 Converting latest Provisioning Profile..."
        base64 -i "$LATEST_PROFILE" | pbcopy
        echo "✅ Profile Base64 copied to clipboard"
    else
        echo "❌ No Provisioning Profiles found"
    fi
fi

echo "🎉 Conversion completed!"

🔮 下一步:App Store 上架

目前我們的 CI/CD 流程已經通過了證書驗證和建置階段,TestFlight 上傳也已經配置完成。在下一篇文章中,我將分享:

  1. App-Specific Password 的正確設定方法
  2. App Store Connect API Key 的替代方案
  3. 最終的 CI/CD 成功配置
  4. 從 TestFlight 到 App Store 的完整流程

🚨 意外的插曲:GitHub 服務問題

就在我們準備測試最終的 iOS 上架流程時,遇到了意外的挑戰:GitHub 服務出現了問題

遇到的問題

  • Webhooks 服務異常: GitHub Status 頁面顯示 Webhooks 服務正在調查中
  • CI/CD 觸發失敗: 推送代碼後 GitHub Actions 沒有自動觸發
  • 服務部分中斷: 雖然大部分 GitHub 服務正常,但 Webhooks 的異常影響了自動化流程

我們的應對策略

  1. 手動觸發 Workflow: 通過 GitHub Actions 頁面手動執行 CI/CD
  2. 創建觸發 Commit: 添加臨時檔案來強制觸發新的 workflow
  3. 監控服務狀態: 持續關注 GitHub Status 頁面

開發者的韌性

這個意外的服務問題提醒我們:在軟體開發的世界裡,不僅要處理代碼問題,還要應對外部服務的不可預測性。真正的開發者需要具備:

  • 問題解決能力: 當自動化工具失效時,能夠找到替代方案
  • 耐心與韌性: 面對外部服務問題時保持冷靜
  • 備用計劃: 永遠準備好 Plan B

📅 Day 26 預告

由於 GitHub 服務問題,明天的內容將有所調整:

如果 GitHub 服務恢復正常

  • 完成 iOS TestFlight 上架的最終測試
  • 分享完整的成功案例和最佳實踐
  • 提供從 TestFlight 到 App Store 的完整指南

如果 GitHub 服務仍有問題

  • 轉向 AI Agent 開發主題
  • 分享如何建立智能化的開發助手
  • 探索 AI 在軟體開發中的應用

無論哪種情況,我們都會繼續我們的開發之旅,因為真正的開發者從不因為外部問題而停止學習和進步

💭 結語

iOS 上架是一個充滿挑戰的過程,但每一次錯誤都是學習的機會。今天的分享希望能幫助其他開發者避免我們遇到的陷阱。

記住: 在軟體開發的世界裡,沒有什麼是「應該很簡單」的。每一個看似簡單的步驟背後,都有無數的細節需要處理。

更重要的是: 當外部服務出現問題時,真正的開發者會展現出韌性和適應能力,找到解決方案並繼續前進。

下一步

明天(Day 26),我們將根據 GitHub 服務狀況,分享 iOS 上架的最終解決方案或探索 AI Agent 開發的新領域。

期待與您在 Day 26 相見!


📋 相關資源

📝 專案資訊

  • 專案名稱: Crew Up!
  • 開發日誌: Day 25 - iOS 上架挑戰實戰:從證書錯誤到 TestFlight 部署
  • 文章日期: 2025-10-09
  • 技術棧: iOS, Fastlane, GitHub Actions, Apple Developer Portal, TestFlight, Clean Architecture

上一篇
Day 24 - Android 建置與簽名實作:從 AAB 到自動化部署
系列文
我的 Flutter 進化論:30 天打造「Crew Up!」的架構之旅25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言