OOZOU
تواصلوا معنا
العودة إلى المدونة

أتمتة التوثيق (Notarization) بالسكربتات لتوزيع تطبيقات macOS

أتمتة توثيق تطبيقات macOS التي تُوزَّع بصيغة DMG

7 يونيو 2020
8 دقائق للقراءة
أتمتة التوثيق (Notarization) بالسكربتات لتوزيع تطبيقات macOS

ما هو التوثيق (Notarization)؟

التوثيق نظام آلي أنشأته Apple يفحص برمجيات macOS لديكم بحثًا عن محتوى خبيث ومشكلات في التوقيع الرقمي للكود (code signing). وهو ليس مراجعة يدوية للتطبيق كتلك التي يجريها المراجعون في متجري Mac App Store وiOS App Store. الغرض من التوثيق منح المستخدمين ثقة أكبر بأن برمجياتكم حظيت بموافقة Apple. وفي التطبيقات الموزعة عبر Mac App Store، يتم ذلك تلقائيًا ضمن عملية التقديم إلى المتجر. أما المطورون الذين يريدون توزيع برمجيات Mac خارج Mac App Store، فعليهم توثيقها قبل أن تعمل على macOS Catalina. يمكنكم بسهولة أرشفة تطبيقكم وتصديره وتوثيقه يدويًا عبر Xcode Organizer، لكن أتمتة العملية توفر طريقة أكثر مرونة وسلاسة لتوزيع البرمجيات. **ماذا يحدث إن لم أوثّق تطبيقي؟**إن لم توثّقوا تطبيقكم، فسيستقبل المستخدمين عند تنزيله رسالة من Gatekeeper تقول إن Apple لم تتمكن من فحص البرمجية بحثًا عن محتوى خبيث، ولن تكون هناك طريقة واضحة لفتح التطبيق. ولفتحه، سيحتاج المستخدم إما 1) إلى النقر بزر الفأرة الأيمن على التطبيق، فتظهر قائمة فيها خيار لفتحه رغم ذلك، أو 2) إلى الذهاب صراحةً إلى إعدادات الأمان والسماح بفتح التطبيق. لكن لا شيء في رسالة Gatekeeper يشير إلى أي من هذين الخيارين، لذا لن يتمكن معظم المستخدمين ببساطة من استخدام تطبيقكم.

المتطلبات

- يتطلب التوثيق Xcode 10 أو أحدث. إذا كانت لديكم عدة إصدارات مثبّتة من Xcode، فاستخدموا الأمر xcode-select للتأكد من أنكم تستخدمون Xcode 10.0 أو أحدث قبل التوثيق. يمكنكم توثيق تطبيقات بُنيت بإصدار < Xcode 10.0، لكن يجب استخدام Xcode 10 أو أحدث لإجراء التوثيق نفسه. - يجب أن يكون الـ hardened runtime مفعّلًا في تطبيقكم (Xcode Build Settings -> Enable hardened runtime) حتى يمكن توثيقه. - يجب أن يكون تطبيقكم موقّعًا بشهادة Developer ID. (المصدر)

الأرشفة

لتوثيق تطبيقكم، عليكم أولًا إنشاء الملف النهائي للتسليم، مثل dmg أو pkg. هذا هو الملف النهائي الذي سترسلونه إلى Apple للتوثيق. يغطي هذا العرض العملية كاملة، من بناء التطبيق حتى إتمام التوثيق. وللبدء، نحتاج أولًا إلى أرشفة التطبيق:

xcodebuild archive \
 -project YourProject.xcodeproj \
 -scheme "YourScheme" \
 -configuration Release \
 -archivePath archive/result.xcarchive
<strong>language-bash</strong>

هذا أمر xcodebuild بسيط يبني تطبيقكم ويؤرشفه بإعداد Release، ويُخرج ملف xcarchive باسم result.xcarchive داخل مجلد اسمه "archive".

التصدير

بعد ذلك، لنصدّر الأرشيف كملف تنفيذي بامتداد .app:

xcodebuild archive \
 -archivePath archive/result.xcarchive \
 -exportArchive \
 -exportOptionsPlist exportOptions.plist \
 -exportPath yourFolder
<strong>language-bash</strong>

يصدّر هذا الأمر الأرشيف كملف تنفيذي .app. تمررون مسار ملف plist الخاص بخيارات التصدير إلى الوسيط "exportOptionsPlist". وكحد أدنى، يجب أن يحدد ملف plist طريقة التصدير التي ستستخدمونها. ولأننا نوزّع خارج Mac App Store، ستكون قيمة المفتاح "method" في ملف plist هي "developer-id". وإذا لم تكونوا تستخدمون التوقيع التلقائي للكود في Xcode، فستحتاجون أيضًا إلى تمرير مفاتيح وقيم إضافية تحدد شهادات التوقيع وprovisioning profiles. شغّلوا "xcodebuild -help" للحصول على قائمة كاملة بجميع الخيارات المتاحة لـ "exportOptionsPlist". وأخيرًا، "exportPath" هو المجلد الذي سيُصدَّر إليه ملف .app.

إنشاء ملف DMG

يمكنكم تشغيل ملف .app التنفيذي مباشرة، لكن معظم التطبيقات تُوزَّع بصيغة dmg أو pkg. في هذا المثال سننشئ ملف dmg ليكون الملف النهائي الذي نرسله إلى Apple للتوثيق. ينشئ الأمر التالي ملف dmg:

hdiutil create -format UDZO -srcfolder yourFolder YourApp.dmg
<strong>language-bash</strong>

"yourFolder" هو اسم المجلد الذي تريدون ضغطه في ملف dmg، ولأغراض هذا السكربت يجب أن يكون هو نفسه "-exportPath" في الخطوة السابقة. أما "YourApp" فهو الاسم الذي تريدون إعطاءه لملف dmg الجديد. ورغم أن ذلك خارج نطاق هذا المقال، فإن UDZO صيغة شائعة لصور الأقراص.

الرفع إلى Apple

لإرسال الملف النهائي إلى Apple للتوثيق، شغّلوا ما يلي:

requestInfo=$(xcrun altool --notarize-app \
   --file "YourApp.dmg" \
   --username "yourDeveloperAccountEmail@email.com" \
   --password "@keychain:notarization-password" \
   --asc-provider "yourAppleTeamID" \
   --primary-bundle-id "com.your.app.bundle.id")
<strong>language-bash</strong>

إليكم بعض الملاحظات: - كما هو متوقع، نمرر ملف dmg إلى الوسيط "--file". - نشغّل الأمر ونحفظ مخرجاته في المتغير $requestInfo، لأن الأمر سيُرجع معرّفًا يمكننا استخدامه للاستعلام عن حالة توثيق تطبيقنا. - كلمة المرور هي كلمة مرور خاصة بالتطبيق (app-specific password) حفظتها في سلسلة المفاتيح (keychain) كعنصر كلمة مرور باسم "notarization-password". من جهة العميل في عملية التوثيق، نرسل الملف أولًا إلى Apple للتوثيق. لكن Apple لا تخبرنا متى يكتمل التوثيق، ولمعرفة حالته علينا الاستعلام من Apple باستمرار وقراءة ردها.

قراءة استجابة $requestInfo

إذا أدخلتم كل المعلومات اللازمة أعلاه بشكل صحيح، فيُفترض أن يُرجع $requestInfo نصًا كهذا (مع قيمة RequestUUID الخاصة بكم):

No errors uploading 'YourApp.dmg'. RequestUUID = ghg99vjrghefe0-tjthty9e-42hv9-a76fiw-76oiauhfgibejrec

نحتاج إلى استخراج قيمة RequestUUID، ثم نستخدمها للاستعلام من Apple عن حالة توثيق تطبيقنا. أنشئوا سكربت ruby صغيرًا باسم uuid.rb، وأضيفوا إليه هذا السطر الوحيد:

puts "#{ARGV[0].split('= ')[1]}"
<strong>language-ruby</strong>

يأخذ هذا السطر أول وسيط يُمرَّر إلى السكربت، ويقسمه إلى مصفوفة من السلاسل النصية مستخدمًا "= " كفاصل، ثم يُرجع العنصر الثاني في المصفوفة. والآن يمكننا استخراج الـ UUID بسهولة بأمر من سطر واحد:

uuid=$(ruby uuid.rb "$requestInfo")
<strong>language-bash</strong>

الاستعلام عن حالة التوثيق

عند التوثيق يدويًا من Xcode، ترسل لكم Apple إشعارًا فوريًا (push notification) لإبلاغكم باكتمال التوثيق. أما من سطر الأوامر، فعلينا الاستعلام باستمرار حتى نكتشف أن العملية انتهت. وإليكم الطريقة:

currentStatus = "in progress"

<strong>while</strong> [[ "$currentStatus" == "in progress" ]]; <strong>do
</strong>
sleep 15

statusResponse=$(xcrun altool --notarization-info "$uuid" \
    --username "yourDeveloperAccountEmail@email.com" \
    --password "@keychain:notarization-password")
<strong>done
language-bash</strong>

نستعلم من Apple عن حالة التوثيق كل 15 ثانية، ونمرر المعرّف الفريد للتوثيق إلى المعامل --notarization-info، إلى جانب البريد الإلكتروني لحساب المطور وكلمة المرور الخاصة بالتطبيق كما فعلنا سابقًا. ثم نحفظ الاستجابة في متغير باسم statusResponse. نحتاج الآن إلى تحليل $statusResponse واستخراج الحالة الفعلية منه، حتى نحدد متى نخرج من الحلقة وننهي التنفيذ. وللتوضيح، قيمة $statusResponse سلسلة نصية متعددة الأسطر، يحمل كل سطر منها معلومة مستقلة، هكذا:

Date: 2020-05-29 18:18:35 +0000 Hash: 87bgjkhbca1767bc7liuhjyghfbc7beg7wuyebf9 LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets..... RequestUUID: udhe-8enfefi-55t8dfgi-38hn-mnud7 Status: in progress Status Code: 0

لذا يحتاج سكربت ruby لدينا إلى تحليل هذا النص لاستخراج عبارة "in progress". أنشئوا ملف ruby باسم status.rb، وانسخوا إليه السكربت التالي:

# the response is a multiline string, with the status being on its own line 
# using the format "Status: <status here>"
# Split each line into its own object in an array    
response_objects = ARGV[0].split("\n")

# get line that contains the "Status:" text    
status_line = response_objects.select { |data| data.include?('Status:') }[0]

# get text describing the status (should be either "in progress" or "success")
current_status = "#{status_line.split('Status: ').last}"

# respond with value    
puts current_status
<strong>language-ruby</strong>

والآن عدّلوا الحلقة السابقة لتصبح كالتالي:

current_status = "in progress"

<strong>while</strong> [[ "$currentStatus" == "in progress" ]]; <strong>do
</strong>
sleep 15

statusResponse=$(xcrun altool --notarization-info "$uuid" \
    --username "yourDeveloperAccountEmail@email.com" \
    --password "@keychain:notarization-password")

current_status=$(ruby status.rb "$statusResponse")
<strong>done

</strong>if [[ "$current_status" == "success" ]]; then
  # staple notarization here
  # distribute your notarized software
else
  echo "Error! The status was $current_status. There were errors. Please check the LogFileURL for error descriptions"
  exit 1
fi

**تثبيت تذكرة التوثيق (Stapling)**تُسمّى عملية إرفاق التوثيق بملف التطبيق "stapling". عند تنزيل تطبيق، يتحقق Gatekeeper من خوادم Apple لمعرفة ما إذا كان التطبيق موثّقًا. لكن ليس كل المستخدمين متصلين بالإنترنت حين يفتحون تطبيقكم لأول مرة. فإن لم يكونوا متصلين، ولم تكونوا قد أرفقتم تذكرة التوثيق بتطبيقكم، فسيفشل تحقق Gatekeeper من التوثيق. ولتثبيت التوثيق في تطبيقكم، شغّلوا ببساطة:

xcrun stapler staple "YourApp.dmg"

تجدر الإشارة إلى أنه لا يمكن تثبيت التوثيق في ملف zip مباشرة. بدلًا من ذلك، عليكم أولًا فك ضغط محتوياته، ثم تشغيل أمر stapler أعلاه على كل عنصر في الملف، ثم إنشاء ملف zip جديد يضم كل العناصر بعد تثبيت التوثيق فيها. LogFileURLإذا ظهر خطأ، فاحرصوا على مراجعة LogFileURL الموجود في $statusResponse. فهو يحتوي على معلومات مفيدة تساعدكم على تحديد ما حدث خطأ أثناء عملية التوثيق بدقة. وجرّبوا أيضًا تشغيل أوامر التوثيق مع الخيار --verbose للحصول على مخرجات أكثر تفصيلًا.

يمكنكم الآن توزيع ملف dmg الموثّق كما تشاؤون. لمزيد من القراءة من Apple: - Resolving Common Notarization Issues - Notarizing macOS Software Before Distribution - Customizing the Notarization Workflow

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد