CircleCI Android Yapılandırması
.circleci/config.yml
version: 2
jobs:
build:
working_directory: ~/code
docker:
- image: circleci/android:api-28-alpha
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- run:
name: Initialize Keystore File
command: echo $KEYSTORE_BASE64 | base64 --decode > app/aykutasilkeystore
- run:
name: Initialize Fabric Properties
command: |
echo "apiKey=$FABRIC_API_KEY" >> app/fabric.properties
echo "apiSecret=$FABRIC_API_SECRET" >> app/fabric.properties
cat app/fabric.properties
- run:
name: Initialize Keystore File
command: |
echo "signingKeyAlias=$KEYSTORE_KEY_ALIAS" >> keystore.properties
echo "signingKeyAliasPassword=$KEYSTORE_KEY_ALIAS_PASSWORD" >> keystore.properties
echo "signingStoreFile=$KEYSTORE_STORE_FILE" >> keystore.properties
echo "signingStorePassword=$KEYSTORE_STORE_PASSWORD" >> keystore.properties
cat keystore.properties
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results
- run:
command: echo "Current Branch:" ${CIRCLE_BRANCH}
- run:
name: Initial build
command: ./gradlew assembleDebug assembleRelease --no-daemon --stacktrace
- store_artifacts:
path: app/build/outputs/apk/
destination: apks/
- deploy:
name: Deploy to Fabric
command: ./gradlew crashlyticsUploadDistributionRelease --stacktrace --debug --no-daemon
workflows:
version: 2
workflow:
jobs:
- build
app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'
android {
compileSdkVersion 28
def fabricPropertiesFile = rootProject.file("app/fabric.properties")
def fabricProperties = new Properties()
if (fabricPropertiesFile.exists()) {
fabricProperties.load(new FileInputStream(fabricPropertiesFile))
}
defaultConfig {
applicationId "com.aykutasil.circlecitest"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ext.betaDistributionEmails = "[email protected]"
ext.betaDistributionNotifications = true
resValue "string", "io.fabric.ApiKey", fabricProperties['apiKey']
}
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
signingConfigs {
config {
keyAlias keystoreProperties['signingKeyAlias']
keyPassword keystoreProperties['signingKeyAliasPassword']
storeFile file(keystoreProperties['signingStoreFile'])
storePassword keystoreProperties['signingStorePassword']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation('com.crashlytics.sdk.android:crashlytics:2.9.6@aar') {
transitive = true
}
}
Ne Yaptık ?
Yukarıda ki örnek gradle dosyasında log için kullanılan Crashlytics’ apiKey bilgilerini ve apk imzalama için gerekli bilgileri başka dosyalardan okuyayarak gizliliği sağladığımızı görüyorsunuz.
Bu bilgileri okuğumuz keystore.properties ve fabric.properties dosyalarını VCS içerisine eklemiyoruz. Yani .gitignore dosyamıza ekleyerek github, bitbucket gibi VCS platformlarına gönderimini engelliyoruz.
Peki bu dosyaları VCS platformuna göndermemiş isek CI/CD platformu projemizi derlemeye çalışırken gradle dosyası içerisinde ki bu bilgileri nasıl okuyacak?
İşte bunun için farklı yöntemler mevcut. Bunlardan ikisi yukarıda ki örnekte mevcut.
1. Base64 Yöntemi
Yukarıda ki .yml dosyasını incelediğinizde command: echo $KEYSTORE_BASE64 | base64 --decode > app/aykutasilkeystore
şeklinde bir satır göreceksiniz. Burada yaptığımız şey mevcut keystore dosyamızın base64 değerini alarak CI/CD platformuna environment variable olarak kayıt etmek. Ve daha sonra yml dosyasında bu environment variable ($KEYSTORE_BASE64) değerini okuyarak base64 --decode
komutu ile decode ederek > app/aykutasilkeystore
yoluna bu dosyayı ekliyoruz. Ve artık gradle dosyamız ilgili dosyayı(keystore) bulacağı için sorun oluşmayacak ve düzgün bir şekilde projemiz derlenecektir.
2. Environment Variable
Aslında burada da bir öncekine benzer bir yapılandırma söz konusu. Tek fark okunan environment variable değerini ilgili dosyaya direk olarak yazmak.
Yukarıda ki yml dosyasında echo "apiKey=$FABRIC_API_KEY" >> app/fabric.properties
satırında direk olarak $FABRIC_API_KEY değeri okunup app/fabric.properties yolunda fabric.properties isimli dosyanın oluşması sağlanmıştır.