Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gradle Support #678

Merged
merged 35 commits into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cac4a82
Run `gradle init`
ihostage Jun 16, 2023
a4029c0
Move `plugin/*` to parent folder
ihostage Jun 16, 2023
a5b0022
Rename plugin id to `com.playframework.twirl`
ihostage Jun 16, 2023
2b869ca
Temporary ignore the headers check
ihostage Jun 16, 2023
e43de02
Enable Java Format check for Gradle Plugin
ihostage Jun 16, 2023
915f811
Enable License Header check for Gradle Plugin
ihostage Jun 23, 2023
c74895c
Enable CI for Gradle Plugin
ihostage Jun 19, 2023
a48e6b0
Sync version between Sbt and Gradle
ihostage Jun 23, 2023
ff2e1c6
Create SourceDirectorySet for Twirl
ihostage Aug 23, 2023
05ace95
Use Worker API for Gradle Plugin
ihostage Aug 25, 2023
6d69b6d
Create custom Twirl configuration for Gradle Plugin
ihostage Aug 28, 2023
cb46b7b
Fix license header in Gradle Plugin sources
ihostage Aug 28, 2023
a381ec5
[Gradle] Add destination directory to the action params
ihostage Aug 28, 2023
2d2ef65
[Gradle] Use isolation classloader for Twirl compilation
ihostage Aug 28, 2023
46ca85d
[Gradle] Add source directory to the action params
ihostage Aug 29, 2023
14f228d
[Gradle] Add formatter type to the action params
ihostage Aug 29, 2023
1ce34a5
[Gradle] Add template imports to the action params
ihostage Aug 30, 2023
4351259
[Gradle] Add constructor annotations to the action params
ihostage Aug 30, 2023
848c3e1
[Gradle] Add source encoding to the action params
ihostage Aug 30, 2023
9f905b5
[Gradle] Use real Twirl compiler
ihostage Aug 30, 2023
4135411
[Gradle] Add compiled templates to scala source set
ihostage Aug 30, 2023
cc67a60
[Gradle] Add few unit tests
ihostage Aug 31, 2023
e069ad2
[Gradle] Drop unnecessary using `afterEvaluate`
ihostage Aug 31, 2023
dc783f1
[Gradle] Add functional tests
ihostage Sep 1, 2023
f6bf96f
[Gradle] Support Gradle 7.1+
ihostage Sep 6, 2023
38518a0
[Gradle] Separate publish release action to be able to re-run separately
ihostage Sep 7, 2023
f6a985b
[Gradle] Migrate to Gradle Version Catalog
ihostage Sep 7, 2023
11d0c68
[Gradle] Add info into README
ihostage Sep 7, 2023
03532f2
[Gradle] Add javadoc comments
ihostage Sep 8, 2023
3d361a7
[Gradle] Support incremental compilation
ihostage Sep 11, 2023
8b57fce
[Gradle] Support Build Cache for TwirlCompile task
ihostage Sep 12, 2023
edcd872
[Gradle] Change groupId to `org.playframework.twirl`
ihostage Oct 6, 2023
76ad962
[Gradle] Sign only release artifacts
ihostage Oct 10, 2023
90355c1
[Gradle] `twirl` configuration shouldn't be consumable
ihostage Oct 11, 2023
d169301
[Gradle] Use `all` gradle distribution instead of `bin` to source cod…
ihostage Oct 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,22 @@ concurrency:
cancel-in-progress: true

jobs:
# Run Gradle Wrapper Validation to verify the wrapper's checksum
gradle-validation:
name: Gradle Wrapper
uses: playframework/.github/.github/workflows/gradle-wrapper-validation.yml@v3

check-code-style:
name: Code Style
needs:
- "gradle-validation"
uses: playframework/.github/.github/workflows/cmd.yml@v3
with:
cmd: sbt validateCode
gradle-build-root: gradle-twirl
cmd: |
sbt validateCode
sbt +compiler/publishM2
cd gradle-twirl && ./gradlew clean spotlessCheck --no-daemon

check-binary-compatibility:
name: Binary Compatibility
Expand All @@ -42,6 +53,7 @@ jobs:
java: 17, 11
scala: 2.12.x, 2.13.x, 3.x
cmd: scripts/test-code.sh
gradle-build-root: gradle-twirl

finish:
name: Finish
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,32 @@ on:
types: [published]

jobs:
publish-artifacts:
publish-snapshot-artifacts:
name: Publish / Artifacts
if: github.ref_type == 'branch' # Snapshots
uses: playframework/.github/.github/workflows/publish.yml@v3
with:
gradle-build-root: gradle-twirl
cmd: |
sbt +compiler/publishM2 ci-release
cd gradle-twirl
./gradlew --no-daemon publishToSonatype -x test -PsonatypeUsername="$SONATYPE_USERNAME" -PsonatypePassword="$SONATYPE_PASSWORD"
secrets: inherit

publish-release:
name: Publish / Artifacts
if: github.ref_type == 'tag' # Releases
uses: playframework/.github/.github/workflows/publish.yml@v3
secrets: inherit

publish-release-gradle:
name: Publish / Artifacts (Gradle Plugin)
if: github.ref_type == 'tag' # Releases
uses: playframework/.github/.github/workflows/publish.yml@v3
with:
gradle-build-root: gradle-twirl
cmd: |
sbt +compiler/publishM2
cd gradle-twirl
./gradlew --no-daemon publishPlugins -x test -Pgradle.publish.key="$GRADLE_PUBLISH_KEY" -Pgradle.publish.secret="$GRADLE_PUBLISH_SECRET"
secrets: inherit
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ project/plugins/project/
.idea

.bloop/

compiler/version.properties
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,108 @@ To use a snapshot version add the [Sonatype Snapshot repository](https://oss.son
</pluginRepositories>
```

## gradle-twirl

⚠️ `org.playframework.twirl` plugin requires Gradle 7.1 or higher.

To use the Twirl plugin in your project add the gradle plugin and
Twirl API as a dependency into `build.gradle.kts`:

```kotlin
plugins {
...
id("org.playframework.twirl") version "LATEST_VERSION"
}

dependencies {
implementation("org.playframework.twirl", "twirl-api_${scalaVersion}", "LATEST_VERSION")
}
```

Replacing the `LATEST_VERSION` with the latest version published, which should be [![Latest version](https://index.scala-lang.org/playframework/twirl/twirl-api/latest.svg?color=orange)](https://index.scala-lang.org/playframework/twirl/twirl-api).

### Template files

Twirl template files are expected to be placed under `src/main/twirl` or
`src/test/twirl`, similar to `scala` or `java` sources. The additional source
locations for template files can be configured.

Template files must be named `{name}.scala.{ext}` where `ext` can be `html`,
`js`, `xml`, or `txt`.

### Additional imports

To add additional imports for the Scala code in template files, use the
`templateImports` key. For example:

```kotlin
sourceSets {
main {
twirl {
templateImports.add("org.example._")
}
}
}
```

### Source directories

To configure the source directories where template files will be found, use the
`srcDir` method for [SourceDirectorySet](https://docs.gradle.org/current/javadoc/org/gradle/api/file/SourceDirectorySet.html). For example:

```kotlin
sourceSets {
main {
twirl {
srcDir("app")
}
}
}
```

### Scala version

To configure the Scala version use the `scalaVersion` property of [TwirlExtension](gradle-twirl/src/main/java/play/twirl/gradle/TwirlExtension.java) (`2.13` by default). For example:

```kotlin
twirl {
scalaVersion.set("3")
}
```

### Other properties

Also, you can use the next properties:

```kotlin
sourceSets {
main {
twirl {
// Annotations added to constructors in injectable templates
constructorAnnotations.add("@org.example.MyAnnotation()")
// Defined custom twirl template formats
templateFormats.put("csv", "play.twirl.api.TxtFormat")
// Source encoding for template files and generated scala files
sourceEncoding.set("<enc>")
}
}
}
```

### Snapshots

To use a snapshot version add the [Sonatype Snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/org/playframework/twirl/org.playframework.twirl.gradle.plugin/) into `settings.gradle.kts`:

```kotlin
pluginManagement {
repositories {
maven {
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
}
}
```

## Releasing a new version

See https://github.com/playframework/.github/blob/main/RELEASING.md
Expand Down
20 changes: 19 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Dependencies._

import sbtcrossproject.CrossPlugin.autoImport.crossProject
import org.scalajs.jsenv.nodejs.NodeJSEnv
import java.util.Properties
import java.io.StringWriter

val ScalaTestVersion = "3.2.17"

Expand Down Expand Up @@ -43,6 +45,8 @@ lazy val twirl = project
(Compile / headerSources) ++=
((baseDirectory.value ** ("*.properties" || "*.md" || "*.sbt" || "*.scala.html"))
--- (baseDirectory.value ** "target" ** "*")
--- (baseDirectory.value / "compiler" / "version.properties")
--- (baseDirectory.value ** "gradle-twirl" ** "*") // Gradle Spotless plugin is used
--- (baseDirectory.value / "docs" ** "*")).get ++
(baseDirectory.value / "project" ** "*.scala" --- (baseDirectory.value ** "target" ** "*")).get
)
Expand Down Expand Up @@ -116,7 +120,10 @@ lazy val compiler = project
libraryDependencies += ("org.scalameta" %% "parsers" % "4.8.12").cross(CrossVersion.for3Use2_13),
run / fork := true,
buildInfoKeys := Seq[BuildInfoKey](scalaVersion),
buildInfoPackage := "play.twirl.compiler"
buildInfoPackage := "play.twirl.compiler",
publishM2 := publishM2.dependsOn(saveCompilerVersion).value,
publish := publish.dependsOn(saveCompilerVersion).value,
publishLocal := publishLocal.dependsOn(saveCompilerVersion).value
)
.aggregate(parser)
.dependsOn(apiJvm % Test, parser % "compile->compile;test->test")
Expand Down Expand Up @@ -186,6 +193,17 @@ def generateVersionFile =
Seq(file)
}

def saveCompilerVersion =
Def.task {
val props = new Properties()
val writer = new StringWriter()
val file = baseDirectory.value / "version.properties"
props.setProperty("twirl.compiler.version", version.value)
props.store(writer, "")
IO.write(file, writer.getBuffer.toString)
Seq(file)
}

addCommandAlias(
"validateCode",
List(
Expand Down
9 changes: 9 additions & 0 deletions gradle-twirl/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf

# These are Windows script files and should use crlf
*.bat text eol=crlf

5 changes: 5 additions & 0 deletions gradle-twirl/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle

# Ignore Gradle build output directory
build
120 changes: 120 additions & 0 deletions gradle-twirl/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/
import java.time.Duration
import java.util.Base64
import java.util.Properties
import kotlin.text.Charsets.UTF_8

plugins {
alias(libs.plugins.gradle.plugin.publish)
alias(libs.plugins.nexus.publish)
alias(libs.plugins.spotless)
signing
}

val compilerVersion: String =
Properties().apply {
val file = file("$projectDir/../compiler/version.properties")
if (!file.exists()) throw GradleException("Install Twirl Compiler to local Maven repository by `sbt +compiler/publishM2` command")
file.inputStream().use { load(it) }
if (this.getProperty("twirl.compiler.version")
.isNullOrEmpty()
) {
throw GradleException("`twirl.compiler.version` key didn't find in ${file.absolutePath}")
}
}.getProperty("twirl.compiler.version")

val isRelease = !compilerVersion.endsWith("SNAPSHOT")

group = "org.playframework.twirl"
version = compilerVersion

repositories {
mavenCentral()
mavenLocal()
}

dependencies {
compileOnly("org.playframework.twirl:twirl-compiler_2.13:$compilerVersion")
testImplementation(libs.assertj)
testImplementation(libs.commons.io)
testImplementation(libs.freemarker)
}

tasks.jar {
manifest {
attributes("Implementation-Version" to version)
}
}

@Suppress("UnstableApiUsage")
testing {
suites {
val test by getting(JvmTestSuite::class) {
useJUnitJupiter()
targets {
all {
testTask.configure {
systemProperty("twirl.version", compilerVersion)
project.findProperty("scala.version")?.let { scalaVersion ->
val ver = (scalaVersion as String).trimEnd { !it.isDigit() }
systemProperty("scala.version", ver)
}
}
}
}
}
}
}

signing {
isRequired = isRelease
if (isRelease) {
val signingKey =
Base64.getDecoder().decode(System.getenv("PGP_SECRET").orEmpty()).toString(UTF_8)
val signingPassword = System.getenv("PGP_PASSPHRASE").orEmpty()
useInMemoryPgpKeys(signingKey, signingPassword)
}
}

nexusPublishing {
packageGroup.set(project.group.toString())
clientTimeout.set(Duration.ofMinutes(60))
this.repositories {
sonatype()
}
}

@Suppress("UnstableApiUsage")
gradlePlugin {
website.set("https://www.playframework.com/documentation/latest/ScalaTemplates")
vcsUrl.set("https://github.com/playframework/twirl")
val twirl by plugins.creating {
id = "org.playframework.twirl"
displayName = "Twirl Plugin"
description = "A Gradle plugin to compile Twirl templates"
tags.set(listOf("playframework", "web", "template", "java", "scala"))
implementationClass = "play.twirl.gradle.TwirlPlugin"
}
}

val headerLicense =
"Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>"
val headerLicenseHash = "# $headerLicense"
val headerLicenseJava = "/*\n * $headerLicense\n */"

spotless {
java {
googleJavaFormat()
licenseHeader(headerLicenseJava)
}
kotlinGradle {
licenseHeader(headerLicenseJava, "[^/*]")
}
format("properties") {
target("**/*.properties")
targetExclude("gradle/**")
licenseHeader(headerLicenseHash, "[^#]")
}
}
5 changes: 5 additions & 0 deletions gradle-twirl/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>

org.gradle.parallel=true
org.gradle.caching=true

17 changes: 17 additions & 0 deletions gradle-twirl/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[versions]
gradle-plugin-publish = "1.2.0"
nexus-publish = "1.3.0"
spotless = "6.19.0"
assertj = "3.24.2"
commons-io = "2.13.0"
freemarker = "2.3.32"

[libraries]
assertj = { group = "org.assertj", name = "assertj-core", version.ref = "assertj" }
commons-io = { group = "commons-io", name = "commons-io", version.ref = "commons-io" }
freemarker = { group = "org.freemarker", name = "freemarker", version.ref = "freemarker" }

[plugins]
gradle-plugin-publish = { id = "com.gradle.plugin-publish", version.ref = "gradle-plugin-publish" }
nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus-publish" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
Binary file added gradle-twirl/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
7 changes: 7 additions & 0 deletions gradle-twirl/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=f2b9ed0faf8472cbe469255ae6c86eddb77076c75191741b4a462f33128dd419
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading
Loading