أتمتة إصدارات App Store باستخدام Fastlane Deliver
أتمتة إصدارات App Store باستخدام Fastlane Deliver
رفع تطبيق iOS يدوياً إلى App Store Connect هو سير عمل متكرر وعرضة للأخطاء: تصدير الأرشيف، وملء ملاحظات الإصدار، وضبط رقم البناء، وتفعيل مجموعات TestFlight، ثم أخيراً النقر على Submit for Review. Fastlane Deliver (إجراء deliver) يؤتمت كل هذه الخطوات من سطر الأوامر، مما يجعل من السهل ربط العملية بالكامل في خط أنابيب CI/CD مُشغَّل بعلامة Git أو دمج إلى فرع الإصدار.
ما الذي يفعله Fastlane Deliver
إجراء deliver هو أداة Fastlane الرسمية للتفاعل مع App Store Connect. يمكنه:
- رفع ملف
.ipaموقَّع إلى App Store Connect باستخدام بروتوكول Transporter - دفع البيانات الوصفية المحلية للتطبيق (الأوصاف والكلمات المفتاحية وملاحظات الإصدار وعناوين URL للدعم)
- رفع لقطات الشاشة ومقاطع الفيديو التجريبية لكل حجم جهاز ولغة
- توزيع البناء على مجموعات TestFlight الداخلية أو الخارجية تلقائياً
- تقديم البناء لمراجعة التطبيق بعلامة واحدة
- تخطي التقديم والرفع فقط، مع السماح للبشر بتشغيل المراجعة من واجهة الويب
.p8.المصادقة باستخدام مفتاح App Store Connect API
قبل استدعاء deliver، يجب إخبار Fastlane بمفتاح API المراد استخدامه. النهج الأنظف هو إجراء app_store_connect_api_key، الذي يُعيد كائن مفتاح قابلاً لإعادة الاستخدام تمرره إلى الإجراءات اللاحقة.
تهيئة مفتاح API في مسار Fastlane
# fastlane/Fastfile
lane :upload_to_store do
# تحميل مفتاح App Store Connect API من متغيرات بيئة CI
api_key = app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"], # مثال: "ABCD1234EF"
issuer_id: ENV["ASC_ISSUER_ID"], # UUID من بوابة ASC
key_content: ENV["ASC_KEY_CONTENT"], # محتوى ملف .p8 (base64 أو خام)
is_key_content_base64: true,
duration: 1200, # TTL للرمز بالثواني (الحد الأقصى 1200)
in_house: false, # true فقط لـ Apple Developer Enterprise
)
deliver(
api_key: api_key,
ipa: "build/Runner.ipa",
skip_metadata: false,
skip_screenshots: true,
submit_for_review: false,
automatic_release: false,
force: true, # تخطي معاينة تقرير HTML
precheck_include_in_app_purchases: false,
)
end
.p8 في Fastfile. خزِّنه كسر CI مُشفَّر بترميز base64 (مثل base64 AuthKey_ABCD1234EF.p8) واضبط is_key_content_base64: true. في GitHub Actions، أضفه كسر مستودع مُشفَّر وارجع إليه عبر ENV["ASC_KEY_CONTENT"].التوزيع على مجموعات TestFlight الخارجية
بعد أن يجتاز الملف الثنائي قائمة انتظار معالجة Apple (عادةً 10-15 دقيقة)، يمكنك إضافته تلقائياً إلى مجموعة TestFlight خارجية. استخدم إجراء pilot (المعروف أيضاً بـ testflight) أو مرر معاملات التوزيع مباشرةً إلى deliver.
مسار CI كامل: البناء والتوقيع والرفع والتوزيع على TestFlight
# fastlane/Fastfile
lane :beta do
api_key = app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_content: ENV["ASC_KEY_CONTENT"],
is_key_content_base64: true,
)
# زيادة رقم البناء من أحدث بناء TestFlight
increment_build_number(
build_number: app_store_build_number(
api_key: api_key,
live: false,
) + 1,
xcodeproj: "ios/Runner.xcodeproj",
)
# بناء وتوقيع Flutter IPA
sh "flutter build ipa --release " \
"--export-options-plist=ios/ExportOptions.plist"
# الرفع إلى TestFlight والتوزيع على المجموعة الخارجية
pilot(
api_key: api_key,
ipa: "build/ios/ipa/Runner.ipa",
distribute_external: true,
groups: ["External Beta Testers"],
notify_external_testers: true,
changelog: ENV["RELEASE_NOTES"] || "Bug fixes and improvements.",
beta_app_review_info: {
contact_email: "qa@example.com",
contact_first_name: "QA",
contact_last_name: "Team",
contact_phone: "+1-555-0100",
demo_account_name: "demo@example.com",
demo_account_password: "DemoPass123!",
notes: "Use demo account to test all flows.",
},
skip_waiting_for_build_processing: false,
)
end
التقديم لمراجعة التطبيق
للانتقال مباشرةً من CI إلى قائمة انتظار مراجعة التطبيق، اضبط submit_for_review: true داخل استدعاء deliver. ادمج هذا مع automatic_release: false للإبقاء على إنسان في حلقة القرار النهائي للنشر، أو اضبطه على true للإصدار الآلي الكامل بمجرد موافقة Apple.
submit_for_review: true في CI يعني أن كل بناء ناجح في ذلك المسار سيدخل قائمة انتظار مراجعة التطبيق. بوِّب هذا المسار خلف نمط علامة محمية (مثل v*.*.*-rc) أو مشغِّل CI يدوي لتجنب تقديم بنيات التطوير للمراجعة عن طريق الخطأ.ربط المسار في خط أنابيب GitHub Actions CI
يُشغِّل سير عمل GitHub Actions النموذجي مسار الإصدار عند دفع علامة إصدار. محتوى .p8 والأسرار الأخرى مخزَّنة كأسرار مستودع وتُحقَن في وقت التشغيل.
سير عمل GitHub Actions (.github/workflows/release.yml)
# .github/workflows/release.yml
name: App Store Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+" # يُشغَّل عند مثل v1.4.0
jobs:
release:
runs-on: macos-14 # صورة Xcode 15
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.22.0"
channel: stable
- name: Install Ruby & Fastlane
run: |
gem install bundler --no-document
bundle install
- name: Install Flutter dependencies
run: flutter pub get
- name: Install CocoaPods
run: cd ios && pod install --repo-update
- name: Run Fastlane beta lane
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_CONTENT: ${{ secrets.ASC_KEY_CONTENT }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
RELEASE_NOTES: "Version ${{ github.ref_name }} released."
run: bundle exec fastlane beta
هيكل البيانات الوصفية لـ Fastlane Deliver
عند ضبط skip_metadata: false، يتوقع Fastlane وجود مجلد fastlane/metadata/ بتخطيط محدد. يتيح ذلك التحكم في إصدارات كل محتوى App Store جنباً إلى جنب مع الكود:
metadata/en-US/name.txt— اسم التطبيق للغة المحددةmetadata/en-US/description.txt— الوصف الكامل لـ App Storemetadata/en-US/keywords.txt— كلمات مفتاحية مفصولة بفواصلmetadata/en-US/release_notes.txt— الجديد في هذا الإصدارmetadata/en-US/support_url.txt— رابط URL للدعمmetadata/review_information/— معلومات تواصل مراجعة التطبيق وبيانات اعتماد العرض التجريبي
fastlane deliver init مرةً واحدة لتنزيل بيانات App Store الوصفية الحالية إلى هيكل المجلدات الصحيح. أودِع مجلد fastlane/metadata/ بالكامل في نظام التحكم بالإصدارات حتى تتم مراجعة ملاحظات الإصدار والأوصاف في طلبات الدمج تماماً مثل تغييرات الكود.ملخص
يحوِّل Fastlane Deliver عملية تقديم App Store من سير عمل يدوي متعدد الخطوات عبر واجهة رسومية إلى أمر طرفي واحد. النقاط الرئيسية التي يجب تذكرها هي: استخدام مفتاح App Store Connect API (ليس اسم المستخدم/كلمة المرور أبداً) مخزَّناً كأسرار CI؛ استخدام deliver لرفع البيانات الوصفية والملف الثنائي؛ استخدام pilot لتوزيع TestFlight مع مجموعات المختبرين الخارجيين؛ وبوابة علامة submit_for_review خلف علامات محمية أو مشغِّلات يدوية لمنع التقديمات العرضية. مع هذا الإعداد، تُنتج كل علامة Git تلقائياً بناء TestFlight بدون أي تدخل يدوي.