diff --git a/.github/actions/disk-cleanup/action.yml b/.github/actions/disk-cleanup/action.yml new file mode 100644 index 00000000000..862cfd95c92 --- /dev/null +++ b/.github/actions/disk-cleanup/action.yml @@ -0,0 +1,37 @@ +name: Disk cleanup +description: Clean up disk space by removing unnecessary files +runs: + using: 'composite' + steps: + - name: Clean up unnecessary files + shell: bash + run: | + # Remove Java JDKs + sudo rm -rf /usr/lib/jvm + + # Remove .NET SDKs + sudo rm -rf /usr/share/dotnet + + # Remove Swift toolchain + sudo rm -rf /usr/share/swift + + # Remove Haskell (GHC) + sudo rm -rf /usr/local/.ghcup + + # Remove Julia + sudo rm -rf /usr/local/julia* + + # Remove Chromium (optional if not using for browser tests) + sudo rm -rf /usr/local/share/chromium + + # Remove Microsoft/Edge and Google Chrome builds + sudo rm -rf /opt/microsoft /opt/google + + # Remove Azure CLI + sudo rm -rf /opt/az + + # Remove PowerShell + sudo rm -rf /usr/local/share/powershell + + # Remove toolcaches + sudo rm -rf /opt/hostedtoolcache diff --git a/.github/actions/disk-usage/action.yml b/.github/actions/disk-usage/action.yml new file mode 100644 index 00000000000..e146b8bdb16 --- /dev/null +++ b/.github/actions/disk-usage/action.yml @@ -0,0 +1,24 @@ +name: Disk usage +description: Show disk usage +runs: + using: 'composite' + steps: + - name: Total runner disk usage + shell: bash + run: df -h / + + - name: Workspace usage + shell: bash + run: du -sh $GITHUB_WORKSPACE || true + + - name: Gradle user home usage + shell: bash + run: du -sh ~/.gradle || true + + - name: Gradle cache usage + shell: bash + run: du -sh ~/.gradle/caches || true + + - name: Build outputs usage + shell: bash + run: du -sh build app-*/build || true diff --git a/.github/actions/setup-gradle/action.yml b/.github/actions/setup-gradle/action.yml new file mode 100644 index 00000000000..17e65a78b59 --- /dev/null +++ b/.github/actions/setup-gradle/action.yml @@ -0,0 +1,34 @@ +name: Set up Gradle build environment +description: Prepares environment for building with JDK and Gradle +inputs: + run-release: + description: 'Whether to run in release mode (true/false). In release mode, Gradle cache is not used.' + required: false + default: 'false' + add-job-summary: + description: 'Whether to add a job summary (always, never, on-failure).' + required: false + default: 'always' + write-cache: + description: 'Whether to write to the cache (true/false).' + required: false + default: 'false' +runs: + using: 'composite' + steps: + - name: Copy CI gradle.properties + shell: bash + run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties + + - name: Set up JDK + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: 'temurin' + java-version: '21' + + - name: Set up Gradle without cache + uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0 + with: + cache-disabled: ${{ inputs.run-release }} + add-job-summary: ${{ inputs.add-job-summary }} + cache-read-only: ${{ inputs.write-cache == 'false' || inputs.run-release == 'true' }} diff --git a/.github/ci-gradle.properties b/.github/ci-gradle.properties index 4865dffa9f0..d329ec204a9 100644 --- a/.github/ci-gradle.properties +++ b/.github/ci-gradle.properties @@ -1,7 +1,10 @@ -org.gradle.daemon=false +org.gradle.daemon=true org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.configuration-cache.parallel=true org.gradle.workers.max=4 -org.gradle.jvmargs=-Xmx10g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx10g -XX:MaxMetaspaceSize=4g -Dfile.encoding=UTF-8 -XX:+UseParallelGC -kotlin.incremental=false +kotlin.incremental=true kotlin.compiler.execution.strategy=in-process diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a0ab4392698..4d634ef05c9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,26 @@ version: 2 -commit-message: - prefix: chore - include: scope -labels: - - "type: dependency" updates: + # Dependabot does not support GitHub composite actions by default (.github/actions) + # so we need to add the folder by hand to the directories entry. - package-ecosystem: "github-actions" + directories: + - "/" + - "/.github/actions/*" + schedule: + interval: "weekly" + labels: + - "type: dependency" + - "type: github actions" + commit-message: + prefix: chore + include: scope + - package-ecosystem: "gradle" directory: "/" schedule: interval: "weekly" + labels: + - "type: dependency" + - "type: gradle" + commit-message: + prefix: chore + include: scope diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml deleted file mode 100644 index 2d00420305f..00000000000 --- a/.github/workflows/android.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Android CI - -on: - pull_request: - paths-ignore: - - '.idea/**' - - '.gitattributes' - - '.github/**.json' - - '.gitignore' - - '.gitmodules' - - '**.md' - - 'LICENSE' - - 'NOTICE' - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - timeout-minutes: 90 - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Copy CI gradle.properties - run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 - - - name: Quality - Spotless - run: ./gradlew spotlessCheck - - - name: Quality - Detekt - run: ./gradlew detekt - - - name: Quality - Lint - run: ./gradlew lint - - - name: Quality - Dependency Guard - run: ./gradlew dependencyGuard - - - name: Build (run full build and tests) - run: ./gradlew build diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 00000000000..77d2f916026 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,158 @@ +name: Android CI + +on: + push: + branches: + - main + pull_request: + paths-ignore: + - '.idea/**' + - '.gitattributes' + - '.github/**.json' + - '.gitignore' + - '.gitmodules' + - '**.md' + - 'LICENSE' + - 'NOTICE' + +permissions: + contents: read + +concurrency: + group: android-ci-${{ github.ref }}-${{ github.event.pull_request.number || 'no-pr' }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-common: + name: Build common code + runs-on: ubuntu-latest + timeout-minutes: 90 + + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Show disk usage + uses: ./.github/actions/disk-usage + + - name: Cleanup disk + uses: ./.github/actions/disk-cleanup + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + with: + write-cache: ${{ github.ref == 'refs/heads/main' }} + + - name: Prime configuration and dependency cache + run: ./gradlew --no-daemon help + + - name: Assemble common + run: ./gradlew :app-common:assemble + + - name: Show disk usage + uses: ./.github/actions/disk-usage + + build-k9: + name: Build K9 application + runs-on: ubuntu-latest + timeout-minutes: 90 + needs: [build-common] + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Build K9 application + run: ./gradlew :app-k9mail:assemble + + - name: Check K9 Badging + run: | + ./gradlew :app-k9mail:checkFossReleaseBadging \ + :app-k9mail:checkFullReleaseBadging \ + -x assemble \ + -x build + + build-thunderbird: + name: Build Thunderbird application + runs-on: ubuntu-latest + timeout-minutes: 90 + needs: [build-common] + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Build Thunderbird application + run: ./gradlew :app-thunderbird:assemble + + - name: Check Thunderbird Badging + run: | + ./gradlew :app-thunderbird:checkFossBetaBadging \ + :app-thunderbird:checkFossDailyBadging \ + :app-thunderbird:checkFossReleaseBadging \ + :app-thunderbird:checkFullBetaBadging \ + :app-thunderbird:checkFullDailyBadging \ + :app-thunderbird:checkFullReleaseBadging \ + -x assemble \ + -x build + + build-ui-catalog: + name: Build UI-catalog application + runs-on: ubuntu-latest + timeout-minutes: 90 + needs: [build-common] + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Build App UI-catalog application in Debug mode + run: ./gradlew :app-ui-catalog:assembleDebug + + quality-unit-test: + name: Quality - Unit tests + runs-on: ubuntu-latest + timeout-minutes: 90 + needs: [build-common] + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Running unit tests + run: ./gradlew testsOnCi --parallel + + quality-lint: + name: Quality - Lint + runs-on: ubuntu-latest + timeout-minutes: 90 + needs: [build-common] + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Running Android lint + run: ./gradlew lint diff --git a/.github/workflows/build-cli-tools.yml b/.github/workflows/build-cli-tools.yml new file mode 100644 index 00000000000..9e75cfecbf4 --- /dev/null +++ b/.github/workflows/build-cli-tools.yml @@ -0,0 +1,35 @@ +name: CLI Tools CI + +on: + push: + branches: + - main + paths: + - 'cli/**' + pull_request: + paths: + - 'cli/**' + +permissions: + contents: read + +concurrency: + group: cli-tools-ci-${{ github.ref }}-${{ github.event.pull_request.number || 'no-pr' }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-cli-tools: + name: Build CLI tools + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Build CLI tools + run: ./gradlew buildCliTools diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index c0b508ccadb..00000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: CodeQL - Code scanning - -on: - schedule: - - cron: '0 10 * * 1' - workflow_dispatch: - -permissions: - contents: read - -jobs: - codeql-scan: - - strategy: - fail-fast: false - - runs-on: ubuntu-latest - - permissions: - security-events: write - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 - with: - cache-read-only: true - - - uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 - with: - languages: java - - - name: Autobuild - uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 - diff --git a/.github/workflows/dependabot-dependency-guard-update.yml b/.github/workflows/dependabot-dependency-guard-update.yml new file mode 100644 index 00000000000..37bd04f2417 --- /dev/null +++ b/.github/workflows/dependabot-dependency-guard-update.yml @@ -0,0 +1,69 @@ +name: dependabot PR - Update dependency guard + +on: + pull_request_target: + types: + - opened + - synchronize + - reopened + branches: + - main + paths: + - '**/*.gradle' + - 'gradle/**' + - 'gradlew' + - '**/libs.versions.toml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event.pull_request.number || 'no-pr' }} + cancel-in-progress: true + +jobs: + update-dependency-guard: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + environment: botmobile + timeout-minutes: 90 + steps: + - name: App Token Generate + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + if: ${{ vars.BOT_CLIENT_ID }} + id: app-token + with: + app-id: ${{ vars.BOT_CLIENT_ID }} + private-key: ${{ secrets.BOT_PRIVATE_KEY }} + + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + ref: ${{ github.head_ref }} + token: ${{ steps.app-token.outputs.token || github.token }} + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Update dependency guard + run: ./gradlew :dependencyGuardBaseline + + - name: Commit and push changes if any + env: + APP_SLUG: ${{ steps.app-token.outputs.app-slug || 'github-actions'}} + APP_USER_ID: ${{ vars.BOT_USER_ID || '41898282' }} + run: | + set -x + + git config --global user.name "${APP_SLUG}" + git config --global user.email "${APP_USER_ID}+${APP_SLUG}[bot]@users.noreply.github.com" + git add . + if ! git diff --cached --quiet; then + git config user.name + git config user.email + git status + git commit -m "chore(deps): Update dependency guard files on behalf of @dependabot" + git log -n 2 + git push + else + echo "No changes to commit" + fi + + set +x diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 7b97f6d993d..39cd855c395 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -21,7 +21,7 @@ jobs: environment: botmobile steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/fluidscan.yml b/.github/workflows/fluidscan.yml index 32b918cacd9..6a9e6e9eb5f 100644 --- a/.github/workflows/fluidscan.yml +++ b/.github/workflows/fluidscan.yml @@ -35,6 +35,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 + uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 with: sarif_file: fluidscan-results.sarif diff --git a/.github/workflows/gradle-cache.yml b/.github/workflows/gradle-cache.yml deleted file mode 100644 index c4802e57060..00000000000 --- a/.github/workflows/gradle-cache.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Update Gradle build cache - -on: - push: - branches: - - main - paths-ignore: - - '.idea/**' - - '.gitattributes' - - '.github/**.json' - - '.gitignore' - - '.gitmodules' - - '**.md' - - 'LICENSE' - - 'NOTICE' - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 - - - name: Build (run full build and tests) - run: ./gradlew build diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index 7923862dfba..42538528f51 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -22,16 +22,8 @@ jobs: - name: Install mdbook and extensions run: ./docs/install.sh - - name: Copy CI gradle.properties - run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle - name: Quality - Spotless Markdown Check run: ./gradlew spotlessFlexmarkCheck diff --git a/.github/workflows/needinfo-answered.yml b/.github/workflows/needinfo-answered.yml index 889578467e8..231abac1a1b 100644 --- a/.github/workflows/needinfo-answered.yml +++ b/.github/workflows/needinfo-answered.yml @@ -22,7 +22,7 @@ jobs: pull-requests: write steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/needinfo-remove.yml b/.github/workflows/needinfo-remove.yml index 6a82ee3d1d7..679b8096007 100644 --- a/.github/workflows/needinfo-remove.yml +++ b/.github/workflows/needinfo-remove.yml @@ -24,7 +24,7 @@ jobs: pull-requests: write steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/needinfo-stale.yml b/.github/workflows/needinfo-stale.yml index e3c216cbd03..6e3312d90b9 100644 --- a/.github/workflows/needinfo-stale.yml +++ b/.github/workflows/needinfo-stale.yml @@ -19,7 +19,7 @@ jobs: pull-requests: write steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/pulls-auto-assign.yml b/.github/workflows/pulls-auto-assign.yml index 741c5871e63..d11ebb25459 100644 --- a/.github/workflows/pulls-auto-assign.yml +++ b/.github/workflows/pulls-auto-assign.yml @@ -13,7 +13,7 @@ jobs: environment: botmobile steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/pulls-merged.yml b/.github/workflows/pulls-merged.yml index afa35fe1ea5..ac3e94edafc 100644 --- a/.github/workflows/pulls-merged.yml +++ b/.github/workflows/pulls-merged.yml @@ -19,7 +19,7 @@ jobs: environment: botmobile steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/pulls-opened.yml b/.github/workflows/pulls-opened.yml index f366551e9b7..225c80971a9 100644 --- a/.github/workflows/pulls-opened.yml +++ b/.github/workflows/pulls-opened.yml @@ -17,7 +17,7 @@ jobs: environment: botmobile steps: - name: App token generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: diff --git a/.github/workflows/quality-checks.yml b/.github/workflows/quality-checks.yml new file mode 100644 index 00000000000..c3493662262 --- /dev/null +++ b/.github/workflows/quality-checks.yml @@ -0,0 +1,98 @@ +name: Quality checks + +on: + push: + branches: + - main + pull_request: + paths-ignore: + - '.idea/**' + - '.gitattributes' + - '.github/**.json' + - '.gitignore' + - '.gitmodules' + - '**.md' + - 'LICENSE' + - 'NOTICE' + +concurrency: + group: quality-checks-${{ github.ref }}-${{ github.event.pull_request.number || 'no-pr' }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + quality-spotless: + name: Spotless check + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Quality - Spotless + run: ./gradlew spotlessCheck + + quality-detekt: + name: Detekt check + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Quality - Detekt + run: ./gradlew detekt + + - name: Running Detekt including KMP + # As we were not verifying detekt in KMP sources before, + # this step is likely to fail. + continue-on-error: true + run: | + ./gradlew detektMetadataCommonMain + ./gradlew detektMetadataMain + ./gradlew detektMetadataCommonJvmMain + + quality-dependency-guard: + name: Dependency guard check + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Quality - Dependency guard + run: ./gradlew dependencyGuard + + quality-konsist: + name: Konsist check + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout the repo + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 1 + + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle + + - name: Quality - Konsist + run: ./gradlew :quality:konsist:test diff --git a/.github/workflows/quality-codeql.yml b/.github/workflows/quality-codeql.yml new file mode 100644 index 00000000000..9e7c30e5545 --- /dev/null +++ b/.github/workflows/quality-codeql.yml @@ -0,0 +1,51 @@ +name: Quality - CodeQL Scan + +on: + schedule: + - cron: '0 10 * * 1' + workflow_dispatch: + +permissions: + contents: read + +jobs: + quality-codeql-scan: + name: Quality - CodeQL Scan + + permissions: + # required to upload analysis results + security-events: write + # required to fetch internal or private CodeQL packs + packages: read + + strategy: + fail-fast: false + matrix: + include: + - language: 'actions' + build-mode: 'none' + - language: 'java-kotlin' + build-mode: 'autobuild' + - language: 'python' + build-mode: 'none' + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Gradle environment + if: matrix.language == 'java-kotlin' + uses: ./.github/actions/setup-gradle + + - name: Initialize CodeQL + uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3d92a1ba7e9..50cb063b720 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -38,7 +38,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif @@ -62,6 +62,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 + uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 with: sarif_file: results.sarif diff --git a/.github/workflows/shippable_builds.yml b/.github/workflows/shippable_builds.yml index 3c638baaef1..fe2358efd10 100644 --- a/.github/workflows/shippable_builds.yml +++ b/.github/workflows/shippable_builds.yml @@ -206,7 +206,7 @@ jobs: new_version_code: ${{ steps.new_version_code.outputs.new_version_code }} steps: - name: App Token Generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ vars.BOT_CLIENT_ID }} id: app-token with: @@ -220,22 +220,11 @@ jobs: fetch-depth: 0 token: ${{ steps.app-token.outputs.token || github.token }} - - name: Copy CI gradle.properties - if: ${{ contains(matrix.releaseTarget, 'github') || needs.dump_config.outputs.releaseType == 'daily' }} - shell: bash - run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 - if: ${{ contains(matrix.releaseTarget, 'github') || needs.dump_config.outputs.releaseType == 'daily' }} - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Setup Gradle environment if: ${{ contains(matrix.releaseTarget, 'github') || needs.dump_config.outputs.releaseType == 'daily' }} + uses: ./.github/actions/setup-gradle with: - cache-disabled: "${{ contains(fromJSON('[\"beta\", \"release\"]'), needs.dump_config.outputs.releaseType) }}" + run-release: "${{ contains(fromJSON('[\"beta\", \"release\"]'), needs.dump_config.outputs.releaseType) }}" add-job-summary: never - name: Get application info @@ -470,19 +459,10 @@ jobs: with: ref: ${{ steps.sha.outputs.app_sha }} - - name: Copy CI gradle.properties - shell: bash - run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Setup Gradle environment + uses: ./.github/actions/setup-gradle with: - cache-disabled: "${{ contains(fromJSON('[\"beta\", \"release\"]'), needs.dump_config.outputs.releaseType) }}" + run-release: "${{ contains(fromJSON('[\"beta\", \"release\"]'), needs.dump_config.outputs.releaseType) }}" add-job-summary: on-failure - name: Set Version Code for Daily @@ -765,7 +745,7 @@ jobs: ls -l uploads/${PKG_FILE_PRETTY} - name: App Token Generate - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: ${{ contains(matrix.releaseTarget, 'github') && vars.BOT_CLIENT_ID }} id: app-token with: @@ -775,7 +755,7 @@ jobs: - name: Publish to GitHub Releases id: publish_gh if: ${{ contains(matrix.releaseTarget, 'github') }} - uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2 + uses: softprops/action-gh-release@62c96d0c4e8a889135c1f3a25910db8dbe0e85f7 # v2.3.4 with: token: ${{ steps.app-token.outputs.token || github.token }} target_commitish: ${{ steps.shanotes.outputs.app_sha }} @@ -913,7 +893,7 @@ jobs: - name: Auth to GCS for FTP if: ${{ !inputs.skipFtp && contains(matrix.releaseTarget, 'ftp') && matrix.packageFormat == 'apk' }} - uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12 + uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0 with: service_account: ${{ steps.prepare_ftp.outputs.SERVICE_ACCOUNT }} workload_identity_provider: ${{ steps.prepare_ftp.outputs.WORKLOAD_IDENTITY_PROVIDER }} @@ -921,7 +901,7 @@ jobs: - name: GCS Upload of APK Package to FTP if: ${{ !inputs.skipFtp && contains(matrix.releaseTarget, 'ftp') && matrix.packageFormat == 'apk' }} - uses: google-github-actions/upload-cloud-storage@7c73f5d6eae167341002e9c946f7479a609c588e # v2.2.3 + uses: google-github-actions/upload-cloud-storage@6397bd7208e18d13ba2619ee21b9873edc94427a # v3.0.0 with: path: ${{ steps.prepare_ftp.outputs.FTP_LOCAL_PATH }}/${{ steps.rename.outputs.PKG_FILE }} destination: ${{ steps.prepare_ftp.outputs.FTP_DESTINATION }} @@ -929,7 +909,7 @@ jobs: - name: GCS Upload of APK Package to FTP Nightly Latest if: ${{ !inputs.skipFtp && contains(matrix.releaseTarget, 'ftp') && matrix.packageFormat == 'apk' && needs.dump_config.outputs.releaseType == 'daily'}} - uses: google-github-actions/upload-cloud-storage@7c73f5d6eae167341002e9c946f7479a609c588e # v2.2.3 + uses: google-github-actions/upload-cloud-storage@6397bd7208e18d13ba2619ee21b9873edc94427a # v3.0.0 with: path: ${{ steps.prepare_ftp.outputs.FTP_LOCAL_PATH_NIGHTLY_LATEST }}/${{ steps.rename.outputs.PKG_FILE }} destination: ${{ steps.prepare_ftp.outputs.FTP_DESTINATION_NIGHTLY_LATEST }} @@ -937,7 +917,7 @@ jobs: - name: GCS Upload of Source Tar to FTP if: ${{ !inputs.skipFtp && contains(matrix.releaseTarget, 'ftp') && matrix.packageFormat == 'apk' }} - uses: google-github-actions/upload-cloud-storage@7c73f5d6eae167341002e9c946f7479a609c588e # v2.2.3 + uses: google-github-actions/upload-cloud-storage@6397bd7208e18d13ba2619ee21b9873edc94427a # v3.0.0 with: path: ${{ steps.prepare_ftp.outputs.FTP_LOCAL_PATH }}/${{ steps.generate_tar.outputs.FTP_TAR_FILENAME }} destination: ${{ steps.prepare_ftp.outputs.FTP_DESTINATION }} @@ -945,7 +925,7 @@ jobs: - name: GCS Upload of Source Tar to FTP Nightly Latest if: ${{ !inputs.skipFtp && contains(matrix.releaseTarget, 'ftp') && matrix.packageFormat == 'apk' && needs.dump_config.outputs.releaseType == 'daily'}} - uses: google-github-actions/upload-cloud-storage@7c73f5d6eae167341002e9c946f7479a609c588e # v2.2.3 + uses: google-github-actions/upload-cloud-storage@6397bd7208e18d13ba2619ee21b9873edc94427a # v3.0.0 with: path: ${{ steps.prepare_ftp.outputs.FTP_LOCAL_PATH_NIGHTLY_LATEST }}/${{ steps.generate_tar.outputs.FTP_TAR_FILENAME }} destination: ${{ steps.prepare_ftp.outputs.FTP_DESTINATION_NIGHTLY_LATEST }} diff --git a/.github/workflows/validate-gradle.yml b/.github/workflows/validate-gradle.yml index 5ff70c3aaab..9592c187d24 100644 --- a/.github/workflows/validate-gradle.yml +++ b/.github/workflows/validate-gradle.yml @@ -12,4 +12,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: gradle/actions/wrapper-validation@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - uses: gradle/actions/wrapper-validation@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4 diff --git a/build-plugin/src/main/kotlin/AndroidExtension.kt b/build-plugin/src/main/kotlin/AndroidExtension.kt index cdd65911aa6..81395391ec0 100644 --- a/build-plugin/src/main/kotlin/AndroidExtension.kt +++ b/build-plugin/src/main/kotlin/AndroidExtension.kt @@ -25,6 +25,7 @@ internal fun CommonExtension<*, *, *, *, *, *>.configureSharedConfig(project: Pr checkDependencies = true lintConfig = project.file("${project.rootProject.projectDir}/config/lint/lint.xml") baseline = project.file("${project.rootProject.projectDir}/config/lint/android-lint-baseline.xml") + checkReleaseBuilds = System.getenv("CI_CHECK_RELEASE_BUILDS")?.toBoolean() ?: true } testOptions { diff --git a/build.gradle.kts b/build.gradle.kts index 9df7fb608dd..40d615ab43e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,9 +37,17 @@ tasks.register("testsOnCi") { val skipTests = setOf("testReleaseUnitTest") dependsOn( - subprojects.map { project -> project.tasks.withType(Test::class.java) } - .flatten() - .filterNot { task -> task.name in skipTests }, + subprojects + .filterNot { it.path == ":quality:konsist" } // Konsist tests should be run separately + .flatMap { it.tasks.withType(Test::class.java) } + .filterNot { it.name in skipTests }, + ) +} + +tasks.register("buildCliTools") { + val cliToolsProjects = subprojects.filter { it.path.startsWith(":cli:") } + dependsOn( + cliToolsProjects.map { project -> project.tasks.named("build") }, ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 12d89abd31a..6b366febca3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -101,7 +101,7 @@ mozillaAndroidComponents = "141.0.1" okhttp = "4.12.0" okio = "3.16.0" preferencesFix = "1.1.0" -robolectric = "4.15.1" +robolectric = "4.16" safeContentResolver = "1.0.0" searchPreference = "2.7.3" spotlessPlugin = "7.2.1" diff --git a/quality/konsist/build.gradle.kts b/quality/konsist/build.gradle.kts index a9e018eeb37..7e1490f737c 100644 --- a/quality/konsist/build.gradle.kts +++ b/quality/konsist/build.gradle.kts @@ -3,10 +3,17 @@ plugins { } kotlin { - jvmToolchain(11) + jvmToolchain { + languageVersion = JavaLanguageVersion.of(11) + vendor = JvmVendorSpec.ADOPTIUM + } } dependencies { testImplementation(libs.konsist) testImplementation(libs.kotlin.test) } + +tasks.withType { + outputs.upToDateWhen { false } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 141ff5bd097..38a84c4d4ea 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,6 +17,10 @@ pluginManagement { } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + dependencyResolutionManagement { repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS repositories { @@ -249,14 +253,14 @@ include( ":feature:debug-settings", ) -check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { +check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { """ - Java 17+ is required to build Thunderbird for Android. + Java 21+ is required to build Thunderbird for Android. But it found an incompatible Java version ${{JavaVersion.current()}}. Java Home: [${System.getProperty("java.home")}] - Please install Java 17+ and set JAVA_HOME to the directory containing the Java 17+ installation. + Please install Java 21+ and set JAVA_HOME to the directory containing the Java 21+ installation. https://developer.android.com/build/jdks#jdk-config-in-studio """.trimIndent() }