Skip to content

Extract "Validation" job as reusable workflow. #512

Extract "Validation" job as reusable workflow.

Extract "Validation" job as reusable workflow. #512

Workflow file for this run

name: "CI"
on:
push
concurrency:
# Documentation suggests ${{ github.head_ref }}, but that's only available on pull_request/pull_request_target triggers, so using ${{ github.ref }}.
# On main, we want all builds to complete even if merging happens faster to make it easier to discover at which point something broke.
# More info: https://stackoverflow.com/a/68422069/253468:
group: ${{ github.ref == 'refs/heads/main' && format('ci-main-{0}', github.sha) || format('ci-{0}', github.ref) }}
cancel-in-progress: true
jobs:
validate:
uses: ./.github/workflows/validate.yml
build:
name: "🔨 Build & Verify"
needs: validate
runs-on: ubuntu-latest
# A local build took 20 seconds, CI takes 3 minutes with setup.
# Because it's cloud, give it a bit of a buffer and constrain.
timeout-minutes: 15
steps:
- name: "Set up JDK 17."
uses: actions/setup-java@v3
with:
java-version: 17
distribution: zulu
- name: "Checkout ${{ github.ref }} branch in ${{ github.repository }} repository."
uses: actions/checkout@v3
- name: "Build & Verify project."
id: gradle
run: >
./gradlew
--no-daemon
--no-build-cache
--continue
--stacktrace
--scan
assemble
lint
detekt
test
check
violationReportHtml
violationCountFile
- name: "Publish 'Gradle' result and Build Scan URL."
if: (success() || failure()) && steps.gradle != null && steps.gradle.outputs.result-success != null
uses: actions/github-script@v6
with:
debug: ${{ secrets.ACTIONS_STEP_DEBUG || false }}
script: |
const description = ${{ toJSON(fromJSON(steps.gradle.outputs.result-text)) }}
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: context.sha,
state: ${{ toJSON(fromJSON(steps.gradle.outputs.result-success)) }} === true ? "success" : "failure",
context: "CI / Build & Verify / Gradle",
// Truncate to be sure it fits:
// > HttpError: Validation Failed: {"resource":"Status","code":"custom",
// > "field":"description","message":"description is too long (maximum is 140 characters)"}
// Max length is 140, give some space for potential Unicode.
description: description.length > 130
? `${description.substring(0, 130)}…`
: description,
target_url: ${{ steps.gradle.outputs.build-scan-url && toJSON(fromJSON(steps.gradle.outputs.build-scan-url)) || 'undefined' }}
});
- name: "Upload 'Lint Results HTMLs' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Lint Results HTMLs'
path: ${{ github.workspace }}/**/build/reports/lint-results*.html
- name: "Upload 'Lint Merged Results' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Lint Merged Results'
path: ${{ github.workspace }}/build/reports/violations.*
- name: "Fail if there are lint violations."
if: success() || failure()
run: |
count=$(cat "${{ github.workspace }}/build/reports/violations.count")
if [[ "$count" != "0" ]]; then
echo "There were $count violations"
exit 1
else
echo "No violations found."
exit 0
fi
- name: "Upload 'Unit Test Results' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Unit Test Results'
path: ${{ github.workspace }}/**/build/reports/tests/*/
- name: "Publish 'Unit Results' check suite."
if: success() || failure()
uses: EnricoMi/publish-unit-test-result-action@v2
with:
check_name: '🔔 Test: Unit Results'
comment_mode: off
report_individual_runs: true
test_changes_limit: 0
junit_files: ${{ github.workspace }}/**/build/test-results/*/TEST-*.xml
- name: "Upload 'Detekt Results' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Detekt Results'
path: ${{ github.workspace }}/**/build/reports/detekt/detekt.*
- name: "Upload 'Detekt Merged Results' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Detekt Merged Results'
path: ${{ github.workspace }}/build/reports/detekt/merge.*
- name: "Publish 'detekt' GitHub Code Scanning analysis."
uses: github/codeql-action/upload-sarif@v2
if: success() || failure()
with:
checkout_path: ${{ github.workspace }}
sarif_file: ${{ github.workspace }}/build/reports/detekt/merge.sarif
instrumentation:
name: "🧪 Instrumentation Tests on ${{ matrix.android-api }}"
needs: validate
runs-on: macos-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
# Why that API level is tested?
#reason: []
# The API level, see https://apilevels.com/
#android-api: [14, ..., 33]
# The best available emulator image type.
# Some are not available: https://issuetracker.google.com/issues/267458959
#android-image-type: [default, google_apis]
include:
# API 15 is the first possible emulator that works well on GitHub Actions' architectures:
# > system-images;android-10;default;armeabi-v7a
# > system-images;android-10;default;x86
# > system-images;android-14;default;armeabi-v7a
# > system-images;android-15;default;armeabi-v7a
# > system-images;android-15;default;x86
#- reason: "minSdkVersion + 1"
# android-api: 15
# android-image-type: default
# android-arch: x86
#- reason: "ART runtime"
# android-api: 21
# android-image-type: default
# android-arch: x86_64
#- reason: "Runtime permissions"
# android-api: 23
# android-image-type: default
# android-arch: x86_64
- reason: "latest 'default'"
android-api: 29
android-image-type: default
android-arch: x86_64
#- reason: "targetSdkVersion"
# android-api: 32
# android-image-type: google_apis
# android-arch: x86_64
#- reason: "compileSdkVersion"
# android-api: 33
# android-image-type: google_apis
# android-arch: x86_64
steps:
- name: "Validate matrix values"
if: matrix.android-api < 26
run: |
echo "Android-JUnit 5 uses Java 8, so it's only possible to use from API 26 onwards."
exit 1
- name: "Set up JDK 17."
uses: actions/setup-java@v3
with:
java-version: 17
distribution: zulu
- name: "Checkout ${{ github.ref }} branch in ${{ github.repository }} repository."
uses: actions/checkout@v3
- name: "Run Instrumentation Tests on emulator for ${{ matrix.reason }}."
id: gradle
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.android-api }}
target: ${{ matrix.android-image-type }}
arch: ${{ matrix.android-arch }}
script: >
./gradlew
--no-daemon
--no-build-cache
--continue
--stacktrace
--scan
connectedCheck
mergeAndroidReports
- name: "Publish 'Gradle' result and Build Scan URL."
if: (success() || failure()) && steps.gradle != null && steps.gradle.outputs.result-success != null
uses: actions/github-script@v6
with:
debug: ${{ secrets.ACTIONS_STEP_DEBUG || false }}
script: |
const description = ${{ toJSON(fromJSON(steps.gradle.outputs.result-text)) }}
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: context.sha,
state: ${{ toJSON(fromJSON(steps.gradle.outputs.result-success)) }} === true ? "success" : "failure",
context: "CI / Instrumentation Tests ${{ matrix.android-api }} / Gradle",
// Truncate to be sure it fits:
// > HttpError: Validation Failed: {"resource":"Status","code":"custom",
// > "field":"description","message":"description is too long (maximum is 140 characters)"}
// Max length is 140, give some space for potential Unicode.
description: description.length > 130
? `${description.substring(0, 130)}…`
: description,
target_url: ${{ steps.gradle.outputs.build-scan-url && toJSON(fromJSON(steps.gradle.outputs.build-scan-url)) || 'undefined' }}
});
- name: "Upload 'Instrumentation Test Results ${{ matrix.android-api }}' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Instrumentation Test Results ${{ matrix.android-api }}'
# Exclude names with colon: https://issuetracker.google.com/issues/223643506
path: |
${{ github.workspace }}/**/build/outputs/androidTest-results/connected/
${{ github.workspace }}/**/build/outputs/connected_android_test_additional_output/
!**/*:*
- name: "Upload 'Instrumentation Merged Results ${{ matrix.android-api }}' artifact."
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: 'Instrumentation Merged Results ${{ matrix.android-api }}'
# Exclude names with colon: https://issuetracker.google.com/issues/223643506
path: |
${{ github.workspace }}/build/androidTest-results/
!**/*:*
- name: "Publish 'Instrumentation Results ${{ matrix.android-api }}' check suite."
if: success() || failure()
uses: EnricoMi/publish-unit-test-result-action/composite@v2
with:
check_name: '🔔 Test: Instrumentation Results ${{ matrix.android-api }}'
comment_mode: off
report_individual_runs: true
test_changes_limit: 0
junit_files: ${{ github.workspace }}/**/build/outputs/androidTest-results/connected/TEST-*.xml