diff --git a/src/sphinx/DetailedTopics/archetypes.rst b/src/sphinx/DetailedTopics/archetypes.rst index ad5b48eec..3e5ccf9f3 100644 --- a/src/sphinx/DetailedTopics/archetypes.rst +++ b/src/sphinx/DetailedTopics/archetypes.rst @@ -195,3 +195,107 @@ You can use ``${{variable_name}}`` to reference variables when writing your scir Creating a file here will override the ``/etc/default/`` template used when SystemV is the server loader. + + +SBT Assembly +------------ + +This isn't currently an archetype itself, but you can configure it yourself very easily. +First add the sbt-assembly plugin to your `plugins.sbt` file. + +.. code-block:: scala + + addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2") + +The next step is to remove all the jar mappings from the normal mappings and only add the +assembly jar. In this example we'll set the assembly jar name ourself, so we know exactly +what the output should look like. Finally we change the ``scriptClasspath`` so it only +contains the assembled jar. This is what the final ``build.sbt`` should contain: + +.. code-block:: scala + + // the assembly settings + assemblySettings + + // we specify the name for our fat jar + jarName in assembly := "assembly-project.jar" + + // using the java server for this application. java_application is fine, too + packageArchetype.java_server + + // removes all jar mappings in universal and appends the fat jar + mappings in Universal := { + // universalMappings: Seq[(File,String)] + val universalMappings = (mappings in Universal).value + val fatJar = (assembly in Compile).value + // removing means filtering + val filtered = universalMappings filter { + case (file, name) => ! name.endsWith(".jar") + } + // add the fat jar + filtered :+ (fatJar -> ("lib/" + fatJar.getName)) + } + + + // the bash scripts classpath only needs the fat jar + scriptClasspath := Seq( (jarName in assembly).value ) + +Multi Module Builds +------------------- + +If you want to aggregate different projects in a multi module build to a single package, +you can specify everthing in a single ``build.sbt`` + +.. code-block:: scala + + import NativePackagerKeys._ + + name := "mukis-fullstack" + + // used like the groupId in maven + organization in ThisBuild := "de.mukis" + + // all sub projects have the same version + version in ThisBuild := "1.0" + + scalaVersion in ThisBuild := "2.11.2" + + // common dependencies + libraryDependencies in ThisBuild ++= Seq( + "com.typesafe" % "config" % "1.2.0" + ) + + // this is the root project, aggregating all sub projects + lazy val root = Project( + id = "root", + base = file("."), + // configure your native packaging settings here + settings = packageArchetype.java_server++ Seq( + maintainer := "John Smith ", + packageDescription := "Fullstack Application", + packageSummary := "Fullstack Application", + // entrypoint + mainClass in Compile := Some("de.mukis.frontend.ProductionServer") + ), + // always run all commands on each sub project + aggregate = Seq(frontend, backend, api) + ) dependsOn(frontend, backend, api) // this does the actual aggregation + + // --------- Project Frontend ------------------ + lazy val frontend = Project( + id = "frontend", + base = file("frontend") + ) dependsOn(api) + + + // --------- Project Backend ---------------- + lazy val backend = Project( + id = "backend", + base = file("backend") + ) dependsOn(api) + + // --------- Project API ------------------ + lazy val api = Project( + id = "api", + base = file("api") + ) diff --git a/src/sphinx/DetailedTopics/linux.rst b/src/sphinx/DetailedTopics/linux.rst index a62a0278a..075e61d0d 100644 --- a/src/sphinx/DetailedTopics/linux.rst +++ b/src/sphinx/DetailedTopics/linux.rst @@ -28,10 +28,12 @@ The required fields for any linux distribution are: Package Mappings ---------------- -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". +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". - 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 - about how you want files handled and run tests on each platform you wish to deploy to. + 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 about how you want files handled and run tests on each platform you wish to deploy to. A package mapping takes this general form @@ -40,6 +42,7 @@ A package mapping takes this general form (packageMapping( file -> "/usr/share/man/man1/sbt.1.gz" ) withPerms "0644" gzipped) asDocs() + 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'. ``withGroup(group:String)`` This denotes which group should be the owner of the given files in the resulting package. + +The LinuxPackageMapping Models +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All classes are located in the ``com.typesafe.sbt.packager.linux`` package. So if you want to create +instances yourself you have to add ``import com.typesafe.sbt.packager.linux._`` to your build file. + +A ``LinuxPackageMapping`` contains the following fields: + + ``mappings: Traversable[(File, String)]`` + A list of mappings aggregated by this LinuxPackageMapping + + ``fileData: LinuxFileMetaData`` + Permissions for all the defined mappings. Default to "root:root 755" + + ``zipped: Boolean`` + Are the mappings zipped. Default to false + +All mappings are stored in the task ``linuxPackageMappings`` which returns a ``Seq[LinuxPackageMapping]``. To display the contents +open the sbt console and call + +.. code-block:: bash + + show linuxPackageMappings + + +The ``LinuxFileMetaData`` has the following fields + + ``user: String`` + The user owning all the mappings. Default "root" + + ``group: String`` + The group owning all the mappings. Default "root" + + ``permissions: String`` + Access permissions for all the mappings. Default "755" + + ``config: String`` + Are the mappings config files. Default "false" + + ``docs: Boolean`` + Are the mappings docs. Default to false + +Last but not least there are the ``linuxPackageSymlinks``, which encapsulate symlinks on your +destination system. A ``LinuxSymlink`` contains only two fields + + ``link: String`` + The actual link that points to ``destination`` + + ``destination: String`` + The link destination + +You can see all currently configured symlinks with this simple command. +``linuxPackageSymlinks`` is just a ``Seq[LinuxSymlink]`` + +.. code-block:: bash + + show linuxPackageSymlinks + + +Modifying Mappings in General +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Adding, filtering and altering mappings are always simple methods on a sequence: ``Seq[LinuxPackageMapping]``. +The basic contstruct for adding looks like this + +.. code-block:: scala + + // simple + linuxPackageMappings += packageMapping( (theFile, "/absolute/path/somefile.txt") ) + + // specialized + linuxPackageMappings += packageMapping( (theFile, "/absolute/path/somefile.txt") ) withPerms("644") asDocs() + +If you want to filter or alter things. The example has a lot of things you can _possibly_ do. Just pick +what you need. After this section there are smaller examples, showing how you can implemenet certain functions. + +.. code-block:: scala + + // sbt 0.13.0 syntax + linuxPackageMappings := { + // mappings: Seq[LinuxPackageMapping] + val mappings = linuxPackageMappings.value + // this process will must return another Seq[LinuxPackageMapping] + mappings map { linuxPackage => + // basic scala collections operations. Seq[(java.io.File, String)] + val filtered = linuxPackage.mappings map { + case (file, name) => file -> name // altering stuff here + } filter { + case (file, name) => true // remove stuff from mappings + } + // case class copy method. Specify only what you need + val fileData = linuxPackage.fileData.copy( + user = "new user", + group = "another group", + permissions = "444", + config = "false", + docs = false + ) + // case class copy method. Specify only what you need. + // returns a fresh LinuxPackageMapping + linuxPackage.copy( + mappings = filterd, + fileData = fileData + ) + } filter { + linuxPackage => linuxPackage.mappings.nonEmpty // remove stuff. Here all empty linuxPackageMappings + } + } + + // sbt 0.12.x syntax + linuxPackageMappings <<= linuxPackageMappings map { mappings => + /* stuff. see above */ + mappings + } + +The ordering in which you apply the tasks is important. + +Add Mappings +~~~~~~~~~~~~ + +To add an arbitrary file in your build path + +.. code-block:: scala + + linuxPackageMappings += { + val file = sourceDirectory.value / "resources" / "somefile.txt" + packageMapping( (file, "/absolute/path/somefile.txt") ) + } + +``linuxPackageMappings`` can be scoped to ``Rpm` or ``Debian`` if you want to add mappings only for a single packacking type. + +.. code-block:: scala + + linuxPackageMappings in Debian += { + val file = sourceDirectory.value / "resources" / "debian-somefile.txt" + packageMapping( (file, "/absolute/path/somefile.txt") ) + } + + linuxPackageMappings in Rpm += { + val file = sourceDirectory.value / "resources" / "rpm-somefile.txt" + packageMapping( (file, "/absolute/path/somefile.txt") ) + } + + +Filter/Remove Mappings +~~~~~~~~~~~~~~~~~~~~~~ + +If you want to remove some mappings you have to filter the current list of ``linuxPackageMappings``. +As ``linuxPackageMappings`` is a task, the order of your settings is important. Here are some examples +on how to filter mappings. + +.. code-block:: scala + + // this is equal to + // linuxPackageMappings <<= linuxPackageMappings map { mappings => /* stuff */ mappings } + linuxPackageMappings := { + // first get the current mappings. mapping is of type Seq[LinuxPackageMapping] + val mappings = linuxPackageMappings.value + // map over the mappings if you want to change them + mappings map { mapping => + // we remove everything besides files that end with ".conf" + val filtered = mapping.mappings filter { + case (file, name) => name endsWith ".conf" + } + // now we copy the mapping but replace the mappings + mapping.copy(mappings = filtered) + } filter { + // remove all LinuxPackageMapping instances that have to file mappings + _.mappings.nonEmpty + } + } + +Alter LinuxPackageMapping +~~~~~~~~~~~~~~~~~~~~~~~~~ + +First we alter the permissions for all ``LinuxPackageMapping``s that match a specific criteria. + +.. code-block:: scala + + // Altering permissions for configs + linuxPackageMappings := { + val mappings = linuxPackageMappings.value + // Changing the group for all configs + mappings map { + case linuxPackage if linuxPackage.fileData.config equals "true" => + // altering the group + val newFileData = linuxPackage.fileData.copy( + group = "appdocs" + ) + // altering the LinuxPackageMapping + linuxPackage.copy( + fileData = newFileData + ) + case linuxPackage => linuxPackage + } + } + +Alter LinuxSymlinks +~~~~~~~~~~~~~~~~~~~ + +First we alter the permissions for all ``LinuxPackageMapping``s that match a specific criteria. + +.. code-block:: scala + + // The same as linuxPackageMappings + linuxPackageSymlinks := { + val links = linuxPackageSymlinks.value + + links filter { /* remove stuff */ } map { /* change stuff */} + } + .. toctree:: :maxdepth: 2 diff --git a/src/sphinx/DetailedTopics/universal.rst b/src/sphinx/DetailedTopics/universal.rst index 011d9e39c..07c177227 100644 --- a/src/sphinx/DetailedTopics/universal.rst +++ b/src/sphinx/DetailedTopics/universal.rst @@ -228,6 +228,61 @@ Mapping the content of a directory The ``dir`` gets excluded and is used as root for ``relativeTo(dir)``. +Filter/Remove mappings +^^^^^^^^^^^^^^^^^^^^^^ + +If you want to remove mappings, you have to filter the current list of mappings. +This example demonstrates how to build a fat jar with sbt-assembly, but using all +the convenience of the sbt native packager archetypes. + +tl;dr how to remove stuff + +.. code-block:: scala + + // removes all jar mappings in universal and appends the fat jar + mappings in Universal := { + // universalMappings: Seq[(File,String)] + val universalMappings = (mappings in Universal).value + val fatJar = (assembly in Compile).value + // removing means filtering + val filtered = universalMappings filter { + case (file, name) => ! name.endsWith(".jar") + } + // add the fat jar + filtered :+ (fatJar -> ("lib/" + fatJar.getName)) + } + + // sbt 0.12 syntax + mappings in Universal <<= (mappings in Universal, assembly in Compile) map { (universalMappings, fatJar) => /* same logic */} + + +The complete ``build.sbt`` should contain these settings if you want a single assembled fat jar. + +.. code-block:: scala + + // the assembly settings + assemblySettings + + // we specify the name for our fat jar + jarName in assembly := "assembly-project.jar" + + // using the java server for this application. java_application would be fine, too + packageArchetype.java_server + + // removes all jar mappings in universal and appends the fat jar + mappings in Universal := { + val universalMappings = (mappings in Universal).value + val fatJar = (assembly in Compile).value + val filtered = universalMappings filter { + case (file, name) => ! name.endsWith(".jar") + } + filtered :+ (fatJar -> ("lib/" + fatJar.getName)) + } + + // the bash scripts classpath only needs the fat jar + scriptClasspath := Seq( (jarName in assembly).value ) + + Commands -------- diff --git a/src/sphinx/GettingStartedServers/MyFirstProject.rst b/src/sphinx/GettingStartedServers/MyFirstProject.rst index 8cb5f5bca..0b0d10a12 100644 --- a/src/sphinx/GettingStartedServers/MyFirstProject.rst +++ b/src/sphinx/GettingStartedServers/MyFirstProject.rst @@ -67,6 +67,9 @@ this `native packager discussion`_. .. _debian policies: https://www.debian.org/doc/debian-policy/ch-files.html .. _native packager discussion: https://github.com/sbt/sbt-native-packager/pull/174 +If you want to change something in this predefined structure read more about it in +the :doc:`linux section `. + Debian (.deb) =============