مقدمة: لماذا يعتبر CI/CD أمرًا بالغ الأهمية لمشاريع Kotlin
\nفي التطوير الحديث باستخدام Kotlin، سواء كان خلفية (باك إند) باستخدام Ktor، أو تطبيق Android، أو مشروع متعدد المنصات، فإن تنفيذ العمليات المتكررة يدويًا (البناء، تشغيل الاختبارات، التحقق من نمط الشفرة) ليس مجرد مضيعة للوقت، بل هو أيضًا مصدر للأخطاء. يحل CI/CD (التكامل المستمر / النشر المستمر) هذه المشكلة عن طريق أتمتة خط الأنابيب بأكمله من الالتزام (commit) إلى الإنتاج.
\nGitHub Actions هي أداة أتمتة مدمجة مثالية لمشاريع Kotlin. تتيح لك إنشاء خطوط أنابيب (pipelines) مباشرة في المستودع دون الحاجة إلى خدمات خارجية. في هذه المقالة، سنشرح كيفية إعداد CI/CD كامل لمشاريع Kotlin باستخدام GitHub Actions، بدءًا من البناء الأساسي وصولاً إلى النشر.
\n\n1. أساسيات GitHub Actions و Kotlin
\nيعمل GitHub Actions بناءً على سير العمل (workflow) — ملفات YAML التي تحدد تسلسل الخطوات. يتم تشغيل كل سير عمل بناءً على مشغل (trigger) (push، pull request، جدولة) ويتم تنفيذه في بيئة افتراضية (runner).
\nبالنسبة لمشاريع Kotlin، تشمل الحزمة القياسية:
\n- \n
- Gradle أو Maven — نظام البناء؛ \n
- JUnit / Kotest — أطر الاختبار؛ \n
- Detekt / ktlint — أدوات فحص الشفرة (linters) لـ Kotlin. \n
الخطوة الأولى هي إنشاء ملف .github/workflows/ci.yml في جذر المستودع. دعنا نلقي نظرة على الحد الأدنى من التكوين للبناء والاختبار.
1.1 البناء والاختبار الأساسيان
\nلنبدأ بخط أنابيب بسيط يتم تشغيله عند كل push و pull request إلى الفرع الرئيسي (main):
\nname: CI for Kotlin\n\non:\n push:\n branches: [ main ]\n pull_request:\n branches: [ main ]\n\njobs:\n build:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v3\n - name: Set up JDK 17\n uses: actions/setup-java@v3\n with:\n java-version: '17'\n distribution: 'temurin'\n - name: Grant execute permission for gradlew\n run: chmod +x gradlew\n - name: Build with Gradle\n run: ./gradlew build\n - name: Run tests\n run: ./gradlew test\nيقوم هذا الكود بما يلي: استنساخ المستودع، تثبيت JDK 17 (الإصدار الموصى به لـ Kotlin 1.9+)، جعل gradlew قابلاً للتنفيذ، تنفيذ البناء وتشغيل الاختبارات. إذا فشلت الاختبارات، يتوقف خط الأنابيب مع ظهور خطأ.
2. تكوين متقدم: فحص الشفرة (linting)، التخزين المؤقت (caching) ومصفوفة البناء (Matrix Build)
\nالإعداد الأساسي جيد، ولكن لمشروع حقيقي نحتاج إلى المزيد. دعنا نضيف التحقق من نمط الشفرة باستخدام Detekt والتخزين المؤقت لتبعيات Gradle لتسريع العمل.
\n\n2.1 التخزين المؤقت لـ Gradle
\nبدون التخزين المؤقت، يقوم كل تشغيل بتنزيل التبعيات من جديد، مما قد يستغرق من 2 إلى 5 دقائق. نستخدم التخزين المؤقت المدمج:
\n- name: Cache Gradle packages\n uses: actions/cache@v3\n with:\n path: |\n ~/.gradle/caches\n ~/.gradle/wrapper\n key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}\n restore-keys: |\n ${{ runner.os }}-gradle-\n\n2.2 فحص الشفرة باستخدام Detekt
\nأضف مهمة للتحقق من الشفرة. يمكن تشغيل Detekt عبر إضافة Gradle:
\n- name: Run Detekt\n run: ./gradlew detekt\nإذا وجد Detekt مخالفات، سينتهي خط الأنابيب بخطأ. هذا يضمن عدم دخول شفرة "غير نظيفة" إلى المستودع.
\n\n2.3 مصفوفة البناء (Matrix Build)
\nإذا كان مشروعك يدعم إصدارات متعددة من Kotlin أو JDK، استخدم المصفوفة. هذا يسمح بالتحقق من التوافق دون تكرار الشفرة:
\njobs:\n build:\n strategy:\n matrix:\n java: [11, 17, 21]\n kotlin: [1.9.0, 2.0.0]\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n - name: Set up JD