Skip to content

Commit

Permalink
Merge pull request #49 from vaadin/feature/48-auto-activate-tasks
Browse files Browse the repository at this point in the history
vaadinPrepareFrontend and vaadinBuildFrontend are now automatically a…
  • Loading branch information
mvysny committed Feb 28, 2020
2 parents f2b613a + 2aa700c commit 78e4818
Show file tree
Hide file tree
Showing 13 changed files with 422 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
language: groovy
language: java
jdk:
- openjdk8
- openjdk11
Expand Down
49 changes: 42 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,22 @@ There are the following tasks:
and will place that by default into the `build/vaadin-generated` folder. The folder is
then later picked up by `jar` and `war` tasks which then package the folder contents properly
onto the classpath. Note that this task is not automatically hooked into `war`/`jar`/`assemble`/`build` and
need to be invoked explicitly.
need to be invoked explicitly. Note: this task will not be triggered automatically if `productionMode` is set to false.
* `vaadinPrepareNode` will download a local distribution of node.js and npm into the `node/` folder for use by Vaadin.
Please see below for more information.

Most common commands for all projects:

* `./gradlew clean vaadinPrepareFrontend` - prepares the project for development
* `./gradlew clean vaadinBuildFrontend build` - will compile Vaadin in production mode, then packages everything into the WAR archive.
* `./gradlew clean build` - builds the project and prepares the project for development. Automatically
calls the `vaadinPrepareFrontend` task, but doesn't call the `vaadinBuildFrontend` task by default.
* `./gradlew clean vaadinPrepareFrontend` - quickly prepares the project for development.
* `./gradlew clean build -Pvaadin.productionMode` - will compile Vaadin in production mode,
then packages everything into the war/jar archive. Automatically calls the
`vaadinPrepareFrontend` and `vaadinBuildFrontend` tasks.

*Note* (after you built the project in production mode): In order to prepare the project
setup back to development mode, you must run `./gradlew vaadinPrepareFrontend`
with the `productionMode` effectively set to false (e.g. by ommitting the `-Pvaadin.productionMode` flag).

## Configuration

Expand All @@ -70,8 +78,10 @@ vaadin {

All configuration options follow. Note that you **RARELY** need to change anything of the below.

* `productionMode = false`: Whether or not we are running in productionMode.
The `vaadinBuildFrontend` task will automatically switch this to true, there is no need for you to configure anything.
* `productionMode = false`: Whether or not the plugin should run in productionMode. Defaults to false.
Responds to the `-Pvaadin.productionMode` property. You need to set this to `true` if you wish
to build a production-ready war/jar artifact. If this is false, the `vaadinBuildFrontend`
task is not triggered automatically by the build.
* `buildOutputDirectory = File(project.buildDir, "vaadin-generated")`:
The plugin will generate additional resource files here. These files need
to be present on the classpath, in order for Vaadin to be
Expand Down Expand Up @@ -123,10 +133,11 @@ In your development environment, just run:
to download and prepare a local distribution of node.js. You only need to run this once,
in order to populate the folder `node/`.

In your CI, don't forget to call the `vaadinPrepareNode` before the `vaadinPrepareFrontend` task:
In your CI, don't forget to call the `vaadinPrepareNode` along with setting the production mode to true:
```bash
./gradlew clean vaadinPrepareNode vaadinBuildFrontend build
./gradlew clean vaadinPrepareNode build -Pvaadin.productionMode
```
That will automatically download node and run `vaadinPrepareFrontend` and `vaadinBuildFrontend` tasks.

If you wish to override the node version which will be downloaded, simply specify
the node.js version in the `vaadin {}` block:
Expand All @@ -140,6 +151,30 @@ vaadin {
Please see the [list of all node.js releases](https://nodejs.org/en/download/releases/). Usually
it's best to select the LTS release.

## Multi-project builds

It is important to apply this plugin only to projects building the final war/jar artifact. You can
achieve that by having the `com.vaadin` plugin in the `plugins{}` block not applied by default, then
applying the plugin only in the war project:

```groovy
plugins {
id 'java'
id "com.vaadin" version "0.5.1" apply false
}
project("lib") {
apply plugin: 'java'
}
project("web") {
apply plugin: 'war'
apply plugin: "com.vaadin"
dependencies {
compile project(':lib')
}
}
```

# Developing The Plugin

Please read the Gradle Tutorial on [Developing Custom Gradle Plugins](https://docs.gradle.org/current/userguide/custom_plugins.html)
Expand Down
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,11 @@ wrapper {
gradleVersion = '5.0'
distributionType = Wrapper.DistributionType.ALL
}

// Travis kills the build if there's no stdout for 10 minutes: https://docs.travis-ci.com/user/common-build-problems/#build-times-out-because-no-output-was-received
// This will print ongoing tests, taken from https://stackoverflow.com/a/4292739/377320
functionalTest {
testLogging {
info.events "passed", "skipped", "failed"
}
}
16 changes: 11 additions & 5 deletions src/functionalTest/kotlin/com/vaadin/gradle/AbstractGradleTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,23 @@ abstract class AbstractGradleTest {
* Runs build on [testProjectDir]; a `build.gradle` [buildFile] is expected
* to be located there.
*
* The function checks that all tasks have succeeded; if not, throws an informative exception.
* The function by default checks that all tasks have succeeded; if not, throws an informative exception.
* You can suppress this functionality by setting [checkTasksSuccessful] to false.
*/
protected fun build(vararg tasks: String): BuildResult {
protected fun build(vararg args: String, checkTasksSuccessful: Boolean = true): BuildResult {
val result: BuildResult = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(tasks.toList() + "--stacktrace")
.withArguments(args.toList() + "--stacktrace")
.withPluginClasspath()
.build()

for (task: String in tasks) {
result.expectTaskSucceded(task)
if (checkTasksSuccessful) {
for (arg: String in args) {
val isTask: Boolean = !arg.startsWith("-")
if (isTask) {
result.expectTaskSucceded(arg)
}
}
}
return result
}
Expand Down
63 changes: 61 additions & 2 deletions src/functionalTest/kotlin/com/vaadin/gradle/MiscMultiModuleTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.vaadin.gradle

import org.gradle.testkit.runner.BuildResult
import org.junit.Test
import kotlin.test.expect

class MiscMultiModuleTest : AbstractGradleTest() {
/**
Expand All @@ -14,8 +16,10 @@ class MiscMultiModuleTest : AbstractGradleTest() {
id 'java'
id 'com.vaadin' apply false
}
repositories {
jcenter()
allprojects {
repositories {
jcenter()
}
}
project(':lib') {
apply plugin: 'java'
Expand All @@ -26,6 +30,13 @@ class MiscMultiModuleTest : AbstractGradleTest() {
dependencies {
compile project(':lib')
compile("com.vaadin:vaadin-core:14.1.16") {
// Webjars are only needed when running in Vaadin 13 compatibility mode
["com.vaadin.webjar", "org.webjars.bowergithub.insites",
"org.webjars.bowergithub.polymer", "org.webjars.bowergithub.polymerelements",
"org.webjars.bowergithub.vaadin", "org.webjars.bowergithub.webcomponents"]
.forEach { group -> exclude(group: group) }
}
}
}
""".trimIndent())
Expand All @@ -36,4 +47,52 @@ class MiscMultiModuleTest : AbstractGradleTest() {
// or it would blow up with FileNotFoundException straight away.
build("web:vaadinPrepareFrontend")
}

/**
* Tests that `vaadinPrepareFrontend` and `vaadinBuildFrontend` tasks are run only
* on the `web` project.
*/
@Test
fun `vaadinBuildFrontend only runs on the web project`() {
settingsFile.writeText("include 'lib', 'web'")
buildFile.writeText("""
plugins {
id 'java'
id 'com.vaadin' apply false
}
allprojects {
repositories {
jcenter()
}
}
project(':lib') {
apply plugin: 'java'
}
project(':web') {
apply plugin: 'war'
apply plugin: 'com.vaadin'
dependencies {
compile project(':lib')
compile("com.vaadin:vaadin-core:14.1.16") {
// Webjars are only needed when running in Vaadin 13 compatibility mode
["com.vaadin.webjar", "org.webjars.bowergithub.insites",
"org.webjars.bowergithub.polymer", "org.webjars.bowergithub.polymerelements",
"org.webjars.bowergithub.vaadin", "org.webjars.bowergithub.webcomponents"]
.forEach { group -> exclude(group: group) }
}
}
}
""".trimIndent())
testProject.newFolder("lib")
testProject.newFolder("web")

val b: BuildResult = build("-Pvaadin.productionMode", "vaadinBuildFrontend", checkTasksSuccessful = false)
b.expectTaskSucceded("web:vaadinPrepareFrontend")
b.expectTaskSucceded("web:vaadinBuildFrontend")
expect(null) { b.task(":lib:vaadinPrepareFrontend") }
expect(null) { b.task(":lib:vaadinBuildFrontend") }
expect(null) { b.task(":vaadinPrepareFrontend") }
expect(null) { b.task(":vaadinBuildFrontend") }
}
}
114 changes: 107 additions & 7 deletions src/functionalTest/kotlin/com/vaadin/gradle/MiscSingleModuleTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,54 @@ class MiscSingleModuleTest : AbstractGradleTest() {
build("tasks")
}


/**
* This test covers the [Base Starter Gradle](https://github.com/vaadin/base-starter-gradle)
* example project.
*/
@Test
fun testWarProject() {
fun testWarProjectDevelopmentMode() {
buildFile.writeText("""
plugins {
id 'war'
id 'org.gretty' version '3.0.1'
id("com.vaadin")
}
repositories {
jcenter()
}
dependencies {
// Vaadin 14
compile("com.vaadin:vaadin-core:14.1.16") {
// Webjars are only needed when running in Vaadin 13 compatibility mode
["com.vaadin.webjar", "org.webjars.bowergithub.insites",
"org.webjars.bowergithub.polymer", "org.webjars.bowergithub.polymerelements",
"org.webjars.bowergithub.vaadin", "org.webjars.bowergithub.webcomponents"]
.forEach { group -> exclude(group: group) }
}
providedCompile("javax.servlet:javax.servlet-api:3.1.0")
// logging
// currently we are logging through the SLF4J API to SLF4J-Simple. See src/main/resources/simplelogger.properties file for the logger configuration
compile("org.slf4j:slf4j-simple:1.7.30")
}
""".trimIndent())

val build: BuildResult = build("clean", "vaadinPrepareNode", "build")
// vaadinBuildFrontend should NOT have been executed automatically
expect(null) { build.task(":vaadinBuildFrontend") }

val war: File = testProjectDir.find("build/libs/*.war").first()
expect(true, "$war is missing\n${build.output}") { war.isFile }
expectArchiveDoesntContainVaadinWebpackBundle(war, false)
}

/**
* This test covers the [Base Starter Gradle](https://github.com/vaadin/base-starter-gradle)
* example project.
*/
@Test
fun testWarProjectProductionMode() {
buildFile.writeText("""
plugins {
id 'war'
Expand Down Expand Up @@ -69,7 +111,9 @@ class MiscSingleModuleTest : AbstractGradleTest() {
}
""".trimIndent())

val build: BuildResult = build("clean", "vaadinPrepareNode", "vaadinBuildFrontend", "build")
val build: BuildResult = build("-Pvaadin.productionMode", "clean", "vaadinPrepareNode", "build")
// vaadinBuildFrontend should have been executed automatically
build.expectTaskSucceded("vaadinBuildFrontend")

val war: File = testProjectDir.find("build/libs/*.war").first()
expect(true, "$war is missing\n${build.output}") { war.isFile }
Expand All @@ -80,7 +124,57 @@ class MiscSingleModuleTest : AbstractGradleTest() {
* This test covers the https://github.com/mvysny/vaadin14-embedded-jetty-gradle example.
*/
@Test
fun testJarProject() {
fun testJarProjectDevelopmentMode() {
buildFile.writeText("""
plugins {
id 'java'
id("com.vaadin")
}
repositories {
jcenter()
}
def jettyVersion = "9.4.20.v20190813"
vaadin {
optimizeBundle = true
}
dependencies {
// Vaadin 14
compile("com.vaadin:vaadin-core:14.1.16") {
// Webjars are only needed when running in Vaadin 13 compatibility mode
["com.vaadin.webjar", "org.webjars.bowergithub.insites",
"org.webjars.bowergithub.polymer", "org.webjars.bowergithub.polymerelements",
"org.webjars.bowergithub.vaadin", "org.webjars.bowergithub.webcomponents"]
.forEach { group -> exclude(group: group) }
}
compile("javax.servlet:javax.servlet-api:3.1.0")
compile("org.eclipse.jetty:jetty-continuation:${"$"}{jettyVersion}")
compile("org.eclipse.jetty:jetty-server:${"$"}{jettyVersion}")
compile("org.eclipse.jetty.websocket:websocket-server:${"$"}{jettyVersion}")
compile("org.eclipse.jetty.websocket:javax-websocket-server-impl:${"$"}{jettyVersion}") {
exclude(module: "javax.websocket-client-api")
}
// logging
// currently we are logging through the SLF4J API to SLF4J-Simple. See src/main/resources/simplelogger.properties file for the logger configuration
compile("org.slf4j:slf4j-simple:1.7.30")
}
""".trimIndent())

val build: BuildResult = build("clean", "vaadinPrepareNode", "build")
// vaadinBuildFrontend should NOT have been executed automatically
expect(null) { build.task(":vaadinBuildFrontend") }

val jar: File = testProjectDir.find("build/libs/*.jar").first()
expect(true, "$jar is missing\n${build.output}") { jar.isFile }
expectArchiveDoesntContainVaadinWebpackBundle(jar, false)
}

/**
* This test covers the https://github.com/mvysny/vaadin14-embedded-jetty-gradle example.
*/
@Test
fun testJarProjectProductionMode() {
buildFile.writeText("""
plugins {
id 'java'
Expand Down Expand Up @@ -117,7 +211,9 @@ class MiscSingleModuleTest : AbstractGradleTest() {
}
""".trimIndent())

val build: BuildResult = build("clean", "vaadinBuildFrontend", "build")
val build: BuildResult = build("-Pvaadin.productionMode", "clean", "vaadinPrepareNode", "build")
build.expectTaskSucceded("vaadinPrepareFrontend")
build.expectTaskSucceded("vaadinBuildFrontend")

val jar: File = testProjectDir.find("build/libs/*.jar").first()
expect(true, "$jar is missing\n${build.output}") { jar.isFile }
Expand All @@ -134,7 +230,7 @@ class MiscSingleModuleTest : AbstractGradleTest() {
* This build script covers the [Spring Boot example](https://github.com/vaadin/base-starter-spring-gradle)
*/
@Test
fun testVaadin14SpringProject() {
fun testVaadin14SpringProjectProductionMode() {
buildFile.writeText("""
plugins {
id 'org.springframework.boot' version '2.2.4.RELEASE'
Expand Down Expand Up @@ -198,7 +294,9 @@ class MiscSingleModuleTest : AbstractGradleTest() {
}
""".trimIndent())

val build: BuildResult = build("vaadinPrepareNode", "vaadinBuildFrontend", "build")
val build: BuildResult = build("-Pvaadin.productionMode", "vaadinPrepareNode", "build")
build.expectTaskSucceded("vaadinPrepareFrontend")
build.expectTaskSucceded("vaadinBuildFrontend")

val jar: File = testProjectDir.find("build/libs/*.jar").first()
expect(true, "$jar is missing\n${build.output}") { jar.isFile }
Expand Down Expand Up @@ -259,7 +357,9 @@ class MiscSingleModuleTest : AbstractGradleTest() {
}
""".trimIndent())

val build: BuildResult = build("clean", "vaadinPrepareNode", "vaadinBuildFrontend", "build")
val build: BuildResult = build("-Dvaadin.productionMode", "clean", "vaadinPrepareNode", "build")
build.expectTaskSucceded("vaadinPrepareFrontend")
build.expectTaskSucceded("vaadinBuildFrontend")

val war: File = testProjectDir.find("build/libs/*.war").first()
expect(true, "$war is missing\n${build.output}") { war.isFile }
Expand Down
Loading

0 comments on commit 78e4818

Please sign in to comment.