[Gradle, JS] Webpack task with conf cache (w/o install of dependencies)

This commit is contained in:
Ilya Goncharov
2020-12-11 13:56:43 +03:00
committed by Alexander Likhachev
parent e6bfe9a702
commit a41d3e5b04
16 changed files with 76 additions and 53 deletions
@@ -9,6 +9,7 @@ import jetbrains.buildServer.messages.serviceMessages.ServiceMessageParserCallba
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.internal.logging.progress.ProgressLogger
import org.gradle.internal.service.ServiceRegistry
import org.gradle.process.ExecResult
import org.gradle.process.internal.ExecAction
import org.gradle.process.internal.ExecActionFactory
@@ -18,15 +19,13 @@ import java.io.PipedInputStream
import java.io.PipedOutputStream
import kotlin.concurrent.thread
internal fun Project.execWithProgress(description: String, readStdErr: Boolean = false, body: (ExecAction) -> Unit): ExecResult {
this as ProjectInternal
internal fun ServiceRegistry.execWithProgress(description: String, readStdErr: Boolean = false, body: (ExecAction) -> Unit): ExecResult {
val stderr = ByteArrayOutputStream()
val stdout = StringBuilder()
val stdInPipe = PipedInputStream()
val exec = services.get(ExecActionFactory::class.java).newExecAction()
val exec = get(ExecActionFactory::class.java).newExecAction()
body(exec)
return project!!.operation(description) {
return operation(description) {
progress(description)
exec.standardOutput = PipedOutputStream(stdInPipe)
val outputReaderThread = thread(name = "output reader for [$description]") {
@@ -69,14 +68,12 @@ internal fun Project.execWithProgress(description: String, readStdErr: Boolean =
}
}
internal fun Project.execWithErrorLogger(
internal fun ServiceRegistry.execWithErrorLogger(
description: String,
body: (ExecAction, ProgressLogger) -> Pair<TeamCityMessageCommonClient, TeamCityMessageCommonClient>
): ExecResult {
this as ProjectInternal
val exec = services.get(ExecActionFactory::class.java).newExecAction()
return project!!.operation(description) {
val exec = get(ExecActionFactory::class.java).newExecAction()
return operation(description) {
progress(description)
val (standardClient, errorClient) = body(exec, this)
exec.isIgnoreExitValue = true
@@ -5,18 +5,16 @@
package org.jetbrains.kotlin.gradle.internal
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.internal.logging.events.ProgressStartEvent
import org.gradle.internal.logging.progress.ProgressLogger
import org.gradle.internal.service.ServiceRegistry
fun <T> Project.operation(
fun <T> ServiceRegistry.operation(
description: String,
initialStatus: String? = null,
body: ProgressLogger.() -> T
): T {
val services = (project as ProjectInternal).services
val progressFactory = services.get(org.gradle.internal.logging.progress.ProgressLoggerFactory::class.java)
val progressFactory = get(org.gradle.internal.logging.progress.ProgressLoggerFactory::class.java)
val operation = progressFactory.newOperation(ProgressStartEvent.BUILD_OP_CATEGORY)
operation.start(description, initialStatus)
try {
@@ -40,9 +40,9 @@ private constructor() {
val detector = MultiplePluginDeclarationDetector()
instance = detector
gradle.buildFinished {
instance = null
}
// gradle.buildFinished {
// instance = null
// }
return detector
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.targets.js.dukat
import org.gradle.api.artifacts.FileCollectionDependency
import org.gradle.api.internal.project.ProjectInternal
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
@@ -103,7 +104,7 @@ internal class DukatCompilationResolverPlugin(
packageJsonIsUpdated,
operation = compilation.name + " > " + DukatExecutor.OPERATION,
compareInputs = true
).execute()
).execute((project as ProjectInternal).services)
}
companion object {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.targets.js.dukat
import org.gradle.internal.service.ServiceRegistry
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
@@ -30,7 +31,7 @@ class DukatExecutor(
val shouldSkip: Boolean
get() = inputsFile.isFile && prevVersion == version && !packageJsonIsUpdated
fun execute() {
fun execute(services: ServiceRegistry) {
if (typeDefinitions.isEmpty()) {
npmProject.externalsDirRoot.deleteRecursively()
return
@@ -53,7 +54,7 @@ class DukatExecutor(
externalsOutputFormat,
npmProject.externalsDir,
operation = operation
).execute()
).execute(services)
inputsFile.writeText(inputs)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.targets.js.dukat
import org.gradle.internal.service.ServiceRegistry
import org.jetbrains.kotlin.gradle.internal.execWithProgress
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
@@ -19,8 +20,8 @@ class DukatRunner(
val jsInteropJvmEngine: String? = null,
val operation: String = "Generating Kotlin/JS external declarations"
) {
fun execute() {
compilation.target.project.execWithProgress(operation) { exec ->
fun execute(services: ServiceRegistry) {
services.execWithProgress(operation) { exec ->
val args = mutableListOf<String>()
if (externalsOutputFormat == ExternalsOutputFormat.BINARY) {
@@ -100,7 +100,7 @@ abstract class DukatTask(
qualifiedPackageName,
null,
operation
).execute()
).execute(services)
}
}
@@ -39,6 +39,6 @@ constructor(
@TaskAction
override fun run() {
executor.execute()
executor.execute(services)
}
}
@@ -37,13 +37,14 @@ open class KotlinJsIrLink : Kotlin2JsCompile() {
@get:SkipWhenEmpty
@get:InputDirectory
@get:PathSensitive(PathSensitivity.RELATIVE)
internal val entryModule: File
get() = File(
internal val entryModule: File by lazy {
File(
(taskData.compilation as KotlinJsIrCompilation)
.output
.classesDirs
.asPath
)
}
override fun skipCondition(inputs: IncrementalTaskInputs): Boolean {
return !inputs.isIncremental && !entryModule.exists()
@@ -25,11 +25,13 @@ val KotlinJsCompilation.npmProject: NpmProject
* More info can be obtained from [KotlinCompilationNpmResolution], which is available after project resolution (after [KotlinNpmInstallTask] execution).
*/
open class NpmProject(@Transient val compilation: KotlinJsCompilation) {
val name: String
get() = buildNpmProjectName()
val name: String by lazy {
buildNpmProjectName()
}
val nodeJs
get() = NodeJsRootPlugin.apply(project.rootProject)
val nodeJs by lazy {
NodeJsRootPlugin.apply(project.rootProject)
}
val dir: File
get() = nodeJs.projectPackagesDir.resolve(name)
@@ -90,7 +92,7 @@ open class NpmProject(@Transient val compilation: KotlinJsCompilation) {
* Require [request] nodejs module and return canonical path to it's main js file.
*/
fun require(request: String): String {
nodeJs.npmResolutionManager.requireAlreadyInstalled(project)
// nodeJs.npmResolutionManager.requireAlreadyInstalled(project)
return modules.require(request)
}
@@ -91,7 +91,8 @@ internal class KotlinCompilationNpmResolver(
val project get() = target.project
@Transient
val packageJsonTaskHolder = KotlinPackageJsonTask.create(compilation)
val packageJsonTaskHolder: TaskProvider<KotlinPackageJsonTask>? =
KotlinPackageJsonTask.create(compilation)
@Transient
val publicPackageJsonTaskHolder: TaskProvider<PublicPackageJsonTask> =
@@ -150,7 +151,7 @@ internal class KotlinCompilationNpmResolver(
@Synchronized
fun getResolutionOrResolveIfForced(): KotlinCompilationNpmResolution? {
if (resolution != null) return resolution
if (packageJsonTaskHolder.get().state.upToDate) return resolve(skipWriting = true)
if (packageJsonTaskHolder == null || packageJsonTaskHolder.get().state.upToDate) return resolve(skipWriting = true)
if (resolver.forceFullResolve && resolution == null) {
// need to force all NPM tasks to be configured in IDEA import
project.tasks.implementing(RequiresNpmDependencies::class).all {}
@@ -112,7 +112,10 @@ constructor(
}
fun useKarma() = useKarma {}
fun useKarma(body: KotlinKarma.() -> Unit) = use(KotlinKarma(compilation), body)
fun useKarma(body: KotlinKarma.() -> Unit) = use(
KotlinKarma(compilation, services),
body
)
fun useKarma(fn: Closure<*>) {
useKarma {
ConfigureUtil.configure(fn, this)
@@ -10,6 +10,7 @@ import jetbrains.buildServer.messages.serviceMessages.BaseTestSuiteMessage
import org.gradle.api.Project
import org.gradle.api.internal.tasks.testing.TestResultProcessor
import org.gradle.internal.logging.progress.ProgressLogger
import org.gradle.internal.service.ServiceRegistry
import org.gradle.process.ProcessForkOptions
import org.gradle.process.internal.ExecHandle
import org.jetbrains.kotlin.gradle.internal.LogType
@@ -35,7 +36,7 @@ import org.jetbrains.kotlin.gradle.utils.property
import org.slf4j.Logger
import java.io.File
class KotlinKarma(override val compilation: KotlinJsCompilation) :
class KotlinKarma(override val compilation: KotlinJsCompilation, private val services: ServiceRegistry) :
KotlinJsTestFramework {
private val project: Project = compilation.target.project
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
@@ -404,7 +405,7 @@ class KotlinKarma(override val compilation: KotlinJsCompilation) :
lateinit var progressLogger: ProgressLogger
override fun wrapExecute(body: () -> Unit) {
project.operation("Running and building tests with karma and webpack") {
services.operation("Running and building tests with karma and webpack") {
progressLogger = this
body()
}
@@ -10,6 +10,7 @@ import org.gradle.api.Incubating
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
@@ -44,9 +45,11 @@ constructor(
init {
// TODO: temporary workaround for configuration cache enabled builds
disableTaskOnConfigurationCacheBuild { nodeJs.npmResolutionManager.toString() }
// disableTaskOnConfigurationCacheBuild { nodeJs.npmResolutionManager.toString() }
}
private val npmProject = compilation.npmProject
@get:Inject
open val fileResolver: FileResolver
get() = injected
@@ -97,7 +100,7 @@ constructor(
@get:OutputFile
open val configFile: File by lazy {
compilation.npmProject.dir.resolve("webpack.config.js")
npmProject.dir.resolve("webpack.config.js")
}
@Input
@@ -137,21 +140,30 @@ constructor(
open val outputFile: File
get() = destinationDirectory.resolve(outputFileName)
open val configDirectory: File?
@Optional @InputDirectory get() = project.projectDir.resolve("webpack.config.d").takeIf { it.isDirectory }
private val projectDir = project.projectDir
@get:Optional
@get:InputDirectory
open val configDirectory: File? by lazy {
projectDir.resolve("webpack.config.d").takeIf { it.isDirectory }
}
@Input
var report: Boolean = false
private val projectReportsDir = project.reportsDir
open val reportDir: File
@Internal get() = reportDirProvider.get()
@OutputDirectory
open val reportDirProvider: Provider<File> = entryProperty
.map { it.asFile.nameWithoutExtension }
.map {
project.reportsDir.resolve("webpack").resolve(it)
}
@get:OutputDirectory
open val reportDirProvider: Provider<File> by lazy {
entryProperty
.map { it.asFile.nameWithoutExtension }
.map {
projectReportsDir.resolve("webpack").resolve(it)
}
}
open val evaluatedConfigFile: File
@Internal get() = evaluatedConfigFileProvider.get()
@@ -217,7 +229,8 @@ constructor(
.forEach { it(config) }
return KotlinWebpackRunner(
compilation.npmProject,
npmProject,
logger,
configFile,
execHandleFactory,
bin,
@@ -237,7 +250,8 @@ constructor(
@TaskAction
fun doExecute() {
nodeJs.npmResolutionManager.checkRequiredDependencies(this)
println(services.get(org.gradle.internal.logging.progress.ProgressLoggerFactory::class.java))
// nodeJs.npmResolutionManager?.checkRequiredDependencies(this)
val runner = createRunner()
@@ -258,7 +272,7 @@ constructor(
progressReporter = true,
progressReporterPathFilter = nodeJs.rootPackageDir.absolutePath
)
).execute()
).execute(services)
}
}
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.gradle.targets.js.webpack
import org.gradle.api.logging.Logger
import org.gradle.internal.logging.progress.ProgressLogger
import org.gradle.internal.service.ServiceRegistry
import org.gradle.process.ExecSpec
import org.gradle.process.internal.ExecHandle
import org.gradle.process.internal.ExecHandleFactory
@@ -18,6 +20,7 @@ import java.io.File
internal data class KotlinWebpackRunner(
val npmProject: NpmProject,
val logger: Logger,
val configFile: File,
val execHandleFactory: ExecHandleFactory,
val tool: String,
@@ -25,7 +28,7 @@ internal data class KotlinWebpackRunner(
val nodeArgs: List<String>,
val config: KotlinWebpackConfig
) {
fun execute() = npmProject.project.execWithErrorLogger("webpack") { execAction, progressLogger ->
fun execute(services: ServiceRegistry) = services.execWithErrorLogger("webpack") { execAction, progressLogger ->
configureExec(
execAction,
progressLogger
@@ -47,7 +50,6 @@ internal data class KotlinWebpackRunner(
clientType: LogType,
progressLogger: ProgressLogger?
): TeamCityMessageCommonClient {
val logger = npmProject.project.logger
return TeamCityMessageCommonClient(clientType, logger)
.apply {
if (progressLogger != null) {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.targets.js.yarn
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.jetbrains.kotlin.gradle.internal.execWithProgress
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
@@ -32,7 +33,7 @@ abstract class YarnBasics : NpmApi {
val nodeJs = NodeJsRootPlugin.apply(project)
val yarnPlugin = YarnPlugin.apply(project)
project.execWithProgress(description) { exec ->
(project as ProjectInternal).services.execWithProgress(description) { exec ->
exec.executable = nodeJs.requireConfigured().nodeExecutable
exec.args = listOf(yarnPlugin.requireConfigured().home.resolve("bin/yarn.js").absolutePath) +
args +