Skip to content

Commit 75fd085

Browse files
committed
FIX #285 FIX #287 FIX #52 Improved docs for packageMappings in Universal and Linux
1 parent 7cc2e09 commit 75fd085

File tree

4 files changed

+380
-3
lines changed

4 files changed

+380
-3
lines changed

src/sphinx/DetailedTopics/archetypes.rst

+104
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,107 @@ You can use ``${{variable_name}}`` to reference variables when writing your scir
195195

196196
Creating a file here will override the ``/etc/default/<application>`` template
197197
used when SystemV is the server loader.
198+
199+
200+
SBT Assembly
201+
------------
202+
203+
This isn't currently an archetype itself, but you can configure it yourself very easily.
204+
First add the sbt-assembly plugin to your `plugins.sbt` file.
205+
206+
.. code-block:: scala
207+
208+
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
209+
210+
The next step is to remove all the jar mappings from the normal mappings and only add the
211+
assembly jar. In this example we'll set the assembly jar name ourself, so we know exactly
212+
what the output should look like. Finally we change the ``scriptClasspath`` so it only
213+
contains the assembled jar. This is what the final ``build.sbt`` should contain:
214+
215+
.. code-block:: scala
216+
217+
// the assembly settings
218+
assemblySettings
219+
220+
// we specify the name for our fat jar
221+
jarName in assembly := "assembly-project.jar"
222+
223+
// using the java server for this application. java_application is fine, too
224+
packageArchetype.java_server
225+
226+
// removes all jar mappings in universal and appends the fat jar
227+
mappings in Universal := {
228+
// universalMappings: Seq[(File,String)]
229+
val universalMappings = (mappings in Universal).value
230+
val fatJar = (assembly in Compile).value
231+
// removing means filtering
232+
val filtered = universalMappings filter {
233+
case (file, name) => ! name.endsWith(".jar")
234+
}
235+
// add the fat jar
236+
filtered :+ (fatJar -> ("lib/" + fatJar.getName))
237+
}
238+
239+
240+
// the bash scripts classpath only needs the fat jar
241+
scriptClasspath := Seq( (jarName in assembly).value )
242+
243+
Multi Module Builds
244+
-------------------
245+
246+
If you want to aggregate different projects in a multi module build to a single package,
247+
you can specify everthing in a single ``build.sbt``
248+
249+
.. code-block:: scala
250+
251+
import NativePackagerKeys._
252+
253+
name := "mukis-fullstack"
254+
255+
// used like the groupId in maven
256+
organization in ThisBuild := "de.mukis"
257+
258+
// all sub projects have the same version
259+
version in ThisBuild := "1.0"
260+
261+
scalaVersion in ThisBuild := "2.11.2"
262+
263+
// common dependencies
264+
libraryDependencies in ThisBuild ++= Seq(
265+
"com.typesafe" % "config" % "1.2.0"
266+
)
267+
268+
// this is the root project, aggregating all sub projects
269+
lazy val root = Project(
270+
id = "root",
271+
base = file("."),
272+
// configure your native packaging settings here
273+
settings = packageArchetype.java_server++ Seq(
274+
maintainer := "John Smith <[email protected]>",
275+
packageDescription := "Fullstack Application",
276+
packageSummary := "Fullstack Application",
277+
// entrypoint
278+
mainClass in Compile := Some("de.mukis.frontend.ProductionServer")
279+
),
280+
// always run all commands on each sub project
281+
aggregate = Seq(frontend, backend, api)
282+
) dependsOn(frontend, backend, api) // this does the actual aggregation
283+
284+
// --------- Project Frontend ------------------
285+
lazy val frontend = Project(
286+
id = "frontend",
287+
base = file("frontend")
288+
) dependsOn(api)
289+
290+
291+
// --------- Project Backend ----------------
292+
lazy val backend = Project(
293+
id = "backend",
294+
base = file("backend")
295+
) dependsOn(api)
296+
297+
// --------- Project API ------------------
298+
lazy val api = Project(
299+
id = "api",
300+
base = file("api")
301+
)

src/sphinx/DetailedTopics/linux.rst

+218-3
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ The required fields for any linux distribution are:
2828
Package Mappings
2929
----------------
3030

31-
Most of the work in generating a linux package is constructing package mappings. These 'map' a file to a location on disk where it should reside as well as information about that file. Package mappings allow the specification of file ownership, permissions and whether or not the file can be considered "configuration".
31+
Most of the work in generating a linux package is constructing package mappings. These 'map' a file to a location on disk where it should
32+
reside as well as information about that file. Package mappings allow the specification of file ownership, permissions and whether or not
33+
the file can be considered "configuration".
3234

33-
Note that while the ``sbt-native-packager`` plugin allows you to specify all of this information, not all platforms will make use of the information. It's best to be specific
34-
about how you want files handled and run tests on each platform you wish to deploy to.
35+
Note that while the ``sbt-native-packager`` plugin allows you to specify all of this information, not all platforms will make use of the
36+
information. It's best to be specific about how you want files handled and run tests on each platform you wish to deploy to.
3537

3638
A package mapping takes this general form
3739

@@ -40,6 +42,7 @@ A package mapping takes this general form
4042
(packageMapping(
4143
file -> "/usr/share/man/man1/sbt.1.gz"
4244
) withPerms "0644" gzipped) asDocs()
45+
4346
4447
4548
Let's look at each of the methods supported in the packageMapping 'library'.
@@ -67,8 +70,220 @@ Let's look at each of the methods supported in the packageMapping 'library'.
6770

6871
``withGroup(group:String)``
6972
This denotes which group should be the owner of the given files in the resulting package.
73+
7074

7175

76+
The LinuxPackageMapping Models
77+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
78+
79+
All classes are located in the ``com.typesafe.sbt.packager.linux`` package. So if you want to create
80+
instances yourself you have to add ``import com.typesafe.sbt.packager.linux._`` to your build file.
81+
82+
A ``LinuxPackageMapping`` contains the following fields:
83+
84+
``mappings: Traversable[(File, String)]``
85+
A list of mappings aggregated by this LinuxPackageMapping
86+
87+
``fileData: LinuxFileMetaData``
88+
Permissions for all the defined mappings. Default to "root:root 755"
89+
90+
``zipped: Boolean``
91+
Are the mappings zipped. Default to false
92+
93+
All mappings are stored in the task ``linuxPackageMappings`` which returns a ``Seq[LinuxPackageMapping]``. To display the contents
94+
open the sbt console and call
95+
96+
.. code-block:: bash
97+
98+
show linuxPackageMappings
99+
100+
101+
The ``LinuxFileMetaData`` has the following fields
102+
103+
``user: String``
104+
The user owning all the mappings. Default "root"
105+
106+
``group: String``
107+
The group owning all the mappings. Default "root"
108+
109+
``permissions: String``
110+
Access permissions for all the mappings. Default "755"
111+
112+
``config: String``
113+
Are the mappings config files. Default "false"
114+
115+
``docs: Boolean``
116+
Are the mappings docs. Default to false
117+
118+
Last but not least there are the ``linuxPackageSymlinks``, which encapsulate symlinks on your
119+
destination system. A ``LinuxSymlink`` contains only two fields
120+
121+
``link: String``
122+
The actual link that points to ``destination``
123+
124+
``destination: String``
125+
The link destination
126+
127+
You can see all currently configured symlinks with this simple command.
128+
``linuxPackageSymlinks`` is just a ``Seq[LinuxSymlink]``
129+
130+
.. code-block:: bash
131+
132+
show linuxPackageSymlinks
133+
134+
135+
Modifying Mappings in General
136+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
137+
138+
Adding, filtering and altering mappings are always simple methods on a sequence: ``Seq[LinuxPackageMapping]``.
139+
The basic contstruct for adding looks like this
140+
141+
.. code-block:: scala
142+
143+
// simple
144+
linuxPackageMappings += packageMapping( (theFile, "/absolute/path/somefile.txt") )
145+
146+
// specialized
147+
linuxPackageMappings += packageMapping( (theFile, "/absolute/path/somefile.txt") ) withPerms("644") asDocs()
148+
149+
If you want to filter or alter things. The example has a lot of things you can _possibly_ do. Just pick
150+
what you need. After this section there are smaller examples, showing how you can implemenet certain functions.
151+
152+
.. code-block:: scala
153+
154+
// sbt 0.13.0 syntax
155+
linuxPackageMappings := {
156+
// mappings: Seq[LinuxPackageMapping]
157+
val mappings = linuxPackageMappings.value
158+
// this process will must return another Seq[LinuxPackageMapping]
159+
mappings map { linuxPackage =>
160+
// basic scala collections operations. Seq[(java.io.File, String)]
161+
val filtered = linuxPackage.mappings map {
162+
case (file, name) => file -> name // altering stuff here
163+
} filter {
164+
case (file, name) => true // remove stuff from mappings
165+
}
166+
// case class copy method. Specify only what you need
167+
val fileData = linuxPackage.fileData.copy(
168+
user = "new user",
169+
group = "another group",
170+
permissions = "444",
171+
config = "false",
172+
docs = false
173+
)
174+
// case class copy method. Specify only what you need.
175+
// returns a fresh LinuxPackageMapping
176+
linuxPackage.copy(
177+
mappings = filterd,
178+
fileData = fileData
179+
)
180+
} filter {
181+
linuxPackage => linuxPackage.mappings.nonEmpty // remove stuff. Here all empty linuxPackageMappings
182+
}
183+
}
184+
185+
// sbt 0.12.x syntax
186+
linuxPackageMappings <<= linuxPackageMappings map { mappings =>
187+
/* stuff. see above */
188+
mappings
189+
}
190+
191+
The ordering in which you apply the tasks is important.
192+
193+
Add Mappings
194+
~~~~~~~~~~~~
195+
196+
To add an arbitrary file in your build path
197+
198+
.. code-block:: scala
199+
200+
linuxPackageMappings += {
201+
val file = sourceDirectory.value / "resources" / "somefile.txt"
202+
packageMapping( (file, "/absolute/path/somefile.txt") )
203+
}
204+
205+
``linuxPackageMappings`` can be scoped to ``Rpm` or ``Debian`` if you want to add mappings only for a single packacking type.
206+
207+
.. code-block:: scala
208+
209+
linuxPackageMappings in Debian += {
210+
val file = sourceDirectory.value / "resources" / "debian-somefile.txt"
211+
packageMapping( (file, "/absolute/path/somefile.txt") )
212+
}
213+
214+
linuxPackageMappings in Rpm += {
215+
val file = sourceDirectory.value / "resources" / "rpm-somefile.txt"
216+
packageMapping( (file, "/absolute/path/somefile.txt") )
217+
}
218+
219+
220+
Filter/Remove Mappings
221+
~~~~~~~~~~~~~~~~~~~~~~
222+
223+
If you want to remove some mappings you have to filter the current list of ``linuxPackageMappings``.
224+
As ``linuxPackageMappings`` is a task, the order of your settings is important. Here are some examples
225+
on how to filter mappings.
226+
227+
.. code-block:: scala
228+
229+
// this is equal to
230+
// linuxPackageMappings <<= linuxPackageMappings map { mappings => /* stuff */ mappings }
231+
linuxPackageMappings := {
232+
// first get the current mappings. mapping is of type Seq[LinuxPackageMapping]
233+
val mappings = linuxPackageMappings.value
234+
// map over the mappings if you want to change them
235+
mappings map { mapping =>
236+
// we remove everything besides files that end with ".conf"
237+
val filtered = mapping.mappings filter {
238+
case (file, name) => name endsWith ".conf"
239+
}
240+
// now we copy the mapping but replace the mappings
241+
mapping.copy(mappings = filtered)
242+
} filter {
243+
// remove all LinuxPackageMapping instances that have to file mappings
244+
_.mappings.nonEmpty
245+
}
246+
}
247+
248+
Alter LinuxPackageMapping
249+
~~~~~~~~~~~~~~~~~~~~~~~~~
250+
251+
First we alter the permissions for all ``LinuxPackageMapping``s that match a specific criteria.
252+
253+
.. code-block:: scala
254+
255+
// Altering permissions for configs
256+
linuxPackageMappings := {
257+
val mappings = linuxPackageMappings.value
258+
// Changing the group for all configs
259+
mappings map {
260+
case linuxPackage if linuxPackage.fileData.config equals "true" =>
261+
// altering the group
262+
val newFileData = linuxPackage.fileData.copy(
263+
group = "appdocs"
264+
)
265+
// altering the LinuxPackageMapping
266+
linuxPackage.copy(
267+
fileData = newFileData
268+
)
269+
case linuxPackage => linuxPackage
270+
}
271+
}
272+
273+
Alter LinuxSymlinks
274+
~~~~~~~~~~~~~~~~~~~
275+
276+
First we alter the permissions for all ``LinuxPackageMapping``s that match a specific criteria.
277+
278+
.. code-block:: scala
279+
280+
// The same as linuxPackageMappings
281+
linuxPackageSymlinks := {
282+
val links = linuxPackageSymlinks.value
283+
284+
links filter { /* remove stuff */ } map { /* change stuff */}
285+
}
286+
72287
.. toctree::
73288
:maxdepth: 2
74289

0 commit comments

Comments
 (0)