11import play .sbt .routes .RoutesKeys
22import com .typesafe .sbt .web .SbtWeb .autoImport ._
3+ import com .typesafe .sbt .packager .archetypes .JavaAppPackaging .autoImport ._
34import com .gu .Dependencies ._
45import com .gu .ProjectSettings ._
56
@@ -14,6 +15,30 @@ https://support.snyk.io/hc/en-us/articles/9590215676189-Deeply-nested-Scala-proj
1415ThisBuild / asciiGraphWidth := 999999999
1516ThisBuild / scalaVersion := SCALA_VERSION
1617
18+ /*
19+ * Standalone JVM agent that records which Twirl templates are rendered at runtime.
20+ *
21+ * It is NOT a Play module: it's a plain, pure-Java project assembled into a shaded, self-contained
22+ * jar (with a `Premain-Class` manifest entry) that gets attached to a host app via `-javaagent`.
23+ * ByteBuddy is relocated under com.gu.shaded.bytebuddy so it can never clash with anything on an
24+ * application's classpath (e.g. the byte-buddy that mockito pulls in for tests).
25+ */
26+ val templateTrackerAgent = Project (" template-tracker-agent" , file(" template-tracker-agent" ))
27+ .settings(
28+ crossPaths := false , // pure Java: don't append a _2.13 suffix to the artifact
29+ autoScalaLibrary := false , // pure Java: no scala-library dependency
30+ libraryDependencies += byteBuddy,
31+ assembly / assemblyJarName := " template-tracker-agent.jar" ,
32+ assembly / assemblyShadeRules := Seq (
33+ ShadeRule .rename(" net.bytebuddy.**" -> " com.gu.shaded.bytebuddy.@1" ).inAll,
34+ ),
35+ assembly / packageOptions += Package .ManifestAttributes (
36+ " Premain-Class" -> " com.gu.templatetracker.TemplateTrackerAgent" ,
37+ " Can-Redefine-Classes" -> " true" ,
38+ " Can-Retransform-Classes" -> " true" ,
39+ ),
40+ )
41+
1742val common = library(" common" )
1843 .settings(
1944 libraryDependencies ++= Seq (
@@ -99,7 +124,20 @@ val sport = application("sport")
99124 ),
100125 )
101126
102- val discussion = application(" discussion" ).dependsOn(commonWithTests).aggregate(common)
127+ val discussion = application(" discussion" )
128+ .dependsOn(commonWithTests)
129+ .aggregate(common)
130+ .settings(
131+ // --- Twirl template usage tracker (PoC) ---
132+ // Bundle the shaded agent jar into the packaged app under agent/, then have the generated
133+ // native-packager start script attach it via -javaagent. ${app_home} is resolved by the start
134+ // script at launch time, so this needs no change to the CDK/systemd launch config.
135+ Universal / mappings += {
136+ val agentJar = (templateTrackerAgent / assembly).value
137+ agentJar -> " agent/template-tracker-agent.jar"
138+ },
139+ bashScriptExtraDefines += """ addJava "-javaagent:${app_home}/../agent/template-tracker-agent.jar"""" ,
140+ )
103141
104142val admin = application(" admin" )
105143 .dependsOn(commonWithTests)
0 commit comments