diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9db71066c..3316f5ac1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
All notable changes to this project will be documented in this file.
+## [0.9.0](https://github.com/gliderlabs/herokuish/compare/v0.8.0...v0.9.0) - 2024-03-31
+
+- #1177 @dependabot: Update php to version v248
+- #1178 @josegonzalez: chore: update dependencies in scala test app
+- #1179 @josegonzalez: feat: use system bash to avoid extracting bash at runtime
+
## [0.8.0](https://github.com/gliderlabs/herokuish/compare/v0.7.6...v0.8.0) - 2024-03-28
- #1093 @dependabot: chore(deps): bump actions/download-artifact from 3 to 4
diff --git a/Dockerfile b/Dockerfile
index 3d161ec55..36eab300d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -53,3 +53,4 @@ RUN /bin/herokuish buildpack install \
*/tmp
COPY include/default_user.bash /tmp/default_user.bash
RUN bash /tmp/default_user.bash && rm -f /tmp/default_user.bash
+ENV BASH_BIN /usr/bin/bash
diff --git a/Makefile b/Makefile
index 6cd461c82..02aa3c3c0 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ REPOSITORY = herokuish
DESCRIPTION = 'Herokuish uses Docker and Buildpacks to build applications like Heroku'
HARDWARE = $(shell uname -m)
SYSTEM_NAME = $(shell uname -s | tr '[:upper:]' '[:lower:]')
-VERSION ?= 0.8.0
+VERSION ?= 0.9.0
IMAGE_NAME ?= $(NAME)
BUILD_TAG ?= dev
PACKAGECLOUD_REPOSITORY ?= dokku/dokku-betafish
diff --git a/README.md b/README.md
index bd41b2cdd..4ca951521 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
[](https://github.com/gliderlabs/herokuish/actions?query=workflow%3ACI)
[](https://kiwiirc.com/client/irc.freenode.net/#gliderlabs)
-[](https://hub.docker.com/r/gliderlabs/herokuish)
+[](https://hub.docker.com/r/gliderlabs/herokuish)
A command line tool for emulating Heroku build and runtime tasks in containers.
@@ -19,7 +19,7 @@ Download and uncompress the latest binary tarball from [releases](https://github
For example, you can do this directly in your Dockerfiles installing into `/bin` as one step:
```shell
-RUN curl --location --silent https://github.com/gliderlabs/herokuish/releases/download/v0.8.0/herokuish_0.8.0_linux_x86_64.tgz \
+RUN curl --location --silent https://github.com/gliderlabs/herokuish/releases/download/v0.9.0/herokuish_0.9.0_linux_x86_64.tgz \
| tar -xzC /bin
```
diff --git a/buildpacks/buildpack-php/buildpack-version b/buildpacks/buildpack-php/buildpack-version
index d0a08b740..bb895b71d 100644
--- a/buildpacks/buildpack-php/buildpack-version
+++ b/buildpacks/buildpack-php/buildpack-version
@@ -1 +1 @@
-v247
+v248
diff --git a/buildpacks/buildpack-scala/tests/scala/.env b/buildpacks/buildpack-scala/tests/scala/.env
new file mode 100644
index 000000000..e3eeb7392
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.env
@@ -0,0 +1 @@
+ENERGY=20 GeV
diff --git a/buildpacks/buildpack-scala/tests/scala/.g8/form/app/controllers/$model__Camel$Controller.scala b/buildpacks/buildpack-scala/tests/scala/.g8/form/app/controllers/$model__Camel$Controller.scala
new file mode 100644
index 000000000..6977727b3
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.g8/form/app/controllers/$model__Camel$Controller.scala
@@ -0,0 +1,46 @@
+package controllers
+
+import javax.inject._
+import play.api.mvc._
+
+import play.api.data._
+import play.api.data.Forms._
+
+case class $model;format="Camel"$Data(name: String, age: Int)
+
+// NOTE: Add the following to conf/routes to enable compilation of this class:
+/*
+GET /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Get()
+POST /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Post()
+*/
+
+/**
+ * $model;format="Camel"$ form controller for Play Scala
+ */
+class $model;format="Camel"$Controller @Inject()(mcc: MessagesControllerComponents) extends MessagesAbstractController(mcc) {
+
+ val $model;format="camel"$Form = Form(
+ mapping(
+ "name" -> text,
+ "age" -> number
+ )($model;format="Camel"$Data.apply)($model;format="Camel"$Data.unapply)
+ )
+
+ def $model;format="camel"$Get() = Action { implicit request: MessagesRequest[AnyContent] =>
+ Ok(views.html.$model;format="camel"$.form($model;format="camel"$Form))
+ }
+
+ def $model;format="camel"$Post() = Action { implicit request: MessagesRequest[AnyContent] =>
+ $model;format="camel"$Form.bindFromRequest().fold(
+ formWithErrors => {
+ // binding failure, you retrieve the form containing errors:
+ BadRequest(views.html.$model;format="camel"$.form(formWithErrors))
+ },
+ $model;format="camel"$Data => {
+ /* binding success, you get the actual value. */
+ /* flashing uses a short lived cookie */
+ Redirect(routes.$model;format="Camel"$Controller.$model;format="camel"$Get()).flashing("success" -> ("Successful " + $model;format="camel"$Data.toString))
+ }
+ )
+ }
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/.g8/form/app/views/$model__camel$/form.scala.html b/buildpacks/buildpack-scala/tests/scala/.g8/form/app/views/$model__camel$/form.scala.html
new file mode 100644
index 000000000..14674ba6e
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.g8/form/app/views/$model__camel$/form.scala.html
@@ -0,0 +1,12 @@
+@($model;format="camel"$Form: Form[$model;format="Camel"$Data])(implicit request: MessagesRequestHeader)
+
+
$model;format="camel"$ form
+
+@request.flash.get("success").getOrElse("")
+
+@helper.form(action = routes.$model;format="Camel"$Controller.$model;format="camel"$Post()) {
+ @helper.CSRF.formField
+ @helper.inputText($model;format="camel"$Form("name"))
+ @helper.inputText($model;format="camel"$Form("age"))
+
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/.g8/form/default.properties b/buildpacks/buildpack-scala/tests/scala/.g8/form/default.properties
new file mode 100644
index 000000000..32090f30c
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.g8/form/default.properties
@@ -0,0 +1,2 @@
+description = Generates a Controller with form handling
+model = user
diff --git a/buildpacks/buildpack-scala/tests/scala/.g8/form/test/controllers/$model__Camel$ControllerSpec.scala b/buildpacks/buildpack-scala/tests/scala/.g8/form/test/controllers/$model__Camel$ControllerSpec.scala
new file mode 100644
index 000000000..d25174315
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.g8/form/test/controllers/$model__Camel$ControllerSpec.scala
@@ -0,0 +1,71 @@
+package controllers
+
+import play.api.mvc._
+import play.api.i18n._
+import org.scalatestplus.play._
+import org.scalatestplus.play.guice.GuiceOneAppPerTest
+import play.api.http.FileMimeTypes
+import play.api.test._
+import play.api.test.Helpers._
+import play.api.test.CSRFTokenHelper._
+
+import scala.concurrent.ExecutionContext
+
+/**
+ * $model;format="Camel"$ form controller specs
+ */
+class $model;format="Camel"$ControllerSpec extends PlaySpec with GuiceOneAppPerTest with Injecting {
+
+ // Provide stubs for components based off Helpers.stubControllerComponents()
+ class StubComponents(cc:ControllerComponents = stubControllerComponents()) extends MessagesControllerComponents {
+ override val parsers: PlayBodyParsers = cc.parsers
+ override val messagesApi: MessagesApi = cc.messagesApi
+ override val langs: Langs = cc.langs
+ override val fileMimeTypes: FileMimeTypes = cc.fileMimeTypes
+ override val executionContext: ExecutionContext = cc.executionContext
+ override val actionBuilder: ActionBuilder[Request, AnyContent] = cc.actionBuilder
+ override val messagesActionBuilder: MessagesActionBuilder = new DefaultMessagesActionBuilderImpl(parsers.default, messagesApi)(executionContext)
+ }
+
+ "$model;format="Camel"$Controller GET" should {
+
+ "render the index page from a new instance of controller" in {
+ val controller = new $model;format="Camel"$Controller(new StubComponents())
+ val request = FakeRequest().withCSRFToken
+ val home = controller.$model;format="camel"$Get().apply(request)
+
+ status(home) mustBe OK
+ contentType(home) mustBe Some("text/html")
+ }
+
+ "render the index page from the application" in {
+ val controller = inject[$model;format="Camel"$Controller]
+ val request = FakeRequest().withCSRFToken
+ val home = controller.$model;format="camel"$Get().apply(request)
+
+ status(home) mustBe OK
+ contentType(home) mustBe Some("text/html")
+ }
+
+ "render the index page from the router" in {
+ val request = CSRFTokenHelper.addCSRFToken(FakeRequest(GET, "/$model;format="camel"$"))
+ val home = route(app, request).get
+
+ status(home) mustBe OK
+ contentType(home) mustBe Some("text/html")
+ }
+ }
+
+ "$model;format="Camel"$Controller POST" should {
+ "process form" in {
+ val request = {
+ FakeRequest(POST, "/$model;format="camel"$")
+ .withFormUrlEncodedBody("name" -> "play", "age" -> "4")
+ }
+ val home = route(app, request).get
+
+ status(home) mustBe SEE_OTHER
+ }
+ }
+
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/.github/CODEOWNERS b/buildpacks/buildpack-scala/tests/scala/.github/CODEOWNERS
new file mode 100644
index 000000000..42e86532e
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.github/CODEOWNERS
@@ -0,0 +1,3 @@
+# Note: Delete this file if you are copying the code in this repository into your own project.
+
+* @heroku/languages
diff --git a/buildpacks/buildpack-scala/tests/scala/.gitignore b/buildpacks/buildpack-scala/tests/scala/.gitignore
new file mode 100644
index 000000000..dce730384
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/.gitignore
@@ -0,0 +1,9 @@
+logs
+target
+/.bsp
+/.idea
+/.idea_modules
+/.classpath
+/.project
+/.settings
+/RUNNING_PID
diff --git a/buildpacks/buildpack-scala/tests/scala/LICENSE b/buildpacks/buildpack-scala/tests/scala/LICENSE
new file mode 100644
index 000000000..9f7552ba2
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2023 Salesforce, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/buildpacks/buildpack-scala/tests/scala/Procfile b/buildpacks/buildpack-scala/tests/scala/Procfile
index 1b9d9070c..5d5f434a3 100644
--- a/buildpacks/buildpack-scala/tests/scala/Procfile
+++ b/buildpacks/buildpack-scala/tests/scala/Procfile
@@ -1 +1 @@
-web: target/universal/stage/bin/hello
+web: target/universal/stage/bin/scala-getting-started -Dhttp.port=${PORT}
diff --git a/buildpacks/buildpack-scala/tests/scala/Procfile.windows b/buildpacks/buildpack-scala/tests/scala/Procfile.windows
new file mode 100644
index 000000000..676de56a3
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/Procfile.windows
@@ -0,0 +1 @@
+web: target\universal\stage\bin\scala-getting-started.bat -Dhttp.port=${PORT}
diff --git a/buildpacks/buildpack-scala/tests/scala/README.md b/buildpacks/buildpack-scala/tests/scala/README.md
new file mode 100644
index 000000000..20218e164
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/README.md
@@ -0,0 +1,21 @@
+# Scala: Getting Started
+
+A barebones Scala app, which can easily be deployed to Heroku.
+
+## Deploying to Heroku
+
+Using resources for this example app counts towards your usage. [Delete your app](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-apps-destroy) and [database](https://devcenter.heroku.com/articles/heroku-postgresql#removing-the-add-on) as soon as you are done experimenting to control costs.
+
+By default, apps use Eco dynos if you are subscribed to Eco. Otherwise, it defaults to Basic dynos. The Eco dynos plan is shared across all Eco dynos in your account and is recommended if you plan on deploying many small apps to Heroku. Learn more about our low-cost plans [here](https://blog.heroku.com/new-low-cost-plans).
+
+Eligible students can apply for platform credits through our new [Heroku for GitHub Students program](https://blog.heroku.com/github-student-developer-program).
+
+This application supports the [Getting Started with Scala on Heroku](https://devcenter.heroku.com/articles/getting-started-with-scala) article - check it out for instructions on how to deploy this app to Heroku and also run it locally.
+
+Alternatively, you can deploy it using this Heroku Button:
+
+[](https://heroku.com/deploy)
+
+For more information about using Scala on Heroku, see these Dev Center articles:
+
+- [Scala on Heroku](https://devcenter.heroku.com/categories/scala)
diff --git a/buildpacks/buildpack-scala/tests/scala/app.json b/buildpacks/buildpack-scala/tests/scala/app.json
new file mode 100644
index 000000000..051c2ad09
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/app.json
@@ -0,0 +1,5 @@
+{
+ "name": "Start on Heroku: Scala",
+ "description": "A barebones Scala app, which can easily be deployed to Heroku.",
+ "addons": ["heroku-postgresql"]
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/app/controllers/Application.scala b/buildpacks/buildpack-scala/tests/scala/app/controllers/Application.scala
new file mode 100644
index 000000000..e93edcc72
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/app/controllers/Application.scala
@@ -0,0 +1,33 @@
+package controllers
+
+import javax.inject._
+import play.api._
+import play.api.db.Database
+import play.api.mvc._
+
+@Singleton
+class Application @Inject()(val controllerComponents: ControllerComponents, val database: Database) extends BaseController {
+
+ def index(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
+ Ok("scala")
+ }
+
+ def db(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
+ // In this getting started app, we don't use a custom execution context to keep the code and configuration simple.
+ // For real-world apps, consult the Play documentation on how to configure custom contexts and how to use them:
+ // https://www.playframework.com/documentation/2.8.19/AccessingAnSQLDatabase#Using-a-CustomExecutionContext
+ database.withConnection { connection =>
+ val statement = connection.createStatement()
+ statement.executeUpdate("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)")
+ statement.executeUpdate("INSERT INTO ticks VALUES (now())")
+
+ val output = new StringBuilder();
+ val resultSet = statement.executeQuery("SELECT tick FROM ticks")
+ while (resultSet.next()) {
+ output.append("Read from DB: " + resultSet.getTimestamp("tick") + "\n")
+ }
+
+ Ok(output.toString())
+ }
+ }
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/app/views/index.scala.html b/buildpacks/buildpack-scala/tests/scala/app/views/index.scala.html
new file mode 100644
index 000000000..15a31da56
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/app/views/index.scala.html
@@ -0,0 +1,4 @@
+@()
+@main {
+ scala
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/app/views/main.scala.html b/buildpacks/buildpack-scala/tests/scala/app/views/main.scala.html
new file mode 100644
index 000000000..eed7fff5e
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/app/views/main.scala.html
@@ -0,0 +1,2 @@
+@(content: Html)
+@content
diff --git a/buildpacks/buildpack-scala/tests/scala/app/views/nav.scala.html b/buildpacks/buildpack-scala/tests/scala/app/views/nav.scala.html
new file mode 100644
index 000000000..a0fa1b318
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/app/views/nav.scala.html
@@ -0,0 +1,33 @@
+
diff --git a/buildpacks/buildpack-scala/tests/scala/build.sbt b/buildpacks/buildpack-scala/tests/scala/build.sbt
index ece22aba0..6f0bb02e0 100644
--- a/buildpacks/buildpack-scala/tests/scala/build.sbt
+++ b/buildpacks/buildpack-scala/tests/scala/build.sbt
@@ -1,15 +1,23 @@
-import NativePackagerKeys._
+name := """scala-getting-started"""
+organization := "com.heroku"
-packageArchetype.java_application
+version := "1.0-SNAPSHOT"
-name := "hello"
+lazy val root = (project in file(".")).enablePlugins(PlayScala)
-version := "1.0"
-
-scalaVersion := "2.10.4"
-
-mainClass in Compile := Some("Web")
+scalaVersion := "2.13.10"
+libraryDependencies += guice
+libraryDependencies += jdbc
+libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test
libraryDependencies ++= Seq(
- "com.twitter" % "finagle-http_2.10" % "6.18.0"
+ "com.google.inject" % "guice" % "5.1.0",
+ "com.google.inject.extensions" % "guice-assistedinject" % "5.1.0",
+ "org.postgresql" % "postgresql" % "42.6.0"
)
+
+// Adds additional packages into Twirl
+//TwirlKeys.templateImports += "com.heroku.controllers._"
+
+// Adds additional packages into conf/routes
+// play.sbt.routes.RoutesKeys.routesImport += "com.heroku.binders._"
diff --git a/buildpacks/buildpack-scala/tests/scala/build.sc b/buildpacks/buildpack-scala/tests/scala/build.sc
new file mode 100644
index 000000000..b162845a5
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/build.sc
@@ -0,0 +1,10 @@
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:`, mill.playlib._
+
+object scalagettingstarted extends PlayModule with SingleModule {
+
+ def scalaVersion = "2.13.10"
+ def playVersion = "2.8.19"
+ def twirlVersion = "1.5.1"
+
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/conf/application.conf b/buildpacks/buildpack-scala/tests/scala/conf/application.conf
new file mode 100644
index 000000000..46b8ece08
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/conf/application.conf
@@ -0,0 +1,23 @@
+# https://www.playframework.com/documentation/latest/Configuration
+
+# Allows all hosts to be valid hosts for requests to this app. This is necessary since this getting started guide
+# makes users deploy their own app of which we don't know the hostname in advance. For production apps, set this
+# to the correct host of your application.
+# More info: https://www.playframework.com/documentation/2.8.x/AllowedHostsFilter
+play.filters.hosts {
+ allowed = ["."]
+}
+
+# Sets the secret key if the APPLICATION_SECRET environment variable isn't set. It is recommended to set the
+# application secret for production apps via heroku config:set on the command line.
+# More info: https://www.playframework.com/documentation/2.8.x/ApplicationSecret
+play.http.secret.key = "YWRmNTNmZDYtMTE5NS00MTc1LWI4YmMtMGU3ZmY2NTE1NDI0Cg=="
+play.http.secret.key = ${?APPLICATION_SECRET}
+
+# Default to "jdbc:postgresql://example.com:5432/database" so that the application at least starts up when
+# JDBC_DATABASE_URL is not set. We use this here to reduce friction when newcomers work with this getting started
+# application. Production applications should not have a default like this, especially not ones that have credentials
+# in them!
+db.default.url = "jdbc:postgresql://example.com:5432/database"
+db.default.url = ${?JDBC_DATABASE_URL}
+db.default.driver = org.postgresql.Driver
diff --git a/buildpacks/buildpack-scala/tests/scala/conf/logback.xml b/buildpacks/buildpack-scala/tests/scala/conf/logback.xml
new file mode 100644
index 000000000..a73d2016e
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/conf/logback.xml
@@ -0,0 +1,40 @@
+
+
+
+
+ ${application.home:-.}/logs/application.log
+
+ UTF-8
+
+ %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) %magenta(%X{akkaSource}) %msg%n
+
+
+
+
+
+ true
+
+ UTF-8
+
+ %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) %magenta(%X{akkaSource}) %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/buildpacks/buildpack-scala/tests/scala/conf/messages b/buildpacks/buildpack-scala/tests/scala/conf/messages
new file mode 100644
index 000000000..0226738a6
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/conf/messages
@@ -0,0 +1 @@
+# https://www.playframework.com/documentation/latest/ScalaI18N
diff --git a/buildpacks/buildpack-scala/tests/scala/conf/routes b/buildpacks/buildpack-scala/tests/scala/conf/routes
new file mode 100644
index 000000000..b22a4d517
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/conf/routes
@@ -0,0 +1,10 @@
+# Routes
+# This file defines all application routes (Higher priority routes first)
+# https://www.playframework.com/documentation/latest/ScalaRouting
+# ~~~~
+
+GET / controllers.Application.index()
+GET /database controllers.Application.db()
+
+# Map static resources from the /public folder to the /assets URL path
+GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
diff --git a/buildpacks/buildpack-scala/tests/scala/project/build.properties b/buildpacks/buildpack-scala/tests/scala/project/build.properties
index 1a1a23239..563a014da 100644
--- a/buildpacks/buildpack-scala/tests/scala/project/build.properties
+++ b/buildpacks/buildpack-scala/tests/scala/project/build.properties
@@ -1,4 +1 @@
-#Activator-generated Properties
-#Wed Aug 13 09:36:12 CDT 2014
-template.uuid=a855816c-0367-44ba-9adb-6a903f6ad599
-sbt.version=0.13.11
+sbt.version=1.7.2
diff --git a/buildpacks/buildpack-scala/tests/scala/project/plugins.sbt b/buildpacks/buildpack-scala/tests/scala/project/plugins.sbt
index cf3a834eb..8846622ec 100644
--- a/buildpacks/buildpack-scala/tests/scala/project/plugins.sbt
+++ b/buildpacks/buildpack-scala/tests/scala/project/plugins.sbt
@@ -1,13 +1,2 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// The Typesafe repository
-resolvers += "Typesafe Releases Repository" at "https://repo.typesafe.com/typesafe/releases/"
-
-// The Maven repository
-resolvers += "Maven Central Server" at "https://repo1.maven.org/maven2"
-
-// The "public" repository
-resolvers += "public" at "https://repo1.maven.org/maven2"
-
-addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.7.5-RC2")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.19")
+addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.13.1")
diff --git a/buildpacks/buildpack-scala/tests/scala/public/images/favicon.png b/buildpacks/buildpack-scala/tests/scala/public/images/favicon.png
new file mode 100644
index 000000000..c7d92d2ae
Binary files /dev/null and b/buildpacks/buildpack-scala/tests/scala/public/images/favicon.png differ
diff --git a/buildpacks/buildpack-scala/tests/scala/public/images/lang-logo.png b/buildpacks/buildpack-scala/tests/scala/public/images/lang-logo.png
new file mode 100644
index 000000000..79c9ce691
Binary files /dev/null and b/buildpacks/buildpack-scala/tests/scala/public/images/lang-logo.png differ
diff --git a/buildpacks/buildpack-scala/tests/scala/public/stylesheets/main.css b/buildpacks/buildpack-scala/tests/scala/public/stylesheets/main.css
new file mode 100644
index 000000000..006f453af
--- /dev/null
+++ b/buildpacks/buildpack-scala/tests/scala/public/stylesheets/main.css
@@ -0,0 +1,39 @@
+.jumbotron {
+ background: #532F8C;
+ color: white;
+ padding-bottom: 80px;
+}
+
+.jumbotron .btn-primary {
+ background: #845ac7;
+ border-color: #845ac7;
+}
+
+.jumbotron .btn-primary:hover {
+ background: #7646c1;
+}
+
+.jumbotron p {
+ color: #d9ccee;
+ max-width: 75%;
+ margin: 1em auto 2em;
+}
+
+.navbar + .jumbotron {
+ margin-top: -20px;
+}
+
+.jumbotron .lang-logo {
+ display: block;
+ background: #B01302;
+ border-radius: 50%;
+ overflow: hidden;
+ width: 100px;
+ height: 100px;
+ margin: auto;
+ border: 2px solid white;
+}
+
+.jumbotron .lang-logo img {
+ max-width: 100%;
+}
diff --git a/buildpacks/buildpack-scala/tests/scala/src/main/scala/web.scala b/buildpacks/buildpack-scala/tests/scala/src/main/scala/web.scala
deleted file mode 100644
index 7f2eb1626..000000000
--- a/buildpacks/buildpack-scala/tests/scala/src/main/scala/web.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-import com.twitter.finagle.{Http, Service}
-import com.twitter.util.{Await, Future}
-import com.twitter.finagle.http.Response
-import java.net.InetSocketAddress
-import org.jboss.netty.handler.codec.http._
-import util.Properties
-
-object Web {
- def main(args: Array[String]) {
- val port = Properties.envOrElse("PORT", "8080").toInt
- println("Starting on port:"+port)
-
- val server = Http.serve(":" + port, new Hello)
- Await.ready(server)
- }
-}
-
-class Hello extends Service[HttpRequest, HttpResponse] {
- def apply(req: HttpRequest): Future[HttpResponse] = {
- val response = Response()
- response.setStatusCode(200)
- response.setContentString("scala\n")
- Future(response)
- }
-}
diff --git a/buildpacks/buildpack-scala/tests/scala/system.properties b/buildpacks/buildpack-scala/tests/scala/system.properties
index 97270b43f..b21dad9cb 100644
--- a/buildpacks/buildpack-scala/tests/scala/system.properties
+++ b/buildpacks/buildpack-scala/tests/scala/system.properties
@@ -1 +1,2 @@
-java.runtime.version=1.7
+# https://devcenter.heroku.com/articles/java-support#specifying-a-java-version
+java.runtime.version=17