Skip to content

Commit 2064933

Browse files
authored
feat: update gradle plugin clean tasks (#18756)
* feat: update gradle plugin clean tasks Updates Vaadin Gradle plugin to clean in same way as Maven plugin cleans. Moved CleanFrontendMojo logic to CleanFrontendUtil in shared flow-plugin-base. Updated VaadinCleanTask and VaadinBuildFrontendTask. Added cleanFrontendFiles property to Gradle plugin. Fixes: #18556 * test: added tests * chore: use local stub jar ...instead of using real hilla endpoint. Also removed webpack.generated.js from the task description and javadoc. * chore: extract Options to CleanOptions * docs: added javadoc
1 parent 11830c9 commit 2064933

File tree

13 files changed

+602
-351
lines changed

13 files changed

+602
-351
lines changed

flow-plugins/flow-dev-bundle-plugin/src/main/java/com/vaadin/flow/plugin/maven/BuildDevBundleMojo.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,11 @@ public void logDebug(CharSequence debugMessage) {
308308
getLog().debug(debugMessage);
309309
}
310310

311+
@Override
312+
public void logDebug(CharSequence debugMessage, Throwable e) {
313+
getLog().debug(debugMessage, e);
314+
}
315+
311316
@Override
312317
public void logInfo(CharSequence infoMessage) {
313318
getLog().info(infoMessage);
@@ -318,14 +323,19 @@ public void logWarn(CharSequence warning) {
318323
getLog().warn(warning);
319324
}
320325

326+
@Override
327+
public void logError(CharSequence error) {
328+
getLog().error(error);
329+
}
330+
321331
@Override
322332
public void logWarn(CharSequence warning, Throwable e) {
323333
getLog().warn(warning, e);
324334
}
325335

326336
@Override
327-
public void logError(CharSequence warning, Throwable e) {
328-
getLog().error(warning, e);
337+
public void logError(CharSequence error, Throwable e) {
338+
getLog().error(error, e);
329339
}
330340

331341
@Override

flow-plugins/flow-gradle-plugin/src/functionalTest/kotlin/com/vaadin/gradle/AbstractGradleTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import java.io.File
2727
*/
2828
abstract class AbstractGradleTest {
2929

30-
val flowVersion = System.getenv("vaadin.version").takeUnless { it.isNullOrEmpty() } ?: "24.3-SNAPSHOT"
30+
val flowVersion = System.getenv("vaadin.version").takeUnless { it.isNullOrEmpty() } ?: "24.4-SNAPSHOT"
3131
val slf4jVersion = "2.0.3"
3232

3333
/**

flow-plugins/flow-gradle-plugin/src/functionalTest/kotlin/com/vaadin/gradle/VaadinSmokeTest.kt

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ import java.io.File
1919
import kotlin.test.assertContains
2020
import kotlin.test.expect
2121
import com.vaadin.flow.server.InitParameters
22+
import com.vaadin.flow.server.frontend.FrontendUtils
2223
import elemental.json.JsonObject
2324
import elemental.json.impl.JsonUtil
24-
import org.gradle.api.JavaVersion
2525
import org.gradle.testkit.runner.BuildResult
2626
import org.gradle.testkit.runner.TaskOutcome
2727
import org.junit.Before
2828
import org.junit.Test
29+
import java.nio.file.Files
30+
import java.nio.file.StandardCopyOption
31+
2932

3033
/**
3134
* The most basic tests. If these fail, the plugin is completely broken and all
@@ -149,29 +152,15 @@ class VaadinSmokeTest : AbstractGradleTest() {
149152
@Test
150153
fun vaadinCleanDoesntDeletePnpmFiles() {
151154
val pnpmLockYaml = testProject.newFile("pnpm-lock.yaml")
152-
val pnpmFileJs = testProject.newFile("pnpmfile.js")
153155
val pnpmFileCjs = testProject.newFile(".pnpmfile.cjs")
154156
val webpackConfigJs = testProject.newFile("webpack.config.js")
155157
testProject.build("vaadinClean")
156158
expect(false) { pnpmLockYaml.exists() }
157-
expect(false) { pnpmFileJs.exists() }
158159
expect(false) { pnpmFileCjs.exists() }
159160
// don't delete webpack.config.js: https://github.com/vaadin/vaadin-gradle-plugin/pull/74#discussion_r444457296
160161
expect(true) { webpackConfigJs.exists() }
161162
}
162163

163-
/**
164-
* Tests that VaadinClean task removes TS-related files.
165-
*/
166-
@Test
167-
fun vaadinCleanDeletesTsFiles() {
168-
val tsconfigJson = testProject.newFile("tsconfig.json")
169-
val typesDTs = testProject.newFile("types.d.ts")
170-
testProject.build("vaadinClean")
171-
expect(false) { tsconfigJson.exists() }
172-
expect(false) { typesDTs.exists() }
173-
}
174-
175164
/**
176165
* Tests that VaadinClean task removes default fronted/generated directory
177166
*/
@@ -246,6 +235,58 @@ class VaadinSmokeTest : AbstractGradleTest() {
246235
expect(false) { generatedTsFolder.exists() }
247236
}
248237

238+
@Test
239+
fun vaadinCleanShouldRemoveNodeModulesAndPackageLock() {
240+
val nodeModules: File = testProject.newFolder(FrontendUtils.NODE_MODULES)
241+
val packageLock: File = testProject.newFile("package-lock.json")
242+
expect(true) { nodeModules.exists() }
243+
expect(true) { packageLock.exists() }
244+
testProject.build("vaadinClean")
245+
expect(false) { nodeModules.exists() }
246+
expect(false) { packageLock.exists() }
247+
}
248+
249+
@Test
250+
fun vaadinCleanShouldNotRemoveNodeModulesAndPackageLockWithHilla() {
251+
testProject.buildFile.writeText("""
252+
plugins {
253+
id 'war'
254+
id 'com.vaadin'
255+
}
256+
repositories {
257+
mavenLocal()
258+
mavenCentral()
259+
maven { url = 'https://maven.vaadin.com/vaadin-prereleases' }
260+
flatDir {
261+
dirs("libs")
262+
}
263+
}
264+
dependencies {
265+
implementation("com.vaadin:flow:$flowVersion")
266+
implementation name:'hilla-endpoint-stub'
267+
providedCompile("jakarta.servlet:jakarta.servlet-api:6.0.0")
268+
implementation("org.slf4j:slf4j-simple:$slf4jVersion")
269+
}
270+
vaadin {
271+
nodeAutoUpdate = true // test the vaadin{} block by changing some innocent property with limited side-effect
272+
}
273+
""")
274+
testProject.newFolder("libs")
275+
// hilla-endpoint-stub.jar contains only stub for com.vaadin.hilla.EndpointController.class
276+
val hillaEndpointJar: File = testProject.newFile("libs/hilla-endpoint-stub.jar")
277+
Files.copy(
278+
File(javaClass.classLoader.getResource("hilla-endpoint-stub.jar").path).toPath(),
279+
hillaEndpointJar.toPath(), StandardCopyOption.REPLACE_EXISTING)
280+
enableHilla()
281+
val nodeModules: File = testProject.newFolder(FrontendUtils.NODE_MODULES)
282+
val packageLock: File = testProject.newFile("package-lock.json")
283+
expect(true) { nodeModules.exists() }
284+
expect(true) { packageLock.exists() }
285+
testProject.build("vaadinClean")
286+
expect(true) { nodeModules.exists() }
287+
expect(true) { packageLock.exists() }
288+
}
289+
249290
/**
250291
* Tests that build works with a custom frontend directory
251292
*/
@@ -360,4 +401,9 @@ class VaadinSmokeTest : AbstractGradleTest() {
360401
)
361402
}
362403
}
404+
405+
private fun enableHilla() {
406+
testProject.newFolder("frontend")
407+
testProject.newFile("frontend/index.ts")
408+
}
363409
}
1020 Bytes
Binary file not shown.

flow-plugins/flow-gradle-plugin/src/main/kotlin/com/vaadin/gradle/GradlePluginAdapter.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ internal class GradlePluginAdapter(
106106
project.logger.debug(debugMessage.toString())
107107
}
108108

109+
override fun logDebug(debugMessage: CharSequence, throwable: Throwable?) {
110+
project.logger.debug(debugMessage.toString(), throwable)
111+
}
112+
109113
override fun logInfo(infoMessage: CharSequence) {
110114
project.logger.info(infoMessage.toString())
111115
}
@@ -118,6 +122,10 @@ internal class GradlePluginAdapter(
118122
project.logger.warn(warningMessage.toString(), throwable)
119123
}
120124

125+
override fun logError(errorMessage: CharSequence) {
126+
project.logger.error(errorMessage.toString())
127+
}
128+
121129
override fun logError(warning: CharSequence, e: Throwable?) {
122130
project.logger.error(warning.toString(), e)
123131
}

flow-plugins/flow-gradle-plugin/src/main/kotlin/com/vaadin/gradle/VaadinBuildFrontendTask.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,18 @@ public open class VaadinBuildFrontendTask : DefaultTask() {
103103
*
104104
* @return `true` to remove created files, `false` to keep the files
105105
*/
106-
protected open fun cleanFrontendFiles(): Boolean = true
106+
protected open fun cleanFrontendFiles(): Boolean {
107+
val adapter = GradlePluginAdapter(project, config, false)
108+
if (FrontendUtils.isHillaUsed(adapter.frontendDirectory(),
109+
adapter.classFinder)) {
110+
/*
111+
* Override this to not clean generated frontend files after the
112+
* build. For Hilla, the generated files can still be useful for
113+
* developers after the build. For example, a developer can use
114+
* {@code vite.generated.ts} to run tests with vitest in CI.
115+
*/
116+
return false
117+
}
118+
return config.cleanFrontendFiles.get()
119+
}
107120
}

flow-plugins/flow-gradle-plugin/src/main/kotlin/com/vaadin/gradle/VaadinCleanTask.kt

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
*/
1616
package com.vaadin.gradle
1717

18+
import com.vaadin.flow.plugin.base.CleanFrontendUtil
19+
import com.vaadin.flow.plugin.base.CleanOptions
20+
import com.vaadin.flow.server.frontend.FrontendUtils
1821
import org.gradle.api.DefaultTask
1922
import org.gradle.api.tasks.TaskAction
20-
import com.vaadin.flow.server.Constants
2123

2224
/**
2325
* Cleans everything Vaadin-related. Useful if npm fails to run after Vaadin
@@ -28,11 +30,7 @@ import com.vaadin.flow.server.Constants
2830
* * `node_modules`
2931
* * `package.json`
3032
* * `package-lock.json`
31-
* * `webpack.generated.js`
3233
* * `package-lock.yaml` (used by Vaadin 14.2+ pnpm)
33-
* * `pnpm-file.js` (used by Vaadin 14.2+ pnpm)
34-
* * `tsconfig.json` (used by Vaadin 15+)
35-
* * `types.d.ts` (used by Vaadin 15+)
3634
*
3735
* Doesn't delete `webpack.config.js` since it is intended to contain
3836
* user-specific code. See https://github.com/vaadin/vaadin-gradle-plugin/issues/43
@@ -48,28 +46,16 @@ public open class VaadinCleanTask : DefaultTask() {
4846

4947
init {
5048
group = "Vaadin"
51-
description = "Cleans the project completely and removes 'generated' folders, node_modules, src/main/bundles/, webpack.generated.js, " +
52-
"vite.generated.js, tsconfig.json, types.d.ts, pnpm-lock.yaml, pnpmfile.js, .pnpmfile.cjs and package-lock.json"
49+
description = "Cleans the project completely and removes 'generated' folders, node_modules, src/main/bundles/, " +
50+
"vite.generated.js, pnpm-lock.yaml, .pnpmfile.cjs and package-lock.json"
5351

5452
dependsOn("clean")
5553
}
5654

5755
@TaskAction
5856
public fun clean() {
59-
project.delete(
60-
config.generatedTsFolder,
61-
config.frontendDirectory.get().resolve("generated").absolutePath,
62-
"${project.projectDir}/node_modules",
63-
"${project.projectDir}/${Constants.BUNDLE_LOCATION}",
64-
"${project.projectDir}/src/main/dev-bundle/",
65-
"${project.projectDir}/package-lock.json",
66-
"${project.projectDir}/webpack.generated.js",
67-
"${project.projectDir}/vite.generated.js",
68-
"${project.projectDir}/.pnpmfile.cjs",
69-
"${project.projectDir}/pnpm-lock.yaml", // used by Vaadin 14.2+ pnpm
70-
"${project.projectDir}/pnpmfile.js", // used by Vaadin 14.2+ pnpm
71-
"${project.projectDir}/tsconfig.json", // used by Vaadin 15+
72-
"${project.projectDir}/types.d.ts" // used by Vaadin 15+
73-
)
57+
CleanFrontendUtil.runCleaning(
58+
GradlePluginAdapter(project, config, false),
59+
CleanOptions())
7460
}
7561
}

flow-plugins/flow-gradle-plugin/src/main/kotlin/com/vaadin/gradle/VaadinFlowPluginExtension.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ public abstract class VaadinFlowPluginExtension {
274274

275275
public abstract val reactEnable: Property<Boolean>
276276

277+
public abstract val cleanFrontendFiles: Property<Boolean>
278+
277279
public fun filterClasspath(@DelegatesTo(value = ClasspathFilter::class, strategy = Closure.DELEGATE_FIRST) block: Closure<*>) {
278280
block.delegate = classpathFilter
279281
block.resolveStrategy = Closure.DELEGATE_FIRST
@@ -419,6 +421,8 @@ internal class PluginEffectiveConfiguration(
419421
.convention(FrontendUtils.isReactRouterRequired(frontendDirectory.get()))
420422
.overrideWithSystemProperty(InitParameters.REACT_ENABLE)
421423

424+
var cleanFrontendFiles: Property<Boolean> = extension.cleanFrontendFiles
425+
.convention(true)
422426
/**
423427
* Finds the value of a boolean property. It searches in gradle and system properties.
424428
*
@@ -466,7 +470,8 @@ internal class PluginEffectiveConfiguration(
466470
"skipDevBundleBuild=${skipDevBundleBuild.get()}, " +
467471
"alwaysExecutePrepareFrontend=${alwaysExecutePrepareFrontend.get()}, " +
468472
"frontendHotdeploy=${frontendHotdeploy.get()}," +
469-
"reactEnable=${reactEnable.get()}" +
473+
"reactEnable=${reactEnable.get()}," +
474+
"cleanFrontendFiles=${cleanFrontendFiles.get()}" +
470475
")"
471476
companion object {
472477
internal fun get(project: Project): PluginEffectiveConfiguration =

0 commit comments

Comments
 (0)