Created
October 11, 2018 16:50
-
-
Save TheDancerCodes/408a6780c5b36b00c3cd8be5b9c9e40e to your computer and use it in GitHub Desktop.
This gist contains the build pipeline for one of our internal products using Circle CI, Firebase TestLab and GCP (Google Cloud Platform)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
default: &defaults | |
docker: | |
- image: circleci/android:api-26-alpha | |
working_directory: ~/repo | |
environment: | |
TERM: dumb | |
# Customize the JVM maximuum heap limit | |
_JAVA_OPTIONS: "-Xmx2048m -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap" | |
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m"' | |
gcloud_config: &gcloud_config | |
working_directory: ~/repo | |
docker: | |
- image: google/cloud-sdk:latest | |
environment: | |
TERM: dumb | |
workspace: &workspace | |
~/repo | |
attach_debug_workspace: &attach_debug_workspace | |
attach_workspace: | |
at: *workspace | |
persist_firebase_workspace: &persist_firebase_workspace | |
persist_to_workspace: | |
root: *workspace | |
paths: | |
- firebase | |
# Google Services From Firebase (JSON) | |
export_gservices_key: &export_gservices_key | |
run: | |
name: Export Google Services key environment variable | |
command: echo 'export GOOGLE_SERVICES_JSON="$GOOGLE_SERVICES_JSON"' >> $BASH_ENV | |
export_failure_determinant: &failure_determinant | |
run: | |
name: Export Failure Determinant | |
when: on_success | |
command: | | |
echo 'export INSTRUMENT_TEST_ARTIFACT=exempted' >> $BASH_ENV | |
decode_gservices_key: &decode_gservices_key | |
run: | |
name: Decode Google Services JSON key | |
command: | | |
mkdir app/src/prod/release | |
mkdir app/src/prod/debug | |
mkdir app/src/mock/debug | |
mkdir app/src/mock/release | |
touch app/src/prod/release/google-services.json | |
touch app/src/prod/debug/google-services.json | |
touch app/src/mock/release/google-services.json | |
touch app/src/mock/debug/google-services.json | |
touch app/google-services.json | |
echo $GOOGLE_SERVICES_JSON | base64 --decode >> app/src/mock/debug/google-services.json | |
echo $GOOGLE_SERVICES_JSON | base64 --decode >> app/src/mock/release/google-services.json | |
echo $GOOGLE_SERVICES_JSON | base64 --decode >> app/src/prod/debug/google-services.json | |
echo $GOOGLE_SERVICES_JSON | base64 --decode >> app/src/prod/release/google-services.json | |
echo $GOOGLE_SERVICES_JSON | base64 --decode >> app/google-services.json | |
# Google Cloud Service Account Key | |
export_gcloud_key: &export_gcloud_key | |
run: | |
name: Export Google Cloud Service Account Key Environment Variable | |
command: echo 'export GCLOUD_SERVICE_KEY="$GCLOUD_SERVICE_KEY"' >> $BASH_ENV | |
decode_gcloud_key: &decode_gcloud_key | |
run: | |
name: Decode Google Cloud Credentials | |
command: | | |
touch client-secret.json | |
echo $GCLOUD_SERVICE_KEY | base64 --decode >> client-secret.json | |
persist_debug_workspace: &persist_debug_workspace | |
persist_to_workspace: | |
root: *workspace | |
paths: | |
- app/build/intermediates | |
- app/build/outputs/androidTest-results | |
- app/build/outputs/apk | |
- app/build/outputs/code-coverage | |
- app/build/test-results | |
version: 2 | |
jobs: | |
android_lint: | |
<<: *defaults | |
steps: | |
- checkout | |
# setup Keystore Environment for downloading necessary assets to use for deployment | |
- run: | |
name: Setup Keystore Environment | |
command: | | |
bash ~/repo/.circleci/keystore_setup.sh | |
# Download and cache dependencies | |
- restore_cache: | |
keys: | |
- v1-dependencies-{{ checksum "build.gradle" }} | |
# fallback to using the latest cache if no exact match is found | |
- v1-dependencies- | |
- run: ./gradlew androidDependencies | |
- save_cache: | |
paths: | |
- ~/.gradle | |
key: v1-dependencies-{{ checksum "build.gradle" }} | |
- *export_gservices_key | |
- *decode_gservices_key | |
# Running static analysis tools | |
- run: | |
name: Running quality checks | |
command: | | |
echo "Run android lint" | |
cd ~/repo | |
./gradlew lint | |
# Storing reports | |
- store_artifacts: | |
path: ~/repo/app/build/reports | |
# Sending notification | |
- run: | |
name: Notifying slack channel (succeeded) | |
when: on_success | |
command: | | |
bash ~/repo/.circleci/notify_slack.sh | |
- run: | |
name: Notifying slack channel (failed) | |
when: on_fail | |
command: | | |
bash ~/repo/.circleci/notify_slack_fail.sh | |
test_unit: | |
<<: *defaults | |
steps: | |
- checkout | |
# setup Keystore Environment for downloading necessary assets to use for deployment | |
- run: | |
name: Setup Keystore Environment | |
command: | | |
bash ~/repo/.circleci/keystore_setup.sh | |
# Download and cache dependencies | |
- restore_cache: | |
keys: | |
- v1-dependencies-{{ checksum "build.gradle" }} | |
# fallback to using the latest cache if no exact match is found | |
- v1-dependencies- | |
- run: ./gradlew androidDependencies | |
- save_cache: | |
paths: | |
- ~/.gradle | |
key: v1-dependencies-{{ checksum "build.gradle" }} | |
- *export_gservices_key | |
- *decode_gservices_key | |
# Running unit tests | |
- run: | |
name: Running unit tests on source code | |
command: | | |
cd ~/repo | |
./gradlew test | |
ls -a app/build/outputs/logs | |
- *persist_debug_workspace | |
#Storing unit test reports | |
- store_artifacts: | |
path: ~/repo/app/build/reports | |
destination: reports | |
- store_artifacts: | |
path: ~/repo/app/build/outputs/androidTest-results | |
destination: reports | |
# Sending notification | |
- run: | |
name: Notifying slack channel on succeed | |
when: on_success | |
command: | | |
bash ~/repo/.circleci/notify_slack.sh | |
- run: | |
name: Notifying slack channel on fail | |
when: on_fail | |
command: | | |
bash ~/repo/.circleci/notify_slack_fail.sh | |
## Build APK depending on current branch and instrumented test APK | |
deploy_build_job: | |
<<: *defaults | |
steps: | |
- checkout | |
# setup Keystore Environment for downloading necessary assets to use for deployment | |
- run: | |
name: Setup Keystore Environment | |
command: | | |
bash ~/repo/.circleci/keystore_setup.sh | |
- restore_cache: | |
keys: | |
- v1-dependencies-{{ checksum "build.gradle" }} | |
# fallback to using the latest cache if no exact match is found | |
- v1-dependencies- | |
- run: ./gradlew androidDependencies | |
- save_cache: | |
paths: | |
- ~/.gradle | |
key: v1-dependencies-{{ checksum "build.gradle" }} | |
- *export_gservices_key | |
- *decode_gservices_key | |
- run: | |
name: Gradle build (debug) | |
command: | | |
bash ~/repo/.circleci/gradle_build.sh | |
- *persist_debug_workspace | |
- store_artifacts: | |
path: app/build/outputs/apk/ | |
destination: /apk/ | |
- store_artifacts: | |
path: ~/repo/app/build/reports | |
destination: reports | |
# Sending notification | |
- run: | |
name: Notifying slack channel on succeed | |
when: on_success | |
command: | | |
bash ~/repo/.circleci/notify_slack.sh | |
- run: | |
name: Notifying slack channel on fail | |
when: on_fail | |
command: | | |
bash ~/repo/.circleci/notify_slack_fail.sh | |
## Run instrumentation tests | |
test_instrumentation: | |
<<: *gcloud_config | |
steps: | |
- checkout | |
- *attach_debug_workspace | |
- *export_gcloud_key | |
- *decode_gcloud_key | |
- *failure_determinant | |
- run: | |
name: Set Google Cloud target project | |
command: gcloud config set project <name-of-GCP-project> | |
- run: | |
name: Authenticate with Google Cloud | |
command: gcloud auth activate-service-account <name-of-GCP-app>.iam.gserviceaccount.com --key-file client-secret.json && gcloud firebase test android models list | |
- run: | |
name: Install Java JDK8 | |
command: | | |
bash ~/repo/.circleci/setup_java.sh | |
- run: | |
name: Notifying slack channel on fail | |
when: on_fail | |
command: | | |
if [ "${INSTRUMENT_TEST_ARTIFACT}" == exempted ]; then | |
bash ~/repo/.circleci/notify_slack_fail.sh | |
fi | |
- run: | |
name: Modify Failure Determinant | |
when: on_success | |
command: | | |
echo 'export INSTRUMENT_TEST_ARTIFACT=required' >> $BASH_ENV | |
- run: | |
name: Run test on Firebase Test Lab with Flank | |
when: on_success | |
command: | | |
cat ~/repo/.circleci/config.properties >> /root/repo/config.properties | |
curl -O https://jitpack.io/com/github/TestArmada/flank/v2.0.3/flank-v2.0.3.jar | |
java -jar /root/repo/flank-v2.0.3.jar -a ~/repo/app/build/outputs/apk/mock/debug/app-mock-debug.apk -t ~/repo/app/build/outputs/apk/androidTest/mock/debug/app-mock-debug-androidTest.apk > result | |
cat result | |
cat result | grep -o 'gs://[^"]*' | grep 'gs://<name-of-GCP-app>-[a-z0-9.-]*' | head -1 > artifact_url | |
- run: | |
name: Create directory to store test results | |
command: mkdir firebase | |
- run: | |
name: Download instrumented test results from Firebase Test Lab on success | |
command: | | |
python ~/repo/.circleci/get_artifact_path.py | |
artifact_path="$(cat artifact_path)" | |
gsutil -m cp -n -r gs://${artifact_path}* /root/repo/firebase/ || true | |
- run: | |
name: Print firebase error results | |
when: on_fail | |
command: | | |
file="$(ls result)" | |
if [ $file == "result" ]; then | |
cat result | |
else | |
echo "Firebase did not create any output" | |
fi | |
- *persist_firebase_workspace | |
- store_artifacts: | |
when: on_success | |
path: firebase/ | |
destination: /firebase/ | |
# Sending notification | |
- run: | |
name: Notifying slack channel on succeed | |
when: on_success | |
command: | | |
bash ~/repo/.circleci/notify_slack.sh | |
- run: | |
name: Download instrumented test results from Firebase Test Lab on fail | |
when: on_fail | |
command: | | |
if [ "$INSTRUMENT_TEST_ARTIFACT" == required ]; then | |
cat result | grep -o 'gs://[^"]*' | grep 'gs://<name-of-GCP-app>-[a-z0-9.-]*' | head -1 > artifact_url | |
mkdir firebase | |
python ~/repo/.circleci/get_artifact_path.py | |
artifact_path="$(cat artifact_path)" | |
gsutil -m cp -n -r gs://${artifact_path}* /root/repo/firebase/ || true | |
fi | |
- store_artifacts: | |
when: on_fail | |
path: firebase/ | |
destination: /firebase/ | |
- run: | |
name: Notifying slack channel on fail | |
when: on_fail | |
command: | | |
if [ "$INSTRUMENT_TEST_ARTIFACT" == required ]; then | |
bash ~/repo/.circleci/notify_slack_fail.sh | |
fi | |
report_coverage: | |
<<: *defaults | |
steps: | |
- checkout | |
- run: | |
name: Setup Keystore Environment | |
command: | | |
bash ~/repo/.circleci/keystore_setup.sh | |
- restore_cache: | |
keys: | |
- v1-dependencies-{{ checksum "build.gradle" }} | |
- v1-dependencies- | |
- run: | |
name: Download dependencies | |
command: ./gradlew androidDependencies | |
- *attach_debug_workspace | |
- run: | |
name: Move Firebase Coverage Report | |
command: | | |
mkdir -p app/build/outputs/code-coverage/connected/flavors/MOCK | |
cp firebase/0/Nexus7-22-en-landscape/artifacts/coverage.ec app/build/outputs/code-coverage/connected/flavors/MOCK/coverage0.ec | |
cp firebase/1/Nexus7-22-en-landscape/artifacts/coverage.ec app/build/outputs/code-coverage/connected/flavors/MOCK/coverage1.ec | |
cp firebase/2/Nexus7-22-en-landscape/artifacts/coverage.ec app/build/outputs/code-coverage/connected/flavors/MOCK/coverage2.ec | |
cp firebase/3/Nexus7-22-en-landscape/artifacts/coverage.ec app/build/outputs/code-coverage/connected/flavors/MOCK/coverage3.ec | |
cp firebase/4/Nexus7-22-en-landscape/artifacts/coverage.ec app/build/outputs/code-coverage/connected/flavors/MOCK/coverage4.ec | |
- *export_gservices_key | |
- *decode_gservices_key | |
- run: | |
name: Code Climate Test Setup | |
command: | | |
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter | |
chmod +x ./cc-test-reporter | |
- run: | |
name: Code Climate Pretest | |
command: ./cc-test-reporter before-build | |
- run: | |
name: Generate JaCoCo report | |
command: ./gradlew jacocoTestReport | |
- run: | |
name: Upload coverage to code climate | |
command: | | |
export JACOCO_SOURCE_PATH=app/src/main/java | |
cp app/src/prod/java/com/andela/mrm/Injection.java app/src/main/java/com/andela/mrm/Injection.java | |
./cc-test-reporter format-coverage app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml -t jacoco | |
./cc-test-reporter upload-coverage | |
- store_artifacts: | |
path: app/build/reports/ | |
destination: /reports/ | |
# Sending notification | |
- run: | |
name: Notifying Slack Channel on Succeed | |
when: on_success | |
command: bash ~/repo/.circleci/notify_slack.sh | |
- run: | |
name: Notifying slack channel on fail | |
when: on_fail | |
command: bash ~/repo/.circleci/notify_slack_fail.sh | |
workflows: | |
version: 2 | |
lint_test_and_deployment: | |
jobs: | |
- android_lint | |
- test_unit: | |
requires: | |
- android_lint | |
- deploy_build_job: | |
requires: | |
- test_unit | |
- test_instrumentation: | |
requires: | |
- deploy_build_job | |
- report_coverage: | |
requires: | |
- test_instrumentation |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment