מדריך הגדרת אוטומציית בנייה לאנדרואיד: CI/CD, חתימה ושמירה במטמון
לעתים קרובות אנו רואים מפתחים שמתלוננים על בניות איטיות ב-CI: פרויקט עם 15+ מודולים, Gradle רץ בחוט יחיד, בנייה קרה 4–7 דקות, בנייה מצטברת 90 שניות. בצוות של 10 אנשים, זה הופך לתור של בניות שחוסמות ביקורות. הניסיון שלנו מראה שאוטומציית בנייה נכונה אינה פתרון קסם, אלא עבודה שיטתית עם תצורות Gradle, צינור CI ושמירה במטמון. הגדרנו הכל כך שהבנייה רצה ביציבות על כל מכונה ללא שלבים ידניים.
נקודות הכאב העיקריות באוטומציית בנייה לאנדרואיד
איך לחתום על APK/AAB בבטחה ב-CI?
הבעיה הנפוצה ביותר. מפתחים מאחסנים את קובץ ה-keystore במאגר (רע) או מעבירים אותו דרך ארגומנטים של שורת פקודה בטקסט רגיל (גרוע יותר). הסכימה הנכונה: קודדו את ה-keystore ב-Base64, שימו אותו במשתנה סביבה של CI, פענחו לקובץ זמני לפני הבנייה, ומחקו אחרי הבנייה. ב-build.gradle.kts, הגדירו דרך משתני סביבה:
android {
signingConfigs {
create("release") {
storeFile = file(System.getenv("KEYSTORE_PATH") ?: "debug.keystore")
storePassword = System.getenv("KEYSTORE_PASSWORD") ?: "android"
keyAlias = System.getenv("KEY_ALIAS") ?: "androiddebugkey"
keyPassword = System.getenv("KEY_PASSWORD") ?: "android"
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
} תצורת בנייה מבוססת ענפים
נקודת הכאב השנייה. android { signingConfigs { create("release") { storeFile = file(System.getenv("KEYSTORE_PATH") ?: "debug.keystore") storePassword = System.getenv("KEYSTORE_PASSWORD") ?: "android" keyAlias = System.getenv("KEY_ALIAS") ?: "androiddebugkey" keyPassword = System.getenv("KEY_PASSWORD") ?: "android" } } buildTypes { release { signingConfig = signingConfigs.getByName("release") isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } → AAB ל-release עבור חנות Play, main → APK ל-debug עם נקודות קצה לבדיקות, develop → APK ל-staging עבור QA. יישמו באמצעות שילוב של release/* + תנאים בסקריפט CI. אין צורך ליצור קבצי buildFlavors נפרדים—תצורה אחת עם build.gradle מספיקה.
למה שמירה במטמון של Gradle חשובה?
ללא מטמון, CI מוריד 200–400 MB של תלויות בכל ריצה. עם שמירה נכונה במטמון של flavorDimensions ו-~/.gradle/caches, הבנייה הראשונה לאחר שינוי ב-~/.gradle/wrapper לוקחת זמן מלא; בניות עוקבות הן מצטברות. בממוצע, אנו חוסכים כ-60% מזמן הבנייה לאחר הבנייה הראשונה. אנו משתמשים במטמון בנייה מרוחק (דרך S3) עבור צוותים מבוזרים.
איך הגדרנו את זה
התשתית הבסיסית: Gradle 8.x + AGP 8.x + GitHub Actions / GitLab CI / Bitrise. אנו משתמשים ב-Fastlane למשימות ש-Gradle לא יכול לטפל בהן מחוץ לקופסה: העלאה ל-Google Play דרך build.gradle, שליחת הודעות, ניהול ערוצים (פנימי → אלפא → הפקה).
מבנה של צינור CI טיפוסי (GitHub Actions):
---
# .github/workflows/android-release.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- name: Decode Keystore
run: echo "$KEYSTORE_BASE64" | base64 -d > app/release.keystore
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
- name: Build Release AAB
run: ./gradlew bundleRelease
env:
KEYSTORE_PATH: release.keystore
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: release-aab
path: app/build/outputs/bundle/release/app-release.aab
---
אנו גם מגדירים supply עבור CI: # .github/workflows/android-release.yml jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - name: Cache Gradle uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - name: Decode Keystore run: echo "$KEYSTORE_BASE64" | base64 -d > app/release.keystore env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} - name: Build Release AAB run: ./gradlew bundleRelease env: KEYSTORE_PATH: release.keystore KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: release-aab path: app/build/outputs/bundle/release/app-release.aab (אין צורך ב-daemon ב-CI), gradle.properties, org.gradle.daemon=false. בפרויקטים עם מודולים מרובים, זה מפחית את זמן התצורה ב-30–40%.
ביצוע מקבילי ואופטימיזציה
אם הפרויקט מונוליטי, מקביליות כמעט לא נותנת אפקט. אבל עם ארכיטקטורה מודולרית (org.gradle.parallel=true, org.gradle.configureondemand=true, :core, :feature-auth), Gradle בונה גרף תלויות ומהדר מודולים עצמאיים במקביל. :feature-feed על סוכן עם 8 ליבות מניב האצה של פי 2–3 בהשוואה לבניות רציפות. זה הופך את ההגדרה המאופטימלית שלנו לפי 2–3 מהירה יותר מתצורה סטנדרטית.
עבור צוותים גדולים, אנו משלבים את Gradle Build Cache—או דרך Gradle Enterprise (בתשלום) או פתרון קוד פתוח עם backend של S3.
| סוג בנייה | ללא אופטימיזציה | עם אופטימיזציה (מטמון + מקביליות) |
|---|---|---|
| קרה (כל המודולים) | 5–7 דקות | 2–3 דקות |
| מצטברת | 90 שניות | 20–30 שניות |
ה-Gradle User Manual ממליץ לשלב בין שתי הגישות.
השוואת פלטפורמות CI לאנדרואיד
| פלטפורמת CI | מאפייני הגדרה | זמן בנייה ממוצע לאחר מטמון |
|---|---|---|
| GitHub Actions | אינטגרציה פשוטה, מערכת אקולוגית גדולה | ~2 דקות |
| GitLab CI | Docker מובנה, מטמון מצוין | ~1.5 דקות |
| Bitrise | מותאם למובייל, שלבים מוכנים רבים | ~2.5 דקות |
טעויות נפוצות בהגדרת CI
- קידוד keystore שגוי (Base64 עם מעברי שורה) מוביל לשגיאות פענוח.
- מטמון חסר בין ריצות: ללא שימוש ב-
:appעם מפתח מתאים, כל בנייה מורידה מחדש תלויות. - שימוש בחתימת debug ב-AAB ל-release—Google Play ידחה קובץ כזה.
- שכחת השבתת Gradle Daemon ב-CI, מה שגורם לחוסר יציבות.
מה כלול בעבודה שלנו
- ביקורת על
./gradlew assembleDebug --parallelהנוכחי (Groovy → Kotlin DSL, גרסאות תוספים, תצורות לא אופטימליות) - תצורת חתימה דרך משתני סביבה של CI
- צינור CI לפלטפורמה שלך (GitHub Actions, GitLab CI, Bitrise)
- שמירה במטמון של Gradle (מקומי ומרוחק)
- תצורה מבוססת ענפים באמצעות build flavors
- תיעוד מקיף לצוות, כולל מדריכי הגדרה ופתרון בעיות
- מפגש הדרכה למפתחים (עד שעתיים) להבטחת הטמעה חלקה
- גישה למאגרי דוגמה ותבניות שלנו
- תמיכה לאחר מסירה למשך שבועיים לטיפול בכל בעיה
- הבטחת יציבות—הכל עובד ללא התאמות ידניות לאחר המסירה
התהליך שלנו
- ייעוץ ראשוני וניתוח הבנייה הנוכחית.
- מעבר ל-Gradle מודרני + Kotlin DSL (במידת הצורך).
- תצורת חתימה דרך סודות CI.
- הגדרת CI עם שמירה במטמון ומקביליות.
- בדיקה על מספר ענפים (main, develop, release/).
- תיעוד ומסירה לצוות.
העלות מחושבת באופן אישי לאחר ניתוח דרישות. ההשקעה הטיפוסית מתחילה ב-$1,500 עבור פרויקט עם מודול יחיד ונעה עד $3,500 עבור הגדרות מורכבות עם מודולים מרובים. ציר זמן: 2–3 ימים לפרויקט עם מודול יחיד, עד 5 ימים לפרויקט עם מודולים מרובים. צרו קשר להערכת פרויקט—נעזור ליישם אוטומציית בנייה מקצה לקצה. בקשו ייעוץ כדי לקבל לוחות זמנים ומחירים מדויקים לפרויקט שלכם.
יש לנו ניסיון של למעלה מ-5 שנים בפיתוח אנדרואיד והקמנו צינורות עבודה ל-30+ פרויקטים—מסטארטאפים ועד אפליקציות ארגוניות. המהנדסים שלנו נשארים מעודכנים בגרסאות העדכניות ביותר של Gradle ו-AGP, כך שאתם מקבלים תצורה מודרנית ללא פרקטיקות מיושנות.







