diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnEnv.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnEnv.kt index e1f23b8f694..64d8b59c824 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnEnv.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnEnv.kt @@ -11,5 +11,6 @@ import java.io.File data class YarnEnv( val downloadUrl: String, val cleanableStore: CleanableStore, - val home: File + val home: File, + val ivyDependency: String ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt index 4ec11659adf..7c812abd0c2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt @@ -32,6 +32,11 @@ open class YarnPlugin : Plugin { registerTask(YarnSetupTask.NAME) { it.dependsOn(nodeJs.nodeJsSetupTaskProvider) + + it.configuration = provider { + this.project.configurations.detachedConfiguration(this.project.dependencies.create(it.ivyDependency)) + .also { conf -> conf.isTransitive = false } + } } val rootClean = project.rootProject.tasks.named(BasePlugin.CLEAN_TASK_NAME) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt index 3f0bc12bb2a..9a3901d0ff0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt @@ -76,9 +76,10 @@ open class YarnRootExtension( val cleanableStore = CleanableStore[installationDir.path] return YarnEnv( - downloadUrl = "$downloadBaseUrl/v$version/yarn-v$version.tar.gz", + downloadUrl = downloadBaseUrl, cleanableStore = cleanableStore, - home = cleanableStore["yarn-v$version"].use() + home = cleanableStore["yarn-v$version"].use(), + ivyDependency = "com.yarnpkg:yarn:$version@tar.gz" ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt index 7591b391b46..5989cf5a8ff 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt @@ -5,17 +5,20 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn -import de.undercouch.gradle.tasks.download.DownloadAction import org.gradle.api.DefaultTask -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.TaskAction +import org.gradle.api.artifacts.Configuration +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.* +import org.jetbrains.kotlin.gradle.logging.kotlinInfo +import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics import java.io.File +import java.net.URI @CacheableTask open class YarnSetupTask : DefaultTask() { + @Transient private val settings = project.yarn private val env by lazy { settings.requireConfigured() } @@ -32,19 +35,46 @@ open class YarnSetupTask : DefaultTask() { description = "Download and install a local yarn version" } - @TaskAction - fun setup() { - val dir = temporaryDir - val tar = download(dir) - extract(tar, destination) + val ivyDependency: String + @Input get() = env.ivyDependency + + @Transient + @get:Internal + internal lateinit var configuration: Provider + + private val _yarnDist by lazy { + configuration.get().files.single() } - private fun download(tar: File): File { - val action = DownloadAction(project) - action.src(downloadUrl) - action.dest(tar) - action.execute() - return action.outputFiles.singleOrNull() ?: error("Cannot get downloaded file $downloadUrl") + @Suppress("unused") // as it called by Gradle before task execution and used to resolve artifact + @get:Classpath + val yarnDist: File + get() { + val repo = project.repositories.ivy { repo -> + repo.name = "Yarn Distributions at ${downloadUrl}" + repo.url = URI(downloadUrl) + repo.patternLayout { + it.artifact("v[revision]/[artifact](-v[revision]).[ext]") + } + repo.metadataSources { it.artifact() } + repo.content { it.includeModule("com.yarnpkg", "yarn") } + } + val startDownloadTime = System.currentTimeMillis() + val dist = _yarnDist + val downloadDuration = System.currentTimeMillis() - startDownloadTime + if (downloadDuration > 0) { + KotlinBuildStatsService.getInstance() + ?.report(NumericalMetrics.ARTIFACTS_DOWNLOAD_SPEED, dist.length() * 1000 / downloadDuration) + } + project.repositories.remove(repo) + return dist + } + + @TaskAction + fun setup() { + logger.kotlinInfo("Using node distribution from '$yarnDist'") + + extract(yarnDist, destination.parentFile) // parent because archive contains name already } private fun extract(archive: File, destination: File) {