My Workflow
As an Android developer, I would like to put under control the developments of an oss sandbox application gathering some practices in a functional application.
In a craftmanship approach I like to work with practices such as industrialization, continuous quality control, functional orientation and fast delivery.
You will find in this repo a some practices and patterns on workflow files that I will detail below.
Submission Category: Phone Friendly
Yaml File / Link to Code
In the project you can find different workflow files :
- CI Workflow - Make build, test and quality check
- Release Workflow - Deal with release control and deployment
- Super-linter Workflow - Check all files with common lint rules
Here is the main Build workflow 👉
name: Build
on:
push:
branches: [ main ] # Just in case main was not up to date while merging PR
pull_request:
types: [ opened, synchronize ]
jobs:
build-and-test:
name: Build, Lint and Test
runs-on: macos-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up our JDK environment
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: Cache Gradle and wrapper
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# Decode Google services configuration file from secrets
# - name: Decode google-services.json
# env:
# FIREBASE_CONFIG: ${{ secrets.FIREBASE_CONFIG }}
# run: echo $FIREBASE_CONFIG > app/google-services.json
# Run emulator
- name: Run integration test on emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
script: ./gradlew createDebugCoverageReport --stacktrace
# Generate jacoco report
- name: Generate report
run: ./gradlew jacocoTestReport
# Upload report
- name: Upload Reports
uses: actions/upload-artifact@v2
if: always()
with:
name: reports
path: |
/build/coverage-report
app/build/reports
# Upload coverage report to Codacy
- name: Run codacy-coverage-reporter
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
static-analysis:
name: Execute analyse on code
continue-on-error: true
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up our JDK environment
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: Cache Gradle and wrapper
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# Check the code with detekt, you can remove this job if you don't use detekt
- name: Run detekt Linter
run: ./gradlew detekt
# Check the code with ktlint, you can remove this job if you don't use ktlint
- name: Run Kotlin Linter
run: ./gradlew ktlintCheck
# Check the code with Android linter (need assemble)
- name: Run Android Linter
run: ./gradlew lint
# Check the code with Spotless
- name: Run Spotless
run: ./gradlew spotlessCheck
generate-release-apk:
name: Try generate Releasable
runs-on: ubuntu-latest
environment: Release
timeout-minutes: 20
needs:
- build-and-test
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up our JDK environment
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: Decode Keystore
env:
ENCODED_STRING: ${{ secrets.KEYSTORE }}
run: |
TMP_KEYSTORE_FILE_PATH="${RUNNER_TEMP}"/keystore
mkdir "${TMP_KEYSTORE_FILE_PATH}"
echo $ENCODED_STRING | base64 -di > "${TMP_KEYSTORE_FILE_PATH}"/keystore_file.jks
- name: Cache Gradle and wrapper
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build Release
run: ./gradlew app:assembleRelease
env:
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
In this file you can see 3 main sections :
- build-and-test
- static-analysis
- generate-release-apk
The build-and-test part is in charge of building application (and check for build failure) and running tests, both unit and instrumented. For instrumented it used android-emulator-runner to prepare a device in order to run. At the end a Jacoco task is merging different coverage result and upload them to Codacy
In parallel of this task, static-analysis is running some of android popular linters : ktLint, detekt, Android lint, Spotless
The last task generate-release-apk is waiting for build-and-test to complete and succeed before running then it will try to build an releaseable apk without publish it.
The real publishing task is in the Release Workflow which do the same job but in an other part of the delivery workflow, when a new version-tag is added. You can notice that the workflow deploy the final apk to firebase through firebase-app-distribution task.
Finally the *.apk file is available to Firebase App Distribution
Additional Resources / Info
Do not hesitate to explore the repository
boitakub / Bogadex
🎲 BoardGameGeek collections explorer application using Hilt, Coroutines, Flow, Jetpack (Room, ViewModel) based on MVVM architecture.
Bogadex is a small demo and functionnal application based on modern Android application tech-stacks and MVVM architecture.
This project aim to regroup and present most of current practices and patterns.
Also dealing with data (from BoardGameGeek) and presenting them in elegants ways
Download 📲
Go to the Releases to download the latest APK.
Features ✨
- Free and open source
- List, Sort and Filter all you BGG BoardGameGeekCollection
Tech Stack & Libraries 🧬
This project takes advantage of best practices, and many popular libraries and tools in the Android ecosystem.
-
Kotlin - 100% Kotlin - Code and Scripts
-
Flow for asynchronous.
-
Lifecycle - dispose of observing data when lifecycle state changes.
-
ViewModel - UI related data holder, lifecycle aware.
-
Hilt-Dagger for dependency injection.
-
- Compose - UI build 100% with Jetpack Compose
- WorkManager - Updating and maintaining data up-to-date periodically and asynchronous
- DataStore - for shared preferences
- Room -…
And some of the Github Actions it used :
- Workflow folder - All Github Actions workflows
- Android emulator for instrumented - GHAction
- Super-linter - GHAction
- Firebase App Distribution - GHAction
Top comments (0)