CI/CD متقدم لمشاريع Kotlin على GitHub Actions
أتمتة البناء والاختبار والنشر هي مرحلة حاسمة في تطوير تطبيقات Kotlin الحديثة. إذا كان الإعداد الأساسي لـ CI/CD قد تم إتقانه بالفعل، فقد حان الوقت للانتقال إلى التقنيات المتقدمة. في هذه المقالة، سنستعرض كيفية تحقيق أقصى استفادة من GitHub Actions لمشاريع Kotlin: البناء المصفوفي، التخزين المؤقت الذكي، الاختبارات المتوازية، والنشر المرن.
1. البناء المصفوفي: الاختبار على إصدارات وأنظمة تشغيل متعددة
واحدة من أقوى ميزات GitHub Actions هي استراتيجية المصفوفة (strategy.matrix). فهي تسمح بتشغيل نفس سير العمل مع معايير مختلفة. بالنسبة لـ Kotlin، هذا لا غنى عنه إذا كنت تدعم إصدارات متعددة من JVM أو منصات مستهدفة (مثل JVM + Native).
مثال على بناء مصفوفي لمشروع Kotlin متعدد المنصات:
name: Matrix Build Kotlinon: [push, pull_request]
jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] java: [11, 17, 21] kotlin-version: [1.9.22, 2.0.0] fail-fast: false # لا نوقف بقية عمليات البناء عند حدوث خطأ في واحدة
steps: - uses: actions/checkout@v4
- name: إعداد JDK ${{ matrix.java }} uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: 'temurin'
- name: التحقق من صحة Gradle wrapper uses: gradle/wrapper-validation-action@v2
- name: البناء باستخدام Gradle run: ./gradlew build -Dkotlin.version=${{ matrix.kotlin-version }}التوصيات:
- استخدم
fail-fast: falseحتى لا تفقد نتائج المجموعات الأخرى إذا فشلت إحداها. - اقتصر المصفوفة على الإصدارات ذات الصلة فقط لتجنب إهدار دقائق Actions الإضافية.
- بالنسبة لـ Windows، تأكد من ضبط المسارات الصحيحة لـ Gradle وتحقق من فواصل الأسطر (CRLF).
2. التخزين المؤقت الذكي لـ Gradle والتبعيات
مشاريع Kotlin على Gradle قد تقوم بتحميل عشرات الميغابايت من التبعيات في كل مرة يتم فيها تشغيل CI. بدون التخزين المؤقت، سيستغرق البناء من 5 إلى 10 دقائق، بينما معه سيستغرق من 30 إلى 40 ثانية. استخدم الإجراءات المدمجة للتخزين المؤقت.
steps: - uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper build/ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle-
- name: البناء باستخدام Gradle run: ./gradlew build --build-cache --no-daemonحيل متقدمة:
- أضف إلى مفتاح التخزين المؤقت تجزئة من
gradle.lockfile(إذا كنت تستخدم--write-locks) - وهذا يضمن إبطال التخزين المؤقت عند تغيير إصدارات التبعيات. - استخدم
gradle-build-actionمن Gradle (الإجراء:gradle/gradle-build-action@v3) - فهو يدير التخزين المؤقت تلقائيًا ويتضمن دعمًا لـ--build-cache. - لا تقم بتخزين
~/.gradle/daemonمؤقتًا - فقد يؤدي ذلك إلى تعارضات بين إصدارات مختلفة من الخفي.
3. الاختبارات المتوازية والتوزيع الديناميكي (sharding)
بالنسبة للمشاريع الكبيرة التي تحتوي على مئات الاختبارات، قد يكون وقت التنفيذ عنق زجاجة. يسمح GitHub Actions بتشغيل الاختبارات بالتوازي عن طريق تقسيمها إلى أجزاء (shards). هذا مفيد بشكل خاص لـ Kotlin + JUnit 5.
مثال على تقسيم الاختبارات إلى أجزاء:
jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] # 4 أجزاء متوازية steps: - uses: actions/checkout@v4 - name: إعداد JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin'