diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 633b3b4f..f4cd3bc6 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -35,7 +35,7 @@ jobs: matrix: gradleVersion: - 7.6 - - 8.5 + - 8.9 os: - windows-latest - ubuntu-latest diff --git a/gradle.properties b/gradle.properties index fd88458d..3175117b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -29,7 +29,7 @@ testGradleVersion= testGradleArguments= # Gradle Releases -> https://github.com/gradle/gradle/releases -gradleVersion=8.5 +gradleVersion=8.9 # https://github.com/gradle/gradle/issues/20416 systemProp.org.gradle.kotlin.dsl.precompiled.accessors.strict=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c..d64cd491 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e093..09523c0e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1a..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/plugin/src/main/kotlin/org/jetbrains/qodana/Qodana.kt b/plugin/src/main/kotlin/org/jetbrains/qodana/Qodana.kt index 19cca1a8..601b3202 100644 --- a/plugin/src/main/kotlin/org/jetbrains/qodana/Qodana.kt +++ b/plugin/src/main/kotlin/org/jetbrains/qodana/Qodana.kt @@ -32,9 +32,9 @@ class Installer { val log: Logger = Logger.getLogger(Installer::class.java.name) companion object { - private const val LATEST_VERSION = "2024.1.8" + private const val LATEST_VERSION = "v2024.1.8" private const val RELEASE_DOWNLOAD_URL = - "https://github.com/JetBrains/qodana-cli/releases/download/v%s/qodana_%s_%s" + "https://github.com/JetBrains/qodana-cli/releases/download/%s/qodana_%s_%s" fun getQodanaUrl( platform: String = getPlatformName(), @@ -70,15 +70,21 @@ class Installer { fun getChecksum(version: String = getLatestVersion()): String { val platform = getPlatformName() val arch = getArchName() - return CHECKSUMS[version]?.get("${platform}_${arch}") + return CHECKSUMS[version.removePrefix("v")]?.get("${platform}_${arch}") ?: throw IllegalArgumentException("Unsupported combination of version, platform and architecture: $version ${platform}_${arch}") } } - fun setup(path: File, downloadURL: String = getQodanaUrl(), version: String = getLatestVersion()): String { + fun setup( + path: File, + version: String = getLatestVersion(), + ): String { + val downloadURL = getQodanaUrl(version = version) + val useNightly = version == "nightly" + if (path.exists()) { try { - verifyChecksum(path, getChecksum(version)) + if (!useNightly) verifyChecksum(path, getChecksum(version)) return path.absolutePath } catch (e: IOException) { log.warning("Checksum verification failed. Redownloading the binary.") @@ -88,7 +94,7 @@ class Installer { try { download(downloadURL, path) - verifyChecksum(path, getChecksum(version)) + if (!useNightly) verifyChecksum(path, getChecksum(version)) } catch (e: IOException) { throw IOException("Unable to download latest qodana binary", e) } diff --git a/plugin/src/main/kotlin/org/jetbrains/qodana/QodanaPlugin.kt b/plugin/src/main/kotlin/org/jetbrains/qodana/QodanaPlugin.kt index df935d6b..c28382b2 100644 --- a/plugin/src/main/kotlin/org/jetbrains/qodana/QodanaPlugin.kt +++ b/plugin/src/main/kotlin/org/jetbrains/qodana/QodanaPlugin.kt @@ -65,6 +65,7 @@ class QodanaPlugin : Plugin { project.file(extension.qodanaPath) }) arguments.convention(listOf()) + useNightly.convention(false) } } } diff --git a/plugin/src/main/kotlin/org/jetbrains/qodana/tasks/QodanaScanTask.kt b/plugin/src/main/kotlin/org/jetbrains/qodana/tasks/QodanaScanTask.kt index ea2acaa6..3567be14 100644 --- a/plugin/src/main/kotlin/org/jetbrains/qodana/tasks/QodanaScanTask.kt +++ b/plugin/src/main/kotlin/org/jetbrains/qodana/tasks/QodanaScanTask.kt @@ -29,6 +29,9 @@ import java.io.File @UntrackedTask(because = "Qodana tracks the state") // TODO: open class QodanaScanTask : Exec() { + private val currentPath = System.getenv("PATH") + private val currentHome = System.getenv("HOME") + /** * Root directory of the project to be analyzed. */ @@ -64,11 +67,27 @@ open class QodanaScanTask : Exec() { @Optional val arguments: ListProperty = objectFactory.listProperty(String::class.java) + + /** + * Use a nightly version of Qodana CLI. + */ + @Input + @Optional + val useNightly = objectFactory.property() + @TaskAction override fun exec() { setArgs(getArguments()) - executable = Installer().setup(qodanaPath.get()) + + executable = (if (useNightly.get()) "nightly" else Installer.getLatestVersion()).let { + Installer().setup( + qodanaPath.get(), + version = it + ) + } environment(QODANA_ENV, QODANA_ENV_NAME) + environment("PATH", currentPath) + environment("HOME", currentHome) ByteArrayOutputStream().use { os -> standardOutput = TeeOutputStream(System.out, os) diff --git a/plugin/src/test/kotlin/org/jetbrains/qodana/tasks/QodanaScanTaskTest.kt b/plugin/src/test/kotlin/org/jetbrains/qodana/tasks/QodanaScanTaskTest.kt index 26f64bb7..3bd61352 100644 --- a/plugin/src/test/kotlin/org/jetbrains/qodana/tasks/QodanaScanTaskTest.kt +++ b/plugin/src/test/kotlin/org/jetbrains/qodana/tasks/QodanaScanTaskTest.kt @@ -39,7 +39,7 @@ class QodanaScanTaskTest : BaseTest() { } @Test - fun `run qodana in a non-empty directory and fail with threshold`() { + fun `run qodana in a container in a non-empty directory and fail with threshold`() { val githubActions = "true".equals(System.getenv("GITHUB_ACTIONS"), ignoreCase = true) val isLinux = System.getProperty("os.name").contains("Linux") if (githubActions) { @@ -60,6 +60,29 @@ class QodanaScanTaskTest : BaseTest() { assertTrue(e.message!!.contains("The number of problems exceeds")) } } +// +// @Test +// fun `run qodana in a non-empty directory and fail a with threshold`() { +// buildFile.groovy(""" +// $EXTENSION_NAME { +// } +// $QODANA_SCAN_TASK_NAME { +// environment = [ +// "QD_PRODUCT_INTERNAL_FEED" : "https://data.services.jetbrains.com/products", +// "QODANA_LICENSE_ONLY_TOKEN": "", +// ] +// arguments = ["--fail-threshold", "0", "--property=idea.headless.enable.statistics=false"] +// useNightly = true +// } +// """.trimIndent()) +// file("main.py").writeText("print('Hello, world!')\n\n\n\n\n\nprintln()") +// file("qodana.yaml").writeText("ide: QDPY-EAP") +// try { +// runTaskForCommand(QODANA_SCAN_TASK_NAME) +// } catch (e: Exception) { +// assertTrue(e.message!!.contains("The number of problems exceeds")) +// } +// } @Test fun `task loads from the configuration cache`() {