From f5513a641e7da4572de205015cdfc53840a1457b Mon Sep 17 00:00:00 2001 From: YingYing Chen <40571804+YYChen01988@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:45:21 +0000 Subject: [PATCH 1/6] feat(OpenSSF) improve Pinned-Dependencies and Token-Permissions scores (#2103) --- .github/workflows/codeql.yml | 73 ++++++++++++------------ .github/workflows/downstream_updates.yml | 1 + dockerfiles/Dockerfile.android-common | 2 +- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 47ab8e0caf..7445ca76d4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -10,6 +10,7 @@ # supported CodeQL languages. # name: "CodeQL" +permissions: read-all on: push: @@ -42,49 +43,49 @@ jobs: # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 - with: - submodules: recursive - - uses: gradle/wrapper-validation-action@v1 + - name: Checkout repository + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 #v3.6.0 + with: + submodules: recursive + - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 #v1.1.0 - - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: 11 + - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 #v3.13.0 + with: + distribution: 'zulu' + java-version: 11 - - name: Gradle cache - uses: gradle/gradle-build-action@v2 + - name: Gradle cache + uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa #v2.12.0 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@396bb3e45325a47dd9ef434068033c6d5bb0d11a #v3.27.3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@396bb3e45325a47dd9ef434068033c6d5bb0d11a #v3.27.3 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@396bb3e45325a47dd9ef434068033c6d5bb0d11a #v3.27.3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/downstream_updates.yml b/.github/workflows/downstream_updates.yml index 20de33f516..68e06e182e 100644 --- a/.github/workflows/downstream_updates.yml +++ b/.github/workflows/downstream_updates.yml @@ -1,4 +1,5 @@ name: downstream-updates +permissions: read-all on: release: diff --git a/dockerfiles/Dockerfile.android-common b/dockerfiles/Dockerfile.android-common index db6b623797..a578127e1b 100644 --- a/dockerfiles/Dockerfile.android-common +++ b/dockerfiles/Dockerfile.android-common @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:20.04@sha256:8e5c4f0285ecbb4ead070431d29b576a530d3166df73ec44affc1cd27555141b RUN apt-get update > /dev/n RUN DEBIAN_FRONTEND=noninteractive apt-get install -y wget maven gnupg1 cppcheck libncurses5 jq clang-format unzip curl git From 0ed78cf9b7b4b2b3f1b440e20b3db33195e79bac Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 20 Nov 2024 14:51:03 +0000 Subject: [PATCH 2/6] test(mazerunner): include the mapping.txt file in the published end2end artifacts to aid test debugging --- scripts/copy-build-files.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/copy-build-files.rb b/scripts/copy-build-files.rb index c2bc1107c4..83ee16a9f6 100755 --- a/scripts/copy-build-files.rb +++ b/scripts/copy-build-files.rb @@ -8,6 +8,7 @@ FileUtils.mkdir_p destination FileUtils.cp "features/fixtures/mazerunner/app/build/outputs/apk/#{build_mode}/fixture-#{ndk_version}.apk", "build/fixture-#{ndk_version}.apk" +FileUtils.cp "features/fixtures/mazerunner/app/build/outputs/mapping/#{build_mode}/mapping.txt", "#{destination}/mapping.txt" fixture_dir = 'features/fixtures/mazerunner' cxx_base = "#{fixture_dir}/cxx-scenarios/build/intermediates" From 01ada616dd80d825b0487f105082aec81b959b10 Mon Sep 17 00:00:00 2001 From: Alex Moinet Date: Thu, 21 Nov 2024 16:29:18 +0000 Subject: [PATCH 3/6] Add signing workflow (#2109) --- .github/workflows/signing.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/signing.yml diff --git a/.github/workflows/signing.yml b/.github/workflows/signing.yml new file mode 100644 index 0000000000..199601bdff --- /dev/null +++ b/.github/workflows/signing.yml @@ -0,0 +1,30 @@ +name: Sign release assets + +on: + release: + types: [released] + workflow_dispatch: + inputs: + tag: + description: 'Tag to sign' + required: true + type: string +jobs: + sign-assets: + runs-on: ubuntu-latest + steps: + - name: Install gpg + run: | + sudo apt-get update + sudo apt-get install -y gnupg + - name: Import GPG key + run: | + echo "${{ secrets.PLATFORMS_GPG_KEY_BASE64 }}" | base64 --decode | gpg --batch --import + - name: Sign assets + uses: bugsnag/platforms-release-signer@main + with: + github_token: ${{ secrets.PLATFORMS_SIGNING_GITHUB_TOKEN }} + full_repository: ${{ github.repository }} + release_tag: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.event.release.tag_name }} + key_id: ${{ secrets.PLATFORMS_GPG_KEY_ID }} + key_passphrase: ${{ secrets.PLATFORMS_GPG_KEY_PASSPHRASE }} From 9737461b96b901663cb6fb05ae96a45f508efe57 Mon Sep 17 00:00:00 2001 From: jason Date: Fri, 15 Nov 2024 16:47:21 +0000 Subject: [PATCH 4/6] chore(build): replaced the buildSrc plugin with a simplified Versions object and moved the build structure down into the individual modules --- bugsnag-android-core/build.gradle.kts | 92 +++++-- bugsnag-android/build.gradle.kts | 14 +- bugsnag-benchmarks/build.gradle | 2 +- bugsnag-plugin-android-anr/build.gradle.kts | 67 ++++- .../build.gradle.kts | 70 +++++- bugsnag-plugin-android-ndk/build.gradle.kts | 70 +++++- .../build.gradle.kts | 57 ++++- bugsnag-plugin-react-native/build.gradle.kts | 56 ++++- build.gradle.kts | 38 +-- buildSrc/build.gradle.kts | 13 - buildSrc/settings.gradle.kts | 1 + .../{com/bugsnag/android => }/Checkstyle.kt | 2 - buildSrc/src/main/kotlin/ProjectDefaults.kt | 36 +++ buildSrc/src/main/kotlin/Versions.kt | 84 +++++++ .../com/bugsnag/android/BugsnagBuildPlugin.kt | 234 ------------------ .../android/BugsnagBuildPluginExtension.kt | 34 --- .../kotlin/com/bugsnag/android/Versions.kt | 31 --- settings.gradle.kts | 8 + 18 files changed, 525 insertions(+), 384 deletions(-) create mode 100644 buildSrc/settings.gradle.kts rename buildSrc/src/main/kotlin/{com/bugsnag/android => }/Checkstyle.kt (95%) create mode 100644 buildSrc/src/main/kotlin/ProjectDefaults.kt create mode 100644 buildSrc/src/main/kotlin/Versions.kt delete mode 100644 buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt delete mode 100644 buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPluginExtension.kt delete mode 100644 buildSrc/src/main/kotlin/com/bugsnag/android/Versions.kt diff --git a/bugsnag-android-core/build.gradle.kts b/bugsnag-android-core/build.gradle.kts index 52c5d28871..12024316a9 100644 --- a/bugsnag-android-core/build.gradle.kts +++ b/bugsnag-android-core/build.gradle.kts @@ -2,35 +2,77 @@ import kotlinx.validation.ApiValidationExtension import org.jetbrains.dokka.gradle.DokkaTask plugins { - id("bugsnag-build-plugin") + loadDefaultPlugins() } -bugsnagBuildOptions { - usesNdk = true +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android.core" - // pick up dsl-json by adding to the default sourcesets - android { - sourceSets { - named("main") { - java.srcDirs("dsl-json/library/src/main/java") - } - named("test") { - java.srcDirs( - "dsl-json/library/src/test/java", - "src/sharedTest/java" - ) - } - named("androidTest") { - java.srcDirs( - "src/sharedTest/java" - ) - } + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + + consumerProguardFiles("proguard-rules.pro") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + externalNativeBuild.cmake.arguments += BugsnagDefaults.cmakeArguments + + configureAbis(ndk.abiFilters) + } + + lint { + isAbortOnError = true + isWarningsAsErrors = true + isCheckAllWarnings = true + baseline(File(project.projectDir, "lint-baseline.xml")) + disable("GradleDependency", "NewerVersionAvailable") + } + + buildFeatures { + aidl = false + renderScript = false + shaders = false + resValues = false + buildConfig = false + } + + compileOptions { + sourceCompatibility = Versions.java + targetCompatibility = Versions.java + } + + testOptions { + unitTests { + isReturnDefaultValues = true + } + } + + sourceSets { + named("main") { + java.srcDirs("dsl-json/library/src/main/java") + } + + named("test") { + java.srcDirs( + "dsl-json/library/src/test/java", + "src/sharedTest/java" + ) + } + named("androidTest") { + java.srcDirs( + "src/sharedTest/java" + ) } } + + externalNativeBuild.cmake.path = project.file("CMakeLists.txt") + externalNativeBuild.cmake.version = Versions.Android.Build.cmakeVersion } -apply(plugin = "com.android.library") -apply(plugin = "org.jetbrains.dokka") +dependencies { + addCommonModuleDependencies() +} tasks.getByName("dokkaHtml") { dokkaSourceSets { @@ -47,3 +89,9 @@ tasks.getByName("dokkaHtml") { plugins.withId("org.jetbrains.kotlinx.binary-compatibility-validator") { project.extensions.getByType(ApiValidationExtension::class.java).ignoredPackages.add("com.bugsnag.android.repackaged.dslplatform.json") } + +apply(from = rootProject.file("gradle/detekt.gradle")) +apply(from = rootProject.file("gradle/license-check.gradle")) +apply(from = rootProject.file("gradle/release.gradle")) + +configureCheckstyle() diff --git a/bugsnag-android/build.gradle.kts b/bugsnag-android/build.gradle.kts index bd5c5a6162..af7c9ed5ac 100644 --- a/bugsnag-android/build.gradle.kts +++ b/bugsnag-android/build.gradle.kts @@ -1,10 +1,16 @@ plugins { - id("bugsnag-build-plugin") - id("com.android.library") + load(Versions.Plugins.AGP) + load(Versions.Plugins.licenseCheck) } -bugsnagBuildOptions { - compilesCode = false +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android" + + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + } } dependencies { diff --git a/bugsnag-benchmarks/build.gradle b/bugsnag-benchmarks/build.gradle index 3c794e9101..ea774a67a7 100644 --- a/bugsnag-benchmarks/build.gradle +++ b/bugsnag-benchmarks/build.gradle @@ -1,6 +1,6 @@ plugins { id "com.android.library" - id "androidx.benchmark" + id "androidx.benchmark" version "1.1.1" id "kotlin-android" } diff --git a/bugsnag-plugin-android-anr/build.gradle.kts b/bugsnag-plugin-android-anr/build.gradle.kts index 9f778ce9f9..dbae9dc178 100644 --- a/bugsnag-plugin-android-anr/build.gradle.kts +++ b/bugsnag-plugin-android-anr/build.gradle.kts @@ -1,13 +1,70 @@ plugins { - id("bugsnag-build-plugin") + loadDefaultPlugins() } -bugsnagBuildOptions { - usesNdk = true -} +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android.anr" + + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + + consumerProguardFiles("proguard-rules.pro") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + externalNativeBuild.cmake.arguments += listOf( + "-DANDROID_CPP_FEATURES=exceptions", + "-DANDROID_STL=c++_static" + ) + + configureAbis(ndk.abiFilters) + } + + lint { + isAbortOnError = true + isWarningsAsErrors = true + isCheckAllWarnings = true + baseline(File(project.projectDir, "lint-baseline.xml")) + disable("GradleDependency", "NewerVersionAvailable") + } + + buildFeatures { + aidl = false + renderScript = false + shaders = false + resValues = false + buildConfig = false + } -apply(plugin = "com.android.library") + compileOptions { + sourceCompatibility = Versions.java + targetCompatibility = Versions.java + } + + testOptions { + unitTests { + isReturnDefaultValues = true + } + } + + sourceSets { + named("test") { + java.srcDir(SHARED_TEST_SRC_DIR) + } + } + + externalNativeBuild.cmake.path = project.file("CMakeLists.txt") + externalNativeBuild.cmake.version = Versions.Android.Build.cmakeVersion +} dependencies { + addCommonModuleDependencies() add("api", project(":bugsnag-android-core")) } + +apply(from = rootProject.file("gradle/detekt.gradle")) +apply(from = rootProject.file("gradle/license-check.gradle")) +apply(from = rootProject.file("gradle/release.gradle")) + +configureCheckstyle() diff --git a/bugsnag-plugin-android-exitinfo/build.gradle.kts b/bugsnag-plugin-android-exitinfo/build.gradle.kts index 6a5fdc1b5a..65b1171c28 100644 --- a/bugsnag-plugin-android-exitinfo/build.gradle.kts +++ b/bugsnag-plugin-android-exitinfo/build.gradle.kts @@ -1,20 +1,66 @@ plugins { - id("bugsnag-build-plugin") - id("com.android.library") - id("com.google.protobuf") version "0.9.4" + loadDefaultPlugins() + load(Versions.Plugins.protobuf) +} + +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android.exitinfo" + + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + + consumerProguardFiles("proguard-rules.pro") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + lint { + isAbortOnError = true + isWarningsAsErrors = true + isCheckAllWarnings = true + baseline(File(project.projectDir, "lint-baseline.xml")) + disable("GradleDependency", "NewerVersionAvailable") + } + + buildFeatures { + aidl = false + renderScript = false + shaders = false + resValues = false + buildConfig = false + } + + compileOptions { + sourceCompatibility = Versions.java + targetCompatibility = Versions.java + } + + testOptions { + unitTests { + isReturnDefaultValues = true + } + } + + sourceSets { + named("test") { + java.srcDir(SHARED_TEST_SRC_DIR) + } + } + + libraryVariants.configureEach { + processJavaResourcesProvider { + exclude("**/*.proto") + } + } } dependencies { + addCommonModuleDependencies() api(project(":bugsnag-android-core")) implementation("com.google.protobuf:protobuf-javalite:3.24.2") } -android.libraryVariants.configureEach { - processJavaResourcesProvider { - exclude("**/*.proto") - } -} - protobuf { protoc { artifact = "com.google.protobuf:protoc:3.24.2" @@ -31,3 +77,9 @@ protobuf { } apiValidation.ignoredPackages += "com.bugsnag.android.repackaged.server.os" + +apply(from = rootProject.file("gradle/detekt.gradle")) +apply(from = rootProject.file("gradle/license-check.gradle")) +apply(from = rootProject.file("gradle/release.gradle")) + +configureCheckstyle() diff --git a/bugsnag-plugin-android-ndk/build.gradle.kts b/bugsnag-plugin-android-ndk/build.gradle.kts index 1006109c80..51a08ab826 100644 --- a/bugsnag-plugin-android-ndk/build.gradle.kts +++ b/bugsnag-plugin-android-ndk/build.gradle.kts @@ -1,15 +1,67 @@ plugins { - id("bugsnag-build-plugin") + loadDefaultPlugins() } -bugsnagBuildOptions { - usesNdk = true - publishesPrefab = "bugsnag-ndk" -} +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android.ndk" + + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + + consumerProguardFiles("proguard-rules.pro") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + externalNativeBuild.cmake.arguments += BugsnagDefaults.cmakeArguments + + configureAbis(ndk.abiFilters) + } -apply(plugin = "com.android.library") + lint { + isAbortOnError = true + isWarningsAsErrors = true + isCheckAllWarnings = true + baseline(File(project.projectDir, "lint-baseline.xml")) + disable("GradleDependency", "NewerVersionAvailable") + } + + buildFeatures { + aidl = false + renderScript = false + shaders = false + resValues = false + buildConfig = false + } + + compileOptions { + sourceCompatibility = Versions.java + targetCompatibility = Versions.java + } + + testOptions { + unitTests { + isReturnDefaultValues = true + } + } + + sourceSets { + named("test") { + java.srcDir(SHARED_TEST_SRC_DIR) + } + } + + buildFeatures.prefabPublishing = true + prefab.create("bugsnag-ndk") { + headers = "src/main/jni/include" + } + + externalNativeBuild.cmake.path = project.file("CMakeLists.txt") + externalNativeBuild.cmake.version = Versions.Android.Build.cmakeVersion +} dependencies { + addCommonModuleDependencies() add("api", project(":bugsnag-android-core")) } @@ -24,3 +76,9 @@ afterEvaluate { } } } + +apply(from = rootProject.file("gradle/detekt.gradle")) +apply(from = rootProject.file("gradle/license-check.gradle")) +apply(from = rootProject.file("gradle/release.gradle")) + +configureCheckstyle() diff --git a/bugsnag-plugin-android-okhttp/build.gradle.kts b/bugsnag-plugin-android-okhttp/build.gradle.kts index 9bfba99091..7ac8784704 100644 --- a/bugsnag-plugin-android-okhttp/build.gradle.kts +++ b/bugsnag-plugin-android-okhttp/build.gradle.kts @@ -1,9 +1,56 @@ plugins { - id("bugsnag-build-plugin") - id("com.android.library") + loadDefaultPlugins() +} + +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android.okhttp" + + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + + consumerProguardFiles("proguard-rules.pro") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + lint { + isAbortOnError = true + isWarningsAsErrors = true + isCheckAllWarnings = true + baseline(File(project.projectDir, "lint-baseline.xml")) + disable("GradleDependency", "NewerVersionAvailable") + } + + buildFeatures { + aidl = false + renderScript = false + shaders = false + resValues = false + buildConfig = false + } + + compileOptions { + sourceCompatibility = Versions.java + targetCompatibility = Versions.java + } + + testOptions { + unitTests { + isReturnDefaultValues = true + } + } + + sourceSets { + named("test") { + java.srcDir(SHARED_TEST_SRC_DIR) + } + } } dependencies { + addCommonModuleDependencies() + add("api", project(":bugsnag-android-core")) add("compileOnly", "com.squareup.okhttp3:okhttp:4.9.1") { @@ -14,3 +61,9 @@ dependencies { exclude(group = "org.jetbrains.kotlin") } } + +apply(from = rootProject.file("gradle/detekt.gradle")) +apply(from = rootProject.file("gradle/license-check.gradle")) +apply(from = rootProject.file("gradle/release.gradle")) + +configureCheckstyle() diff --git a/bugsnag-plugin-react-native/build.gradle.kts b/bugsnag-plugin-react-native/build.gradle.kts index da00b5fbe3..8aaf78009f 100644 --- a/bugsnag-plugin-react-native/build.gradle.kts +++ b/bugsnag-plugin-react-native/build.gradle.kts @@ -1,8 +1,60 @@ plugins { - id("bugsnag-build-plugin") - id("com.android.library") + loadDefaultPlugins() +} + +android { + compileSdk = Versions.Android.Build.compileSdkVersion + namespace = "com.bugsnag.android.reactnative" + + defaultConfig { + minSdk = Versions.Android.Build.minSdkVersion + ndkVersion = Versions.Android.Build.ndk + + consumerProguardFiles("proguard-rules.pro") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + lint { + isAbortOnError = true + isWarningsAsErrors = true + isCheckAllWarnings = true + baseline(File(project.projectDir, "lint-baseline.xml")) + disable("GradleDependency", "NewerVersionAvailable") + } + + buildFeatures { + aidl = false + renderScript = false + shaders = false + resValues = false + buildConfig = false + } + + compileOptions { + sourceCompatibility = Versions.java + targetCompatibility = Versions.java + } + + testOptions { + unitTests { + isReturnDefaultValues = true + } + } + + sourceSets { + named("test") { + java.srcDir(SHARED_TEST_SRC_DIR) + } + } } dependencies { + addCommonModuleDependencies() add("api", project(":bugsnag-android-core")) } + +apply(from = rootProject.file("gradle/detekt.gradle")) +apply(from = rootProject.file("gradle/license-check.gradle")) +apply(from = rootProject.file("gradle/release.gradle")) + +configureCheckstyle() diff --git a/build.gradle.kts b/build.gradle.kts index 07f756315d..871f1073c5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,23 +1,8 @@ -buildscript { - repositories { - google() - mavenCentral() - maven(url = "https://plugins.gradle.org/m2/") - } - - dependencies { - classpath("com.android.tools.build:gradle:7.0.4") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10") - classpath("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.1") - classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.9.0") - classpath("org.jlleitschuh.gradle:ktlint-gradle:10.2.0") - classpath("androidx.benchmark:benchmark-gradle-plugin:1.1.1") - } -} +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("com.github.hierynomus.license") version "0.16.1" - id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.1" apply false + load(Versions.Plugins.AGP) apply false + load(Versions.Plugins.kotlin) apply false } allprojects { @@ -31,4 +16,19 @@ allprojects { options.compilerArgs.addAll(listOf("-Xlint:all", "-Werror")) } } -} \ No newline at end of file +} + +subprojects { + tasks.withType(KotlinCompile::class.java).configureEach { + kotlinOptions { + allWarningsAsErrors = true + apiVersion = Versions.kotlinLang + languageVersion = Versions.kotlinLang + freeCompilerArgs += listOf( + "-Xno-call-assertions", + "-Xno-receiver-assertions", + "-Xno-param-assertions" + ) + } + } +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 901628b472..bac8645f5d 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,24 +1,11 @@ plugins { - `java-gradle-plugin` `kotlin-dsl` } -gradlePlugin { - plugins { - register("bugsnag-build-plugin") { - id = "bugsnag-build-plugin" - implementationClass = "com.bugsnag.android.BugsnagBuildPlugin" - } - } -} - repositories { - google() mavenCentral() } dependencies { compileOnly(gradleApi()) - implementation("com.android.tools.build:gradle:7.0.2") - implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10") } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000000..ac180651c0 --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "bugsnag-buildSrc" \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/bugsnag/android/Checkstyle.kt b/buildSrc/src/main/kotlin/Checkstyle.kt similarity index 95% rename from buildSrc/src/main/kotlin/com/bugsnag/android/Checkstyle.kt rename to buildSrc/src/main/kotlin/Checkstyle.kt index 989a9ae6ad..d8bd874b75 100644 --- a/buildSrc/src/main/kotlin/com/bugsnag/android/Checkstyle.kt +++ b/buildSrc/src/main/kotlin/Checkstyle.kt @@ -1,5 +1,3 @@ -package com.bugsnag.android - import org.gradle.api.Project import org.gradle.api.plugins.quality.Checkstyle import org.gradle.api.plugins.quality.CheckstyleExtension diff --git a/buildSrc/src/main/kotlin/ProjectDefaults.kt b/buildSrc/src/main/kotlin/ProjectDefaults.kt new file mode 100644 index 0000000000..38da13d88c --- /dev/null +++ b/buildSrc/src/main/kotlin/ProjectDefaults.kt @@ -0,0 +1,36 @@ +import org.gradle.api.Project +import org.gradle.plugin.use.PluginDependenciesSpec + +const val SHARED_TEST_SRC_DIR = "../bugsnag-android-core/src/sharedTest/java" + +object BugsnagDefaults { + val cmakeArguments + get() = listOf( + "-DANDROID_CPP_FEATURES=exceptions", + "-DANDROID_STL=c++_static" + ) +} + +fun Project.configureAbis(abiFilters: MutableSet) { + val override: String? = project.findProperty("ABI_FILTERS") as String? + val abis = override?.split(",") ?: mutableSetOf( + "arm64-v8a", + "armeabi-v7a", + "x86", + "x86_64" + ) + + abiFilters.clear() + abiFilters.addAll(abis) +} + +fun PluginDependenciesSpec.loadDefaultPlugins() { + load(Versions.Plugins.AGP) + load(Versions.Plugins.kotlin) + load(Versions.Plugins.ktlint) + load(Versions.Plugins.dokka) + load(Versions.Plugins.detekt) + load(Versions.Plugins.licenseCheck) + load(Versions.Plugins.binaryCompatibilityCheck) + load(Versions.Plugins.checkstyle) +} diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt new file mode 100644 index 0000000000..ad9e74a7e6 --- /dev/null +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -0,0 +1,84 @@ +import org.gradle.api.JavaVersion +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.plugin.use.PluginDependenciesSpec +import org.gradle.plugin.use.PluginDependencySpec + +/** + * Controls the versions of plugins, dependencies, and build targets used by the SDK. + */ +object Versions { + val java = JavaVersion.VERSION_1_8 + val kotlin = "1.6.0" + val kotlinLang = "1.5" + + object Plugins { + val AGP = ModuleWithVersion("com.android.library", "7.0.4") + val kotlin = ModuleWithVersion("org.jetbrains.kotlin.android", Versions.kotlin) + val detekt = ModuleWithVersion("io.gitlab.arturbosch.detekt", "1.23.1") + val ktlint = ModuleWithVersion("org.jlleitschuh.gradle.ktlint", "10.2.0") + val dokka = ModuleWithVersion("org.jetbrains.dokka", "1.9.20") + val binaryCompatibilityCheck = ModuleWithVersion( + "org.jetbrains.kotlinx.binary-compatibility-validator", "0.13.1") + val licenseCheck = ModuleWithVersion("com.github.hierynomus.license", "0.16.1") + + val protobuf = ModuleWithVersion("com.google.protobuf", "0.9.4") + + val checkstyle = ModuleWithVersion("checkstyle") + } + + object Android { + // dependencies + val supportLib = "1.1.0" + val supportTestLib = "1.2.0" + val espressoTestLib = "3.1.0" + val junitTestLib = "4.12" + val mockitoTestLib = "2.28.2" + + object Build { + // Note minSdkVersion must be >=21 for 64 bit architectures + val minSdkVersion = 14 + val compileSdkVersion = 34 + + val ndk = "23.1.7779620" + val cmakeVersion = "3.22.1" + } + } + + data class ModuleWithVersion( + val id: String, + val version: String? = null, + ) +} + +fun PluginDependenciesSpec.load(module: Versions.ModuleWithVersion): PluginDependencySpec { + var plugin = id(module.id) + if (module.version != null) { + plugin = plugin.version(module.version) + } + + return plugin +} + +fun DependencyHandler.addCommonModuleDependencies() { + // needs to be kept as 'compile' for license checking to work + // as otherwise the downloadLicenses task misses these deps + add("api", "androidx.annotation:annotation:${Versions.Android.supportLib}") + add("api", "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}") + + add("testImplementation", "junit:junit:${Versions.Android.junitTestLib}") + add("testImplementation", "org.mockito:mockito-core:${Versions.Android.mockitoTestLib}") + add("testImplementation", "org.mockito:mockito-inline:${Versions.Android.mockitoTestLib}") + add("testImplementation", "androidx.test:core:${Versions.Android.supportTestLib}") + + add( + "androidTestImplementation", + "org.mockito:mockito-android:${Versions.Android.mockitoTestLib}" + ) + add("androidTestImplementation", "androidx.test:core:${Versions.Android.supportTestLib}") + add("androidTestImplementation", "androidx.test:runner:${Versions.Android.supportTestLib}") + add("androidTestImplementation", "androidx.test:rules:${Versions.Android.supportTestLib}") + add( + "androidTestImplementation", + "androidx.test.espresso:espresso-core:${Versions.Android.espressoTestLib}" + ) +} diff --git a/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt b/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt deleted file mode 100644 index efbf6784c9..0000000000 --- a/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPlugin.kt +++ /dev/null @@ -1,234 +0,0 @@ -package com.bugsnag.android - -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.dependencies -import org.jetbrains.kotlin.gradle.dsl.KotlinCompile -import java.io.File - -/** - * A plugin which shares build logic between subprojects. This is the recommended way of - * sharing logic in Gradle builds as it cuts down on repetition, and avoids the pitfalls - * of the `allProjects {}` DSL. - * - * The Android Library plugin must be applied after this plugin. - * - * https://docs.gradle.org/current/userguide/sharing_build_logic_between_subprojects.html - */ -class BugsnagBuildPlugin : Plugin { - - override fun apply(project: Project) { - val bugsnag = project.extensions.create( - "bugsnagBuildOptions", - BugsnagBuildPluginExtension::class.java, - project.objects - ) - - // configure AGP with the information it needs to build the project - project.pluginManager.withPlugin("com.android.library") { - configureProject(project, bugsnag) - } - } - - private fun configureProject( - project: Project, - bugsnag: BugsnagBuildPluginExtension - ) { - // load 3rd party gradle plugins - project.applyPlugins(bugsnag) - - val android = project.extensions.getByType(LibraryExtension::class.java) - android.apply { - configureDefaults() - configureAndroidLint(project) - configureTests() - configureAndroidPackagingOptions() - - if (bugsnag.usesNdk) { - configureNdk(project) - - bugsnag.publishesPrefab?.let { prefabModuleName -> - configurePrefabPublishing(prefabModuleName) - } - } - - bugsnag.androidConfiguration.forEach { config -> - config(android) - } - } - - // add 3rd party dependencies to the project - project.addExternalDependencies() - - // apply legacy groovy scripts to configure 3rd party plugins - project.apply(from = project.file("../gradle/release.gradle")) - project.apply(from = project.file("../gradle/license-check.gradle")) - - if (bugsnag.compilesCode) { - project.configureKotlinOptions() - project.configureCheckstyle() - - project.apply(from = project.file("../gradle/detekt.gradle")) - } - } - - private fun LibraryExtension.configurePrefabPublishing(prefabModuleName: String) { - buildFeatures.prefabPublishing = true - prefab.create(prefabModuleName) { - headers = "src/main/jni/include" - } - } - - /** - * Configures the Android NDK, if it is enabled - */ - private fun BaseExtension.configureNdk(project: Project) { - defaultConfig { - externalNativeBuild.cmake.arguments += listOf( - "-DANDROID_CPP_FEATURES=exceptions", - "-DANDROID_STL=c++_static" - ) - - - val override: String? = project.findProperty("ABI_FILTERS") as String? - val abis = override?.split(",") ?: mutableSetOf( - "arm64-v8a", - "armeabi-v7a", - "x86", - "x86_64" - ) - ndk.setAbiFilters(abis) - } - externalNativeBuild.cmake.path = project.file("CMakeLists.txt") - externalNativeBuild.cmake.version = Versions.cmakeVersion - } - - /** - * Configures the compile and package options for the Android artefacts - */ - private fun BaseExtension.configureAndroidPackagingOptions() { - buildFeatures.apply { - aidl = false - renderScript = false - shaders = false - resValues = false - buildConfig = false - } - - compileOptions { - sourceCompatibility = Versions.java - targetCompatibility = Versions.java - } - } - - /** - * Configures the Android Lint static analysis tool - */ - private fun BaseExtension.configureAndroidLint(project: Project) { - lintOptions { - isAbortOnError = true - isWarningsAsErrors = true - isCheckAllWarnings = true - baseline(File(project.projectDir, "lint-baseline.xml")) - disable("GradleDependency", "NewerVersionAvailable") - } - } - - /** - * Configures options for how the unit test target behaves. - */ - private fun BaseExtension.configureTests() { - testOptions { - unitTests { - isReturnDefaultValues = true - } - } - - sourceSets { - named("test") { - java.srcDir(SHARED_TEST_SRC_DIR) - } - } - } - - /** - * Adds external libraries to the dependencies for each project, such as the Kotlin stdlib. - */ - private fun Project.addExternalDependencies() { - project.dependencies { - // needs to be kept as 'compile' for license checking to work - // as otherwise the downloadLicenses task misses these deps - add("api", "androidx.annotation:annotation:${Versions.supportLib}") - add("api", "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}") - - add("testImplementation", "junit:junit:${Versions.junitTestLib}") - add("testImplementation", "org.mockito:mockito-core:${Versions.mockitoTestLib}") - add("testImplementation", "org.mockito:mockito-inline:${Versions.mockitoTestLib}") - add("testImplementation", "androidx.test:core:${Versions.supportTestLib}") - - add( - "androidTestImplementation", - "org.mockito:mockito-android:${Versions.mockitoTestLib}" - ) - add("androidTestImplementation", "androidx.test:core:${Versions.supportTestLib}") - add("androidTestImplementation", "androidx.test:runner:${Versions.supportTestLib}") - add("androidTestImplementation", "androidx.test:rules:${Versions.supportTestLib}") - add( - "androidTestImplementation", - "androidx.test.espresso:espresso-core:${Versions.espressoTestLib}" - ) - } - } - - private fun Project.configureKotlinOptions() { - tasks.withType(KotlinCompile::class.java).configureEach { - kotlinOptions { - allWarningsAsErrors = true - apiVersion = Versions.kotlinLang - languageVersion = Versions.kotlinLang - freeCompilerArgs += listOf( - "-Xno-call-assertions", - "-Xno-receiver-assertions", - "-Xno-param-assertions" - ) - } - } - } - - /** - * Configures Android project defaults such as minSdkVersion. - */ - private fun BaseExtension.configureDefaults() { - defaultConfig { - setCompileSdkVersion(Versions.compileSdkVersion) - minSdk = Versions.minSdkVersion - ndkVersion = Versions.ndk - consumerProguardFiles("proguard-rules.pro") - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - } - - /** - * Applies gradle plugins to the given project which are always required (e.g. - * kotlin-android). - */ - private fun Project.applyPlugins(bugsnag: BugsnagBuildPluginExtension) { - val plugins = project.plugins - plugins.apply("com.github.hierynomus.license") - - if (bugsnag.compilesCode) { - plugins.apply("checkstyle") - plugins.apply("kotlin-android") - plugins.apply("io.gitlab.arturbosch.detekt") - plugins.apply("org.jlleitschuh.gradle.ktlint") - plugins.apply("org.jetbrains.kotlinx.binary-compatibility-validator") - } - } - - companion object { - private const val SHARED_TEST_SRC_DIR = "../bugsnag-android-core/src/sharedTest/java" - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPluginExtension.kt b/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPluginExtension.kt deleted file mode 100644 index d2637be468..0000000000 --- a/buildSrc/src/main/kotlin/com/bugsnag/android/BugsnagBuildPluginExtension.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.bugsnag.android - -import com.android.build.api.dsl.LibraryExtension -import org.gradle.api.model.ObjectFactory - -/** - * Controls how the Bugsnag Build Plugin should be applied to a given module. This interface - * allows for unwanted behaviour to be switched off - e.g., modules which don't use the NDK - * can disable it. - */ -open class BugsnagBuildPluginExtension(@Suppress("UNUSED_PARAMETER") objects: ObjectFactory) { - - internal val androidConfiguration = ArrayList Unit>() - - /** - * Whether this project compiles code or not. If this is set to false then unnecessary - * plugins are not applied, which speeds up the build. By default this is enabled. - */ - open var compilesCode: Boolean = true - - /** - * Whether the project uses the Android NDK or not. By default this is disabled. - */ - open var usesNdk: Boolean = false - - /** - * The project publishes a native prefab with the specified name. By default this is disabled. - */ - open var publishesPrefab: String? = null - - fun android(config: LibraryExtension.() -> Unit) { - androidConfiguration.add(config) - } -} diff --git a/buildSrc/src/main/kotlin/com/bugsnag/android/Versions.kt b/buildSrc/src/main/kotlin/com/bugsnag/android/Versions.kt deleted file mode 100644 index 0184e19bfc..0000000000 --- a/buildSrc/src/main/kotlin/com/bugsnag/android/Versions.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.bugsnag.android - -import org.gradle.api.JavaVersion - -/** - * Controls the versions of plugins, dependencies, and build targets used by the SDK. - */ -object Versions { - // Note minSdkVersion must be >=21 for 64 bit architectures - val minSdkVersion = 14 - val compileSdkVersion = 34 - val ndk = "23.1.7779620" - val java = JavaVersion.VERSION_1_8 - val kotlin = "1.5.10" - val kotlinLang = "1.5" - val cmakeVersion = "3.22.1" - - // plugins - val androidGradlePlugin = "7.0.4" - val detektPlugin = "1.23.1" - val ktlintPlugin = "10.2.0" - val dokkaPlugin = "1.9.0" - val benchmarkPlugin = "1.1.1" - - // dependencies - val supportLib = "1.1.0" - val supportTestLib = "1.2.0" - val espressoTestLib = "3.1.0" - val junitTestLib = "4.13.2" - val mockitoTestLib = "4.11.0" -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index a093eafc48..cc2590528a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,11 @@ +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} + plugins { id("com.gradle.enterprise") version "3.5" } From 7f86a25feb2e675aa1b15de835a6babbce406829 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 18 Nov 2024 16:25:16 +0000 Subject: [PATCH 5/6] chore(build): update CodeQL to use custom build script --- .github/workflows/codeql.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 7445ca76d4..344d77b2f1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -73,7 +73,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@396bb3e45325a47dd9ef434068033c6d5bb0d11a #v3.27.3 +# uses: github/codeql-action/autobuild@396bb3e45325a47dd9ef434068033c6d5bb0d11a #v3.27.3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -84,6 +84,9 @@ jobs: # - run: | # echo "Run, Build Application using script" # ./location_of_script_within_repo/buildscript.sh + run: | + echo "Run, Build Application using script" + ./gradlew --no-daemon assemble - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@396bb3e45325a47dd9ef434068033c6d5bb0d11a #v3.27.3 From e190021946f9ce99ef3c799b3684ba51df2b37d9 Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 28 Nov 2024 14:18:41 +0000 Subject: [PATCH 6/6] test(startup): remove flaky MultiThreadedStartupScenario - it cannot be made reliable and no amount of retries will stop the flakes --- .../scenarios/MultiThreadedStartupScenario.kt | 35 ------------------- features/full_tests/threaded_startup.feature | 10 ------ 2 files changed, 45 deletions(-) delete mode 100644 features/fixtures/mazerunner/jvm-scenarios/src/main/java/com/bugsnag/android/mazerunner/scenarios/MultiThreadedStartupScenario.kt delete mode 100644 features/full_tests/threaded_startup.feature diff --git a/features/fixtures/mazerunner/jvm-scenarios/src/main/java/com/bugsnag/android/mazerunner/scenarios/MultiThreadedStartupScenario.kt b/features/fixtures/mazerunner/jvm-scenarios/src/main/java/com/bugsnag/android/mazerunner/scenarios/MultiThreadedStartupScenario.kt deleted file mode 100644 index aea3d67d10..0000000000 --- a/features/fixtures/mazerunner/jvm-scenarios/src/main/java/com/bugsnag/android/mazerunner/scenarios/MultiThreadedStartupScenario.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.bugsnag.android.mazerunner.scenarios - -import android.content.Context -import com.bugsnag.android.Bugsnag -import com.bugsnag.android.Configuration -import kotlin.concurrent.thread - -class MultiThreadedStartupScenario( - config: Configuration, - context: Context, - eventMetadata: String? -) : Scenario(config, context, eventMetadata) { - override fun startBugsnag(startBugsnagOnly: Boolean) {} - - override fun startScenario() { - val startThread = thread(name = "AsyncStart") { - measureBugsnagStartupDuration(context, config) - } - - thread(name = "leaveBreadcrumb") { - // simulate the start of some startup work, but not enough for Bugsnag.start to complete - Thread.sleep(1L) - try { - Bugsnag.leaveBreadcrumb("I'm leaving a breadcrumb on another thread") - Bugsnag.notify(Exception("Scenario complete")) - } catch (e: Exception) { - measureBugsnagStartupDuration(context, config) - Bugsnag.notify(e) - } - } - - // make sure we wait before returning - startThread.join() - } -} diff --git a/features/full_tests/threaded_startup.feature b/features/full_tests/threaded_startup.feature deleted file mode 100644 index ab383ea02f..0000000000 --- a/features/full_tests/threaded_startup.feature +++ /dev/null @@ -1,10 +0,0 @@ -Feature: Switching automatic error detection on/off for Unity - - Background: - Given I clear all persistent data - - Scenario: Starting Bugsnag & calling it on separate threads - When I run "MultiThreadedStartupScenario" and relaunch the crashed app - And I configure Bugsnag for "MultiThreadedStartupScenario" - Then I wait to receive an error - And the error is correct for "MultiThreadedStartupScenario" or I allow a retry