Commits
Tarun Sukhani authored 8a65578e70c
feat: playBundle task — self-contained deployment zip (PF-90)
Adds a 22nd user-facing task: playBundle. Produces a runtime-only zip
that requires nothing beyond a JRE to deploy.
What's in the bundle (under <projectName>/ root inside the zip):
- conf/, public/, modules/, precompiled/, certs/ (only host.cert/host.key,
not the gitignored .env)
- framework/play-X.Y.Z.jar + framework/lib/*.jar (from frameworkPath)
- lib/*.jar (Gradle-resolved deps + any manually-placed app/lib jars,
deduped by filename if both sources have the same artifact)
- .classpath: relative paths from bundle root, one per line, in load order
(conf, framework jar, framework lib, app lib, modules lib)
- bin/play-start.sh: runs `java -classpath \$(cat .classpath | tr \\n :)
-Dprecompiled=true -Dplay.id=\${PLAY_ID:-prod} ... play.server.Server`
(renamed from bin/start.sh to avoid colliding with user bin/ scripts)
Design choice: include-list (only conf/public/modules/precompiled/certs)
rather than exclude-list. The exclude-list approach broke against jclaw
which has many app-specific top-level dirs (workspace/, data/, frontend/,
openspec/, skills/, .junie/, .githooks/) that aren't standard Play layout
and shouldn't be in a deployment artifact. Apps that need app-specific
runtime data dirs would mount them as volumes at deploy time anyway.
Excludes app/, test/, documentation/ — source isn't needed in
precompiled mode. Excludes .git, .gradle, build, dist, logs, tmp, etc.
implicitly via the include-list.
dependsOn extractPlayModules + playPrecompile so the bundle is
always up-to-date with the latest extracted modules and precompiled
classes.
Verified end-to-end against jclaw:
- Bundle: 363 MB zip
- Top-level dirs: bin, certs, conf, framework, lib, modules, precompiled, public
- 262 .classpath entries
- Unzipped to /tmp, ran `bash bin/play-start.sh` with PLAY_SECRET env var
set: HTTP/HTTPS/HTTP-3 listeners up, "Application is precompiled" logged,
"Application 'JClaw' is now started", HTTP 200 on / with proper
<title>JClaw</title> welcome page
Also fixed an unrelated implicit-dependency error: compileJava reads
modules/*/lib/*.jar via the source set compileClasspath we configured
in Phase 3, but didn't dependsOn extractPlayModules. Gradle 9 flagged
this. Added a configureEach hook on compileJava/compileTestJava.