-
Notifications
You must be signed in to change notification settings - Fork 445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First refactoring to provide multiple debian packaging strategies #284
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package com.typesafe.sbt | ||
package packager | ||
package debian | ||
|
||
import Keys._ | ||
import sbt._ | ||
import sbt.Keys.{ target, name, normalizedName, TaskStreams } | ||
import linux.{ LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink } | ||
import linux.Keys.{ linuxScriptReplacements, daemonShell } | ||
import com.typesafe.sbt.packager.linux.LinuxPackageMapping | ||
import scala.collection.JavaConversions._ | ||
|
||
import org.vafer.jdeb.{ DebMaker, DataProducer } | ||
import org.vafer.jdeb.mapping._ | ||
import org.vafer.jdeb.producers._ | ||
import DebianPlugin.Names | ||
|
||
/** | ||
* This provides a java based debian packaging implementation based | ||
* on the jdeb maven-plugin. To use this, put this into your build.sbt | ||
* | ||
* {{ | ||
* packageBin in Debian <<= debianJDebPackaging in Debian | ||
* }} | ||
* | ||
* @author Nepomuk Seiler | ||
* @see https://github.com/tcurdt/jdeb/blob/master/src/main/java/org/vafer/jdeb/maven/DebMojo.java#L503 | ||
* | ||
*/ | ||
trait JDebPackaging { this: DebianPlugin with linux.LinuxPlugin => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, we may be going over the top with cake :) I'm almost regretting having used it in the first place. Did this feel like it made things simpler, or just more complicated to find things? |
||
|
||
private[debian] def debianJDebSettings: Seq[Setting[_]] = Seq( | ||
|
||
/** | ||
* Depends on the 'debianExplodedPackage' task as this creates all the files | ||
* which are defined in the mappings. | ||
*/ | ||
debianJDebPackaging <<= (debianExplodedPackage, linuxPackageMappings, linuxPackageSymlinks, | ||
debianControlFile, debianMaintainerScripts, debianConffilesFile, | ||
normalizedName, version, target, streams) map { | ||
(_, mappings, symlinks, controlfile, controlscripts, conffile, | ||
name, version, target, s) => | ||
s.log.info("Building debian package with java based implementation 'jdeb'") | ||
val console = new JDebConsole(s.log) | ||
|
||
val debianFile = target.getParentFile / "%s_%s_all.deb".format(name, version) | ||
val debMaker = new DebMaker(console, | ||
fileAndDirectoryProducers(mappings, target) ++ linkProducers(symlinks), | ||
conffileProducers() | ||
) | ||
debMaker setDeb debianFile | ||
debMaker setControl (target / Names.Debian) | ||
|
||
// TODO set compression, gzip is default | ||
// TODO add signing with setKeyring, setKey, setPassphrase, setSignPackage, setSignMethod, setSignRole | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now, depending on the pgpPlugin may not be "safe to do", we should have a big auto-plugins discussion across the plugin authors to see what kinds of conventions/dependencies we'd liek to expose and how we do so. |
||
debMaker validate () | ||
debMaker makeDeb () | ||
debianFile | ||
}) | ||
|
||
/** | ||
* Creating file and directory producers. These "produce" the | ||
* files for the debian packaging | ||
*/ | ||
private[debian] def fileAndDirectoryProducers(mappings: Seq[LinuxPackageMapping], target: File): Seq[DataProducer] = mappings.map { | ||
case LinuxPackageMapping(paths, perms, zipped) => | ||
// TODO implement mappers here or use the maintainerscripts logic? | ||
val (dirs, files) = paths.partition(_._1.isDirectory) | ||
paths map { | ||
case (path, name) if path.isDirectory => | ||
new DataProducerDirectory(target / name, null, Array("**"), null) | ||
case (path, name) => | ||
new DataProducerFile(target / name, name, null, null, null) | ||
} | ||
}.flatten | ||
|
||
/** | ||
* Creating link producers for symlinks. | ||
*/ | ||
private[debian] def linkProducers(symlinks: Seq[LinuxSymlink]): Seq[DataProducer] = symlinks map { | ||
case LinuxSymlink(link, destination) => | ||
new DataProducerLink(link, destination, true, null, null, null) | ||
} | ||
|
||
/** | ||
* Creating the files which should be added as conffiles. | ||
* This is currently handled by the debian plugin itself. | ||
*/ | ||
private[debian] def conffileProducers(): Seq[DataProducer] = Seq.empty | ||
|
||
} | ||
|
||
/** | ||
* This provides the task for building a debian packaging with | ||
* the java-based implementation jdeb | ||
*/ | ||
class JDebConsole(log: Logger) extends org.vafer.jdeb.Console { | ||
|
||
def debug(message: String) = log debug message | ||
|
||
def info(message: String) = log info message | ||
|
||
def warn(message: String) = log warn message | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package com.typesafe.sbt | ||
package packager | ||
package debian | ||
|
||
import Keys._ | ||
import sbt._ | ||
import sbt.Keys.{ target, name, normalizedName, TaskStreams } | ||
import linux.{ LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink } | ||
import linux.Keys.{ linuxScriptReplacements, daemonShell } | ||
import com.typesafe.sbt.packager.Hashing | ||
import com.typesafe.sbt.packager.archetypes.TemplateWriter | ||
|
||
/** | ||
* This provides a dpgk based implementation for debian packaging. | ||
* Your machine must have dpkg installed to use this. | ||
* | ||
* {{ | ||
* packageBin in Debian <<= debianNativePackaging in Debian | ||
* }} | ||
* | ||
* | ||
* | ||
*/ | ||
trait NativePackaging { this: DebianPlugin with linux.LinuxPlugin => | ||
|
||
import com.typesafe.sbt.packager.universal.Archives | ||
import DebianPlugin.Names | ||
import linux.LinuxPlugin.Users | ||
|
||
private[debian] def debianNativeSettings: Seq[Setting[_]] = Seq( | ||
genChanges <<= (packageBin, target, debianChangelog, name, version, debianPackageMetadata) map { | ||
(pkg, tdir, changelog, name, version, data) => | ||
changelog match { | ||
case None => sys.error("Cannot generate .changes file without a changelog") | ||
case Some(chlog) => { | ||
// dpkg-genchanges needs a debian "source" directory, different from the DEBIAN "binary" directory | ||
val debSrc = tdir / "../tmp" / Names.DebianSource | ||
debSrc.mkdirs() | ||
copyAndFixPerms(chlog, debSrc / Names.Changelog, LinuxFileMetaData("0644")) | ||
IO.writeLines(debSrc / Names.Files, List(pkg.getName + " " + data.section + " " + data.priority)) | ||
// dpkg-genchanges needs a "source" control file, located in a "debian" directory | ||
IO.writeLines(debSrc / Names.Control, List(data.makeSourceControl())) | ||
val changesFileName = name + "_" + version + "_" + data.architecture + ".changes" | ||
val changesFile: File = tdir / ".." / changesFileName | ||
try { | ||
val changes = Process(Seq("dpkg-genchanges", "-b"), Some(tdir / "../tmp")) !! | ||
val allChanges = List(changes) | ||
IO.writeLines(changesFile, allChanges) | ||
} catch { | ||
case e: Exception => sys.error("Failure generating changes file." + e.getStackTraceString) | ||
} | ||
changesFile | ||
} | ||
} | ||
|
||
}, | ||
debianSign <<= (packageBin, debianSignRole, streams) map { (deb, role, s) => | ||
Process(Seq("dpkg-sig", "-s", role, deb.getAbsolutePath), Some(deb.getParentFile())) ! s.log match { | ||
case 0 => () | ||
case x => sys.error("Failed to sign debian package! exit code: " + x) | ||
} | ||
deb | ||
}, | ||
lintian <<= packageBin map { file => | ||
Process(Seq("lintian", "-c", "-v", file.getName), Some(file.getParentFile)).! | ||
}, | ||
|
||
/** Implementation of the actual packaging */ | ||
debianNativePackaging <<= (debianExplodedPackage, debianMD5sumsFile, debianSection, debianPriority, name, version, packageArchitecture, target, streams) map { | ||
(pkgdir, _, section, priority, name, version, arch, tdir, s) => | ||
s.log.info("Building debian package with native implementation") | ||
// Make the package. We put this in fakeroot, so we can build the package with root owning files. | ||
val archive = name + "_" + version + "_" + arch + ".deb" | ||
Process(Seq("fakeroot", "--", "dpkg-deb", "--build", pkgdir.getAbsolutePath, "../" + archive), Some(tdir)) ! s.log match { | ||
case 0 => () | ||
case x => sys.error("Failure packaging debian file. Exit code: " + x) | ||
} | ||
tdir / ".." / archive | ||
} | ||
) | ||
|
||
} | ||
|
||
/** | ||
* This provides the task for building a debian packaging with | ||
* native tools | ||
* | ||
*/ | ||
object Native { | ||
|
||
/* static assets definitions */ | ||
|
||
private[debian] def postinstGroupaddTemplateSource: java.net.URL = getClass.getResource("postinst-groupadd") | ||
private[debian] def postinstUseraddTemplateSource: java.net.URL = getClass.getResource("postinst-useradd") | ||
private[debian] def postinstChownTemplateSource: java.net.URL = getClass.getResource("postinst-chown") | ||
private[debian] def postrmPurgeTemplateSource: java.net.URL = getClass.getResource("postrm-purge") | ||
private[debian] def headerSource: java.net.URL = getClass.getResource("header") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import NativePackagerKeys._ | ||
|
||
packagerSettings | ||
|
||
mapGenericFilesToLinux | ||
|
||
name := "debian-test" | ||
|
||
version := "0.1.0" | ||
|
||
maintainer := "Josh Suereth <[email protected]>" | ||
|
||
packageSummary := "Test debian package" | ||
|
||
packageDescription := """A fun package description of our software, | ||
with multiple lines.""" | ||
|
||
debianPackageDependencies in Debian ++= Seq("java2-runtime", "bash (>= 2.05a-11)") | ||
|
||
debianPackageRecommends in Debian += "git" | ||
|
||
packageBin in Debian <<= debianJDebPackaging in Debian |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version")) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Run the debian packaging. | ||
> debian:package-bin | ||
$ exists target/debian-test_0.1.0_all.deb |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah nice, I had been watching this guy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using the jdeb library at our company without any problems. The
artifacts (Artifact("jdeb","jar","jar"))
part was the hardest to get :P