Skip to content

Commit

Permalink
Merge pull request #678 from playframework/gradle
Browse files Browse the repository at this point in the history
Gradle Support
  • Loading branch information
mkurz authored Oct 22, 2023
2 parents 8ff2859 + d169301 commit e45150e
Show file tree
Hide file tree
Showing 30 changed files with 1,702 additions and 4 deletions.
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

0 comments on commit e45150e

Please sign in to comment.