Having now set this up, I feel that I can and should publish an answer here.
First, a few assumptions:
1. We're publishing to Nexus. (Artifactory should be similar but shown here is what worked for Nexus.)
2. Nexus requires credentials to publish. This complicates issues, hence we override the publish task to directly supply credentials.
3. We're building a server application, hence JavaServerAppPackaging. Modify as appropriate.
4. As part of being a server application, we need a start script. In this case we're using system-v, hence ServerLoader.SystemV. Modify as appropriate since most newer Linuxes use Systemd.
5. That you'd like to use the sbt-release plugin to automate releasing.
6. Our app is modularized, hence we're using a multi-module sbt build.
build.sbt content:
import sbtcrossproject.CrossPlugin.autoImport.{CrossType, crossProject}
import NativePackagerHelper._
import ReleaseTransformations._
import scala.sys.process._
// Top-level settings
name := "project-name"
organization in ThisBuild := "com.example"
scalaVersion in ThisBuild := "2.12.8"
// Integrating with sbt-release plugin
releasePublishArtifactsAction := {(publish in Rpm).value}
lazy val publishRpmUrl = Def.setting {
val nexus = "http://nexus.example.com"
if (version.value.trim.endsWith("SNAPSHOT"))
("test-yum-repo", url(nexus + "/repository/test-yum-repo/"))
else
("prod-yum-repo", url(nexus + "/repository/prod-yum-repo/"))
}
// Keep the release plugin happy by having this key set, but disallow remote publishing since
// nothing in this project is sharable.
Global / publishTo := {Option(Resolver.mavenLocal)}
// Settings for root project
lazy val root = (project in file("."))
.settings(
name := "root",
// Top-level publishing settings
publishArtifact in Rpm := true,
publishLocal in Rpm := {},
// Standard publish doesn't appear to pass credentials
publish in Rpm := {
val creds = Credentials.toDirect(Credentials(Path.userHome / ".sbt" / "nexus.credentials"))
val (_, destUrl) = publishRpmUrl.value
Process(
"curl" :: "-v" ::
"-u" :: s"${creds.userName}:${creds.passwd}" ::
"--upload-file" :: (packageBin in Rpm).value.getAbsolutePath ::
destUrl.toString :: Nil
) ! streams.value.log
},
// Top-level settings
mainClass in Compile := Some("com.example.app.Main"),
// RPM settings
// package settings
maintainer := "Acme <[email protected]>",
packageName in Rpm := "rpm-name",
packageSummary in Rpm := "Some Summary",
packageDescription in Rpm := "Some Description",
// rpm specific
rpmVendor := "Acme",
rpmUrl := Some("http://example.com/"),
rpmLicense := Some("Copyright © 2019 Acme Inc. All Rights Reserved."),
rpmRequirements ++= Seq("java-1.8.0-openjdk", "bash"),
linuxPackageMappings in Rpm := configWithNoReplace((linuxPackageMappings in Rpm).value),
// Java Server Application Archetype
daemonUser in Rpm := "app-daemon",
daemonGroup in Rpm := "app-daemon",
// System loader settings
// WARN Newer systems will want to use a different loader!
serverLoading := Some(ServerLoader.SystemV),
serviceAutostart := true,
mappings in Universal ++= directory( (sourceDirectory in server).value / "main" / "resources" )
)
// Package as normal java server for RedHat RPM running SystemV
.enablePlugins(RpmPlugin,RpmDeployPlugin)
.enablePlugins(JavaServerAppPackaging)
.enablePlugins(SystemloaderPlugin, SystemVPlugin)
.aggregate(server,client)
.dependsOn(server,client)
lazy val server = ...
lazy val client = ...