Skip to content

Commit 60714a4

Browse files
Gedochaobtomala
andauthored
Bump scala-packager to 0.2.1 & enable adding extra directories to a docker image (#3908)
* Bump `scala-packager` to 0.2.1 * Add `--docker-extra-directories` command line option for the `package` sub-command * Add `//> using packager.dockerExtraDirectories` directive * Add a simple test for adding an extra directory to a docker image * fix 'pass extra directory to docker' test --------- Co-authored-by: Bartłomiej Tomala <btomala@users.noreply.github.com>
1 parent 2e7f150 commit 60714a4

File tree

10 files changed

+114
-8
lines changed

10 files changed

+114
-8
lines changed

modules/cli/src/main/scala/scala/cli/commands/package0/Package.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,8 @@ object Package extends ScalaCommand[PackageOptions] with BuildCommandHelpers {
683683
repository = repository,
684684
tag = Some(tag),
685685
exec = exec,
686-
dockerExecutable = None
686+
dockerExecutable = None,
687+
extraDirectories = packageOptions.dockerOptions.extraDirectories.map(_.toNIO)
687688
)
688689

689690
val appPath = os.temp.dir(prefix = "scala-cli-docker") / "app"

modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ final case class PackageOptions(
219219
imageRepository = packager.dockerImageRepository,
220220
imageTag = packager.dockerImageTag,
221221
cmd = packager.dockerCmd,
222-
isDockerEnabled = Some(docker)
222+
isDockerEnabled = Some(docker),
223+
extraDirectories = packager.dockerExtraDirectories.map(os.Path(_, os.pwd))
223224
),
224225
nativeImageOptions = NativeImageOptions(
225226
graalvmJvmId = packager.graalvmJvmId.map(_.trim).filter(_.nonEmpty),

modules/cli/src/main/scala/scala/cli/commands/package0/PackagerOptions.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ final case class PackagerOptions(
138138
)
139139
@Tag(tags.restricted)
140140
dockerCmd: Option[String] = None,
141+
142+
@Group(HelpGroup.Docker.toString)
143+
@HelpMessage("Extra directories to be added to the docker image")
144+
@Tag(tags.restricted)
145+
dockerExtraDirectories: List[String] = Nil,
141146

142147
@Group(HelpGroup.NativeImage.toString)
143148
@HelpMessage(s"GraalVM Java major version to use to build GraalVM native images (${Constants.defaultGraalVMJavaVersion} by default)")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package scala.build.errors
2+
3+
class WrongDirectoryPathError(cause: Throwable) extends BuildException(
4+
message = s"""The directory path argument in the using directives at could not be found!
5+
|${cause.getLocalizedMessage}""".stripMargin,
6+
cause = cause
7+
)

modules/directives/src/main/scala/scala/build/preprocessing/directives/Packaging.scala

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import scala.build.errors.{
1010
BuildException,
1111
CompositeBuildException,
1212
MalformedInputError,
13-
ModuleFormatError
13+
ModuleFormatError,
14+
WrongDirectoryPathError
1415
}
1516
import scala.build.options.*
1617
import scala.build.options.packaging.{DockerOptions, NativeImageOptions}
1718
import scala.cli.commands.SpecificationLevel
19+
import scala.util.Try
1820

1921
@DirectiveGroupName("Packaging")
2022
@DirectivePrefix("packaging.")
@@ -28,6 +30,10 @@ import scala.cli.commands.SpecificationLevel
2830
@DirectiveExamples("//> using packaging.dockerImageRepository scala-cli")
2931
@DirectiveExamples("//> using packaging.dockerCmd sh")
3032
@DirectiveExamples("//> using packaging.dockerCmd node")
33+
@DirectiveExamples(
34+
"//> using packaging.dockerExtraDirectories path/to/directory1 path/to/directory2"
35+
)
36+
@DirectiveExamples("//> using packaging.dockerExtraDirectory path/to/directory")
3137
@DirectiveUsage(
3238
"""using packaging.packageType [package type]
3339
|using packaging.output [destination path]
@@ -38,6 +44,7 @@ import scala.cli.commands.SpecificationLevel
3844
|using packaging.dockerImageRegistry [image registry]
3945
|using packaging.dockerImageRepository [image repository]
4046
|using packaging.dockerCmd [docker command]
47+
|using packaging.dockerExtraDirectories [directories]
4148
|""".stripMargin,
4249
"""`//> using packaging.packageType` _package-type_
4350
|
@@ -57,6 +64,9 @@ import scala.cli.commands.SpecificationLevel
5764
|
5865
|`//> using packaging.dockerCmd` _docker-command_
5966
|
67+
|`//> using packaging.dockerExtraDirectories` _directories_
68+
|`//> using packaging.dockerExtraDirectory` _directory_
69+
|
6070
|""".stripMargin
6171
)
6272
@DirectiveDescription("Set parameters for packaging")
@@ -70,7 +80,10 @@ final case class Packaging(
7080
dockerImageTag: Option[String] = None,
7181
dockerImageRegistry: Option[String] = None,
7282
dockerImageRepository: Option[String] = None,
73-
dockerCmd: Option[String] = None
83+
dockerCmd: Option[String] = None,
84+
@DirectiveName("dockerExtraDirectory")
85+
dockerExtraDirectories: DirectiveValueParser.WithScopePath[List[Positioned[String]]] =
86+
DirectiveValueParser.WithScopePath.empty(Nil)
7487
) extends HasBuildOptions {
7588
def buildOptions: Either[BuildException, BuildOptions] = either {
7689
val maybePackageTypeOpt = packageType
@@ -110,6 +123,23 @@ final case class Packaging(
110123
.left.map(CompositeBuildException(_))
111124
}
112125

126+
val cwd = dockerExtraDirectories.scopePath
127+
val extraDirectories = value {
128+
dockerExtraDirectories
129+
.value
130+
.map { posPathStr =>
131+
val eitherRootPathOrBuildException =
132+
Directive.osRoot(cwd, posPathStr.positions.headOption)
133+
eitherRootPathOrBuildException.flatMap { root =>
134+
Try(os.Path(posPathStr.value, root))
135+
.toEither
136+
.left.map(new WrongDirectoryPathError(_))
137+
}
138+
}
139+
.sequence
140+
.left.map(CompositeBuildException(_))
141+
}
142+
113143
BuildOptions(
114144
internal = InternalOptions(
115145
keepResolution = provided0.nonEmpty || packageTypeOpt.contains(PackageType.Spark)
@@ -124,7 +154,8 @@ final case class Packaging(
124154
imageRegistry = dockerImageRegistry,
125155
imageRepository = dockerImageRepository,
126156
imageTag = dockerImageTag,
127-
cmd = dockerCmd
157+
cmd = dockerCmd,
158+
extraDirectories = extraDirectories
128159
),
129160
nativeImageOptions = NativeImageOptions(
130161
graalvmArgs = graalvmArgs

modules/integration/src/test/scala/scala/cli/integration/PackageTestDefinitions.scala

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,13 +1118,62 @@ abstract class PackageTestDefinitions extends ScalaCliSuite with TestScalaVersio
11181118
}
11191119
}
11201120

1121-
if (Properties.isLinux)
1121+
def dockerWithExtraDirsTest(): Unit = {
1122+
val codePath = os.rel / "src" / "Hello.scala"
1123+
val extraFileName = "extraFile.txt"
1124+
val extraFileDir = os.rel / "extraDir"
1125+
val extraFilePath = extraFileDir / extraFileName
1126+
val imageName = "extradir"
1127+
val expectedOutput = "hello"
1128+
val inputs = TestInputs(
1129+
codePath ->
1130+
s"""//> using toolkit default
1131+
|
1132+
|object Smth extends App {
1133+
| val content =
1134+
| os.walk(os.pwd)
1135+
| .filter(os.isFile)
1136+
| .filter(_.endsWith(os.rel / "$extraFileName"))
1137+
| .headOption
1138+
| .map(file => os.read(file).trim())
1139+
| .getOrElse("No matching files found")
1140+
| println(content)
1141+
|}
1142+
|""".stripMargin,
1143+
extraFilePath -> expectedOutput
1144+
)
1145+
inputs.fromRoot { root =>
1146+
os.proc(
1147+
TestUtil.cli,
1148+
"--power",
1149+
"package",
1150+
codePath,
1151+
"--docker",
1152+
"--docker-image-repository",
1153+
imageName,
1154+
"--docker-extra-directories",
1155+
root / extraFileDir,
1156+
"-f"
1157+
).call(cwd = root)
1158+
val output = os.proc("docker", "run", imageName).call(cwd = root).out.trim()
1159+
expect(output == expectedOutput)
1160+
}
1161+
}
1162+
1163+
if (Properties.isLinux) {
11221164
test("pass java options to docker") {
11231165
TestUtil.retryOnCi() {
11241166
javaOptionsDockerTest()
11251167
}
11261168
}
11271169

1170+
test("pass extra directory to docker") {
1171+
TestUtil.retryOnCi() {
1172+
dockerWithExtraDirsTest()
1173+
}
1174+
}
1175+
}
1176+
11281177
test("default values in help") {
11291178
TestInputs.empty.fromRoot { root =>
11301179
val res = os.proc(TestUtil.cli, "--power", "package", extraOptions, "--help").call(cwd = root)

modules/options/src/main/scala/scala/build/options/packaging/DockerOptions.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ final case class DockerOptions(
88
imageRepository: Option[String] = None,
99
imageTag: Option[String] = None,
1010
cmd: Option[String] = None,
11-
isDockerEnabled: Option[Boolean] = None
11+
isDockerEnabled: Option[Boolean] = None,
12+
extraDirectories: Seq[os.Path] = Nil
1213
)
1314

1415
object DockerOptions {

project/deps/package.mill.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ object Deps {
134134
def maxScalaNativeForTypelevelToolkit = scalaNative04
135135
def maxScalaNativeForScalaPy = scalaNative04
136136
def maxScalaNativeForMillExport = scalaNative05
137-
def scalaPackager = "0.2.0"
137+
def scalaPackager = "0.2.1"
138138
def signingCli = "0.2.11"
139139
def signingCliJvmVersion = Java.defaultJava
140140
def javaSemanticdb = "0.10.0"

website/docs/reference/cli-options.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,10 @@ The image tag; the default tag is `latest`
972972

973973
Allows to override the executable used to run the application in docker, otherwise it defaults to sh for the JVM platform and node for the JS platform
974974

975+
### `--docker-extra-directories`
976+
977+
Extra directories to be added to the docker image
978+
975979
### `--graalvm-java-version`
976980

977981
GraalVM Java major version to use to build GraalVM native images (17 by default)

website/docs/reference/directives.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ Set parameters for packaging
300300

301301
`//> using packaging.dockerCmd` _docker-command_
302302

303+
`//> using packaging.dockerExtraDirectories` _directories_
304+
`//> using packaging.dockerExtraDirectory` _directory_
305+
303306

304307

305308
#### Examples
@@ -323,6 +326,10 @@ Set parameters for packaging
323326

324327
`//> using packaging.dockerCmd node`
325328

329+
`//> using packaging.dockerExtraDirectories path/to/directory1 path/to/directory2`
330+
331+
`//> using packaging.dockerExtraDirectory path/to/directory`
332+
326333
### Platform
327334

328335
Set the default platform to Scala.js or Scala Native

0 commit comments

Comments
 (0)