image: registry.gitlab.com/fdroid/fdroidserver:buildserver-bookworm stages: - lint - test - deploy # only create a pipeline if it is a merge request, not for plain # branches, unless that branch is master. workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_PIPELINE_SOURCE == "web"' - if: '$CI_PIPELINE_SOURCE == "webide"' - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' .base: tags: - saas-linux-medium-amd64 variables: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 before_script: - echo "org.gradle.caching=true" >> gradle.properties - test -e /etc/apt/sources.list.d/bookworm-backports.list || echo "deb http://deb.debian.org/debian bookworm-backports main" >> /etc/apt/sources.list - apt update - apt-get -qy install -t bookworm-backports --no-install-recommends git sdkmanager openjdk-17-jdk-headless - test -n "$ANDROID_HOME" || source /etc/profile.d/bsenv.sh - export cmdline_tools_latest="$ANDROID_HOME/cmdline-tools/latest/bin" - test -e $cmdline_tools_latest && export PATH="$cmdline_tools_latest:$PATH" - export GRADLE_USER_HOME=$PWD/.gradle - export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdk = "\([0-9][0-9]*\)".*,\1,p' gradle/libs.versions.toml` - echo y | sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" > /dev/null # index-v1.jar tests need SHA1 support still, TODO use apksig to validate JAR sigs - sed -i 's,SHA1 denyAfter 20[0-9][0-9],SHA1 denyAfter 2026,' /usr/lib/jvm/java-17-openjdk-amd64/conf/security/java.security after_script: # this file changes every time but should not be cached - rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock - rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/ cache: key: '${CI_PROJECT_PATH}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}' paths: - .gradle/wrapper - .gradle/caches .test-template: &test-template extends: .base stage: test artifacts: name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}" paths: - kernel.log - logcat.txt - app/core* - app/*.log - app/build/reports - app/build/outputs/*ml - app/build/outputs/apk - libs/*/build/reports - build/reports reports: junit: - app/build/**/TEST-*.xml - libs/*/build/**/TEST-*.xml expire_in: 1 week when: on_failure after_script: - echo "Download debug artifacts from https://gitlab.com/${CI_PROJECT_PATH}/-/jobs" # this file changes every time but should not be cached - rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock - rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/ .always-on-these-changes: &always-on-these-changes changes: - .gitlab-ci.yml - build.gradle - settings.gradle - gradle/libs.versions.toml app assembleRelease test: <<: *test-template rules: - <<: *always-on-these-changes - changes: - app/**/* - libs/**/* script: - ./gradlew :app:assembleRelease :app:assembleDebug :app:testFullDebugUnitTest artifacts: name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}" paths: - app/build/reports - app/build/outputs/apk - libs/*/build/reports reports: junit: - app/build/test-results/*/TEST-*.xml expire_in: 1 week when: always libs db test: <<: *test-template rules: - <<: *always-on-these-changes - changes: - libs/database/**/* script: - ./gradlew :libs:database:testDebugUnitTest libs download test: <<: *test-template rules: - <<: *always-on-these-changes - changes: - libs/download/**/* script: - ./gradlew :libs:download:testDebugUnitTest libs index test: <<: *test-template rules: - <<: *always-on-these-changes - changes: - libs/index/**/* script: - ./gradlew :libs:index:testDebugUnitTest app lint checkstyle: <<: *test-template stage: lint rules: - <<: *always-on-these-changes - changes: - app/**/* script: # always report on lint errors to the build log - sed -i -e 's,textReport .*,textReport true,' app/build.gradle # the tasks "lint", "test", etc don't always include everything - ./gradlew :app:lint :app:checkstyle :app:ktlintCheck libs lint ktlintCheck: <<: *test-template stage: lint rules: - <<: *always-on-these-changes - changes: - libs/**/* script: # always report on lint errors to the build log - sed -i -e 's,textReport .*,textReport true,' app/build.gradle - ./gradlew :libs:database:lint :libs:download:lint :libs:index:lint ktlintCheck checkLegacyAbi # Reference: https://gitlab.com/components/code-quality-oss/codequality-os-scanners-integration/-/blob/4121970daed111dda84cab4547e1f2951684653c/templates/pmd.yml#L52-92 app lint pmd: stage: lint image: name: registry.gitlab.com/gitlab-ci-utils/gitlab-pmd-cpd:latest entrypoint: [ "" ] rules: - <<: *always-on-these-changes - changes: - app/**/* parallel: matrix: - PMD_VARIANT: main PMD_RULESETS: "config/pmd/rules.xml,config/pmd/rules-main.xml" PMD_FILE_PATHS: - "app/src/main/java" - PMD_VARIANT: test PMD_RULESETS: "config/pmd/rules.xml,config/pmd/rules-test.xml" PMD_FILE_PATHS: - "app/src/test/java" - "app/src/androidTest/java" before_script: - apt-get update - apt-get -qy install --no-install-recommends jq script: - find ${PMD_FILE_PATHS[@]} -type f -name '*.java' ! -path '/vendored/*' > .pmd-files.txt - pmd check --file-list .pmd-files.txt -R ${PMD_RULESETS} -f codeclimate -r gl-code-quality-not-formatted.json --no-fail-on-violation after_script: ## Fingerprint is required for reading Codequality: https://docs.gitlab.com/ee/ci/testing/code_quality.html#implement-a-custom-tool ## PMD output does not contain fingerprint. Following snippet generates a fingerprint with md5sum for each code quality item and adds a comma at end of each line to format as JSON array ## This returns true always. PMD rarely outputs codequality items which are not JSON conformant, because they are not properly escaped. ## For example \w+ instead of \\w+ Therefore following snippet ignores those issues, so that all other lines are represented in the report - | sed 's/\\/\\\\/g' gl-code-quality-not-formatted.json | while IFS= read -r line; do fingerprint=$(echo -n "$line" | md5sum | awk '{print $1}'); echo "$line" | jq -c --arg fp "$fingerprint" '. + {fingerprint: $fp}' | sed 's/$/,/'; done > gl-pmd-${PMD_VARIANT}-report.json || true # adds square bracket at the beginning for JSON array - sed -i '1s/^/[/' gl-pmd-${PMD_VARIANT}-report.json # adds square bracket at the end for JSON array - sed -i '$s/,$/]/' gl-pmd-${PMD_VARIANT}-report.json artifacts: paths: - gl-pmd-${PMD_VARIANT}-report.json reports: codequality: gl-pmd-${PMD_VARIANT}-report.json when: always app tools scripts: stage: lint image: debian:bookworm-slim rules: - <<: *always-on-these-changes - changes: - app/**/* script: - apt-get update - apt-get -qy install --no-install-recommends git python3 - ./tools/check-format-strings.py - ./tools/check-fastlane-whitespace.py - ./tools/remove-unused-and-blank-translations.py - echo "These are unused or blank translations that should be removed:" - git --no-pager diff --ignore-all-space --name-only --exit-code app/src/*/res/values*/strings.xml app weblate merge conflict: stage: lint image: debian:bookworm-slim rules: - changes: - .gitlab-ci.yml - app/src/*/res/values*/strings.xml - metadata/* script: - apt-get update - apt-get -qy install --no-install-recommends ca-certificates git - git config user.name "$CI_PIPELINE_ID/$CI_JOB_ID" - git config user.email $CI_PROJECT_PATH@f-droid.org - git fetch https://hosted.weblate.org/git/f-droid/f-droid - git checkout -B weblate FETCH_HEAD - export EXITVALUE=0 - if ! git rebase $CI_COMMIT_SHA; then export EXITVALUE=1; set -x; while git rebase --skip; do echo; done; set +x; fi - git diff --exit-code - exit $EXITVALUE app errorprone: extends: .base stage: lint rules: - <<: *always-on-these-changes - changes: - app/**/* script: - sed -i "s@plugins {@plugins{\nid 'net.ltgt.errorprone' version '3.1.0'@" app/build.gradle - cat config/errorprone.gradle >> app/build.gradle - ./gradlew -Dorg.gradle.dependency.verification=lenient assembleDebug libs database schema: stage: lint image: debian:bookworm-backports rules: - <<: *always-on-these-changes - changes: - libs/database/**/* variables: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 script: - apt-get update - apt-get -qy --no-install-recommends install openjdk-17-jdk-headless git sdkmanager - export ANDROID_HOME=/opt/android-sdk - export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdk = "\([0-9][0-9]*\)".*,\1,p' gradle/libs.versions.toml` - sdkmanager "platforms;android-$ANDROID_COMPILE_SDK" "build-tools;$ANDROID_COMPILE_SDK.0.0" - sdkmanager "build-tools;34.0.0" # something (AGP?) still pulls in old build-tools - sdkmanager "build-tools;35.0.0" # something (AGP?) still pulls in old build-tools - ./gradlew :libs:database:kspDebugKotlin - git --no-pager diff --exit-code # Run the tests in the emulator. Each step is broken out to run on # its own since the CI runner can have limited RAM, and the emulator # can take a while to start. # # once these prove stable, the task should be switched to # connectedCheck to test all the build flavors .kvm-connected-template: &kvm-connected-template extends: .base image: briar/ci-image-android-emulator:latest tags: - kvm cache: [] script: - ./gradlew assembleFullDebug - export AVD_SDK=`echo $CI_JOB_NAME | awk '{print $2}'` - export AVD_TAG=`echo $CI_JOB_NAME | awk '{print $3}'` - export AVD_ARCH=`echo $CI_JOB_NAME | awk '{print $4}'` - export AVD_PACKAGE="system-images;android-${AVD_SDK};${AVD_TAG};${AVD_ARCH}" - echo $AVD_PACKAGE - $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager --verbose delete avd --name "$NAME_AVD" - export AVD="$AVD_PACKAGE" - echo y | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install "$AVD" - echo no | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager --verbose create avd --name "$NAME_AVD" --package "$AVD" --device "pixel" - df -h - start-emulator.sh - ./gradlew installFullDebug - adb shell am start -n org.fdroid.fdroid.debug/org.fdroid.fdroid.views.main.MainActivity - export FLAG="-Pandroid.testInstrumentationRunnerArguments.notAnnotation=androidx.test.filters.LargeTest,androidx.test.filters.FlakyTest" - ./gradlew $FLAG :app:connectedFullDebugAndroidTest :libs:database:connectedCheck :libs:download:connectedCheck :libs:index:connectedCheck - export FLAG="-Pandroid.testInstrumentationRunnerArguments.annotation=androidx.test.filters.FlakyTest" - for i in {1..5}; do echo "$i" && ./gradlew $FLAG :app:connectedFullDebugAndroidTest :libs:database:connectedCheck :libs:download:connectedCheck :libs:index:connectedCheck && break; done || exit 137 allow_failure: exit_codes: 137 kvm 24 default x86: <<: *test-template <<: *kvm-connected-template pages: extends: .base stage: deploy only: - master script: - ./gradlew :libs:core:dokkaGenerateHtml :libs:download:dokkaGenerateHtml :libs:index:dokkaGenerateHtml :libs:database:dokkaGenerateHtml - mkdir -p public/libs - touch public/index.html public/libs/index.html - cp -r libs/core/build/dokka/html public/libs/core - cp -r libs/download/build/dokka/html public/libs/download - cp -r libs/index/build/dokka/html public/libs/index - cp -r libs/database/build/dokka/html public/libs/database artifacts: paths: - public deploy_nightly: extends: .base stage: deploy only: - master variables: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 script: - test -z "$DEBUG_KEYSTORE" && exit 0 - apt-get install -t bookworm-backports androguard fdroidserver - sed -i 's,.*,F-Nightly,' app/src/main/res/values*/strings.xml # add this nightly repo as a enabled repo - sed -i -e '/<\/string-array>/d' -e '/<\/resources>/d' app/src/main/res/values/default_repos.xml - echo "${CI_PROJECT_PATH}-nightly" >> app/src/main/res/values/default_repos.xml - echo "${CI_PROJECT_URL}-nightly/-/raw/master/fdroid/repo" >> app/src/main/res/values/default_repos.xml - cat config/nightly-repo/repo.xml >> app/src/main/res/values/default_repos.xml - export DB=`sed -n 's,.*version *= *\([0-9][0-9]*\).*,\1,p' libs/database/src/main/java/org/fdroid/database/FDroidDatabase.kt` - export versionCode=`printf '%d%05d' $DB $(date '+%s'| cut -b1-8)` - sed -i "s,^\(\s*versionCode\) *[0-9].*,\1 $versionCode," app/build.gradle # build the APKs! - ./gradlew assembleDebug # taken from fdroiddata/.gitlab-ci.yml as a tmp workaround until this is released: # https://gitlab.com/fdroid/fdroidserver/-/merge_requests/1666 - rm -rf $fdroidserver - mkdir $fdroidserver - git ls-remote https://gitlab.com/fdroid/fdroidserver.git master - curl --silent https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz | tar -xz --directory=$fdroidserver --strip-components=1 - export PATH="$fdroidserver:$PATH" - export PYTHONPATH="$fdroidserver:$fdroidserver/examples" - export PYTHONUNBUFFERED=true - fdroid nightly -v