diff --git a/.github/workflows/code-format.yml b/.github/workflows/code-format.yml new file mode 100644 index 000000000..60980bae1 --- /dev/null +++ b/.github/workflows/code-format.yml @@ -0,0 +1,35 @@ +name: Check code formatting + +on: + push: + branches: [main] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + spotless: + name: Check Java formatting (Spotless) + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: temurin + - uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v4 + - name: Check formatting + run: ./gradlew spotlessCheck diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 49414fe1b..6d33e5aba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,18 +73,15 @@ esp. before/after screenshots. ### Coding Conventions -Source files are partly derived from different other open source projects -and may follow different coding styles and conventions. - -If you do a PR fixing a bug or adding a feature, -please embrace the coding convention you see in the corresponding files, -so that the result fits well together. - -Do not refactor or rename things in the same PR -to make the diff small and the PR easy to review. - Project language is Java. +Code formatting is enforced via [Spotless](https://github.com/diffplug/spotless) Gradle plugin. +Auto-format all files by running `./gradlew spotlessApply` before opening a PR. +CI will fail if files are not formatted correctly so make sure to run the formatter before pushing. + +If you do a PR fixing a bug or adding a feature, do not refactor or rename things in the same PR +to make the diff small and the PR easy to review. + By using [Delta Chat Core](https://github.com/deltachat/deltachat-core-rust) there is already a strong separation between "UI" and "Model". Further separations and abstraction layers are often not helpful diff --git a/build.gradle b/build.gradle index 66116c4e1..0e0d19854 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' version '8.11.1' id 'com.google.gms.google-services' version '4.4.1' + id 'com.diffplug.spotless' version '8.3.0' } repositories { @@ -151,6 +152,31 @@ android { } +spotless { + java { + target 'src/*/java/**/*.java' + targetExclude 'src/main/java/chat/delta/**' // ignore auto-generated code + googleJavaFormat() // Google style = 2-space indent, matches Android Studio defaults + removeUnusedImports() + trimTrailingWhitespace() + endWithNewline() + } + format 'xml', { + target 'src/*/res/**/*.xml', 'src/*/AndroidManifest.xml' + eclipseWtp('xml') + leadingTabsToSpaces(2) + trimTrailingWhitespace() + endWithNewline() + } + groovy { + target '*.gradle' + greclipse() + leadingTabsToSpaces(2) + trimTrailingWhitespace() + endWithNewline() + } +} + dependencies { def media3_version = "1.8.0" // 1.9.0 need minSdkVersion 23 diff --git a/settings.gradle b/settings.gradle index 8aeca1ea1..492070dea 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,6 @@ pluginManagement { repositories { + gradlePluginPortal() google() mavenCentral() }