From 0754ad4ebf24acdb475ad6bf4f7a0883dcc69ba6 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Tue, 30 Jun 2026 21:44:12 -0500 Subject: [PATCH] ci: enforce ktlint + detekt on pull requests Add a `static-analysis` job (JDK 21 + Android SDK) that runs `:app:ktlintCheck :app:detekt` and uploads the reports, and add it to the `ci-passed` aggregating gate so lint regressions block merges like the other checks. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5203f7..825d7e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,6 +89,43 @@ jobs: path: app/build/reports/tests/testDebugUnitTest/ if-no-files-found: warn + static-analysis: + name: Static analysis + runs-on: ubuntu-latest + steps: + - name: Check out source + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Set up JDK 21 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + with: + distribution: temurin + java-version: "21" + + # AGP configuration needs the SDK even for ktlint/detekt (they run on the :app module). + - name: Set up Android SDK + uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1 + + - name: Install SDK platform and build-tools + run: sdkmanager "$ANDROID_PLATFORM" "$ANDROID_BUILD_TOOLS" + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 + + # --continue so a ktlint failure still lets detekt report (and vice versa). + - name: Run ktlint and detekt + run: ./gradlew :app:ktlintCheck :app:detekt --continue --stacktrace + + - name: Upload analysis reports + if: ${{ !cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: static-analysis-reports + path: | + app/build/reports/ktlint/ + app/build/reports/detekt/ + if-no-files-found: warn + e2e: name: E2E runs-on: ubuntu-latest @@ -291,13 +328,14 @@ jobs: ci-passed: name: CI passed if: always() - needs: [debug-build, unit-tests, e2e, e2e-preview] + needs: [static-analysis, debug-build, unit-tests, e2e, e2e-preview] runs-on: ubuntu-latest steps: - name: Verify every required job succeeded if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} run: | echo "Required CI jobs did not all succeed:" + echo " static-analysis: ${{ needs.static-analysis.result }}" echo " debug-build: ${{ needs.debug-build.result }}" echo " unit-tests: ${{ needs.unit-tests.result }}" echo " e2e: ${{ needs.e2e.result }}"