הגדרת CI/CD לאפליקציות iOS באמצעות Fastlane
אנו מגדירים עבורך CI/CD באמצעות Fastlane—התקן דה פקטו לאוטומציית בנייה של iOS מחוץ למערכת האקולוגית של Apple. Fastlane פועל על כל CI: GitHub Actions, GitLab CI, Jenkins, Bitrise. היתרון העיקרי שלו על פני Xcode Cloud הוא שליטה מלאה בכל שלב והיכולת להריץ את אותן פקודות מקומית ש-CI מבצע.
פעם עבדנו על פרויקט שבו בניית CI ארכה 40 דקות עקב חוסר caching ותצורת code signing לא אופטימלית. לאחר הגדרת Fastlane עם Match ו-caching מתאים, הזמן ירד ל-15 דקות—חיסכון של מעל 60% מזמן הצוות. אוטומציה עם Fastlane מפחיתה את זמן הבנייה ב-40% וחוסכת עד $2000 לחודש עבור צוות של חמישה מפתחים. הצוות שלנו, עם 5 שנות ניסיון ולמעלה מ-40 פרויקטים שהושלמו, מבטיח תצורה אמינה.
למה Code Signing הוא כאב ראש ב-CI
iOS דורש provisioning profile ותעודה תקפים עבור כל בנייה שאינה על סימולטור. על מכונה מקומית, אלה נמצאים ב-Keychain. על שרת CI—הם לא. ללא הגדרה נכונה, fastlane נכשל בעקביות עם Code Signing Error: No profiles for bundle ID found.
fastlane match פותר זאת: כל התעודות וה-profiles מאוחסנים מוצפנים במאגר Git נפרד (או S3/Google Cloud). ב-CI, פקודה אחת bundle exec fastlane match adhoc מורידה ומתקינה את ה-profile הנדרש. ה-passphrase עבור match הוא משתנה סודי של CI.
התכנית:
Git-репозиторий (зашифрованный) ←→ fastlane match ←→ Apple Developer Portal ↓ CI Keychain (временный) עבור צוות של 5+ מפתחים, match במצב readonly ב-CI ובמצב רגיל על מכונות מפתחים הוא התצורה הסטנדרטית. זה מונע התנגשויות במהלך עבודה מקבילה.
כיצד להגדיר Fastlane לבנייה ופריסה
מבנה של Fastfile:
default_platform(:ios)
platform :ios do
before_all do
setup_ci if ENV['CI'] # Создаёт временный Keychain на CI
end
lane :test do
run_tests(
scheme: "MyApp",
devices: ["iPhone 15", "iPhone SE (3rd generation)"],
code_coverage: true
)
end
lane :beta do
match(type: "adhoc", readonly: true)
increment_build_number(
build_number: ENV["CI_PIPELINE_ID"] || Time.now.to_i.to_s
)
build_ios_app(
scheme: "MyApp",
configuration: "Release",
export_method: "ad-hoc"
)
firebase_app_distribution(
app: ENV["FIREBASE_APP_ID"],
groups: "qa-team",
release_notes: changelog_from_git_commits(commits_count: 5)
)
end
lane :release do
match(type: "appstore", readonly: true)
increment_build_number(build_number: latest_testflight_build_number + 1)
build_ios_app(scheme: "MyApp", configuration: "Release", export_method: "app-store")
upload_to_testflight(skip_waiting_for_build_processing: true)
slack(message: "New build uploaded to TestFlight!", channel: "#releases")
end
end
Git-репозиторий (зашифрованный) ←→ fastlane match ←→ Apple Developer Portal ↓ CI Keychain (временный) יוצר keychain זמני בתוך עבודת ה-CI. בלעדיו, fastlane מנסה לפתוח את keychain המשתמש, שאינו זמין ב-CI ללא ראש.
כיצד להגדיר Fastlane ב-5 שלבים
- התקן את Fastlane ואתחל את הפרויקט:
match, ולאחר מכןdefault_platform(:ios) platform :ios do before_all do setup_ci if ENV['CI'] # Создаёт временный Keychain на CI end lane :test do run_tests( scheme: "MyApp", devices: ["iPhone 15", "iPhone SE (3rd generation)"], code_coverage: true ) end lane :beta do match(type: "adhoc", readonly: true) increment_build_number( build_number: ENV["CI_PIPELINE_ID"] || Time.now.to_i.to_s ) build_ios_app( scheme: "MyApp", configuration: "Release", export_method: "ad-hoc" ) firebase_app_distribution( app: ENV["FIREBASE_APP_ID"], groups: "qa-team", release_notes: changelog_from_git_commits(commits_count: 5) ) end lane :release do match(type: "appstore", readonly: true) increment_build_number(build_number: latest_testflight_build_number + 1) build_ios_app(scheme: "MyApp", configuration: "Release", export_method: "app-store") upload_to_testflight(skip_waiting_for_build_processing: true) slack(message: "New build uploaded to TestFlight!", channel: "#releases") end end. - צור מאגר Git מוצפן עבור Match והגדר גישה.
- תאר lanes ב-Fastfile: לפחות
setup_ci,bundle init,fastlane init. - הגדר את סקריפט ה-CI (GitHub Actions, GitLab CI, או אחר) על runner של macOS.
- הרץ בדיקה על CI ונתח שגיאות.
מספר בנייה
test ללא ארגומנטים קורא את המספר הנוכחי מ-beta ומגדיל ב-1. אבל עם עבודות CI מקבילות, יכולות להתרחש התנגשויות—שני PRs שבונים בו-זמנית מקבלים את אותו מספר. פתרון: השתמש ב-release (GitLab) או increment_build_number (GitHub Actions) כמספר הבנייה. זה מבטיח ייחודיות.
השוואה: Fastlane לעומת Xcode Cloud
| קריטריון | Fastlane | Xcode Cloud |
|---|---|---|
| שליטה בשלבים | מלאה | מוגבלת |
| תמיכה במערכות CI | כל מערכת (GitHub Actions, GitLab CI, Jenkins) | Apple בלבד |
| ביצוע מקומי | כן, ללא שינוי | לא, רק ענן |
| עלות | חינם (קוד פתוח) | כלול בתוכנית Apple Developer |
| מורכבות הגדרה | גבוהה יותר (גמישות) | נמוכה יותר (יכולות מוגבלות) |
Fastlane עדיף לפרויקטים הדורשים pipelines מותאמים אישית ואינטגרציה עם שירותים חיצוניים (Firebase, Slack). Xcode Cloud מתאים לפרויקטים פשוטים בתוך המערכת האקולוגית של Apple.
אינטגרציה עם GitHub Actions
---
- name: Run Fastlane
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_AUTH }}
FIREBASE_APP_ID: ${{ secrets.FIREBASE_APP_ID }}
FIREBASE_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }}
run: bundle exec fastlane beta
---ה-runner חייב להיות macOS (Info.plist). Runners של Linux אינם מתאימים לבניית iOS מכיוון ש-Xcode פועל רק על macOS.
Caching של תלויות
השלב הארוך ביותר הוא CI_PIPELINE_ID או github.run_number. ב-GitHub Actions, אנו שומרים במטמון:
---
- name: Cache CocoaPods
uses: actions/cache@v4
with:
path: Pods
key: ${{ runner.os }}-pods-${{ hashFiles('Podfile.lock') }}
זה חוסך 3–8 דקות לכל ריצה כאשר - name: Run Fastlane Beta env: MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_AUTH }} FIREBASE_APP_ID: ${{ secrets.FIREBASE_APP_ID }} FIREBASE_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }} run: bundle exec fastlane beta לא השתנה. אם אתה משתמש ב-Swift Package Manager, שמור במטמון את runs-on: macos-14 באופן דומה.
טעויות נפוצות בהגדרת Fastlane
| שגיאה | סיבה | פתרון |
|---|---|---|
pod install |
Match לא התקין profile | בדוק את ה-passphrase והגישה למאגר Match |
swift package resolve |
נתיב שגוי לתלויות | ודא ש-- name: Cache CocoaPods uses: actions/cache@v4 with: path: Pods key: ${{ runner.os }}-pods-${{ hashFiles('Podfile.lock') }} או Podfile.lock הופעל |
.build |
התעודה פגה | חדש דרך Match: Code Signing Error: No profiles for bundle ID found |
כיצד לנתח code signing על CI?
לניפוי מקומי, הרץ `fastlane match development` וודא שה-keychain נוצר. על CI, הפעל רישום: `fastlane beta --verbose`.מה כלול בעבודה
אנו מספקים חבילה מלאה:
- תצורת Fastlane: Fastfile, Matchfile, Appfile
- סקריפטים של CI (GitHub Actions / GitLab CI / וכו') עם caching
- הגדרת Match: מאגר תעודות מוצפן
- תיעוד להרצה ותחזוקה
- הדרכת צוות (שעה מקוונת)
- אחריות לתפקוד למשך 30 יום
- תמיכה בשינויי תעודות או מכשירים
צור קשר כדי לדון בהגדרת CI/CD לפרויקט שלך. הזמן תצורת Fastlane וקבל pipeline מוכן תוך 3–5 ימים.
לוחות זמנים
הגדרת Fastlane בסיסית עם lanes של error: no such module 'MyModule', pod install, ו-swift package resolve על GitHub Actions: 3–5 ימים. תצורה מלאה עם lane של Expired provisioning profile, changelog, הודעות Slack, caching, ותמיכה במספר schemes: 1–2 שבועות. המחיר מחושב באופן אישי לפי מורכבות הפרויקט.
— Fastlane — פרויקט קוד פתוח.







