From 695d69f197e08944f3c98cdc8f4f77c88fe6d9ef Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Thu, 27 Sep 2018 22:28:43 +0200 Subject: [PATCH] Strip sbt-native-packager universal zip's (fixes #41) (#43) --- build.sbt | 3 ++ src/main/scala/ReproducibleBuildsPlugin.scala | 27 +++++++++---- src/main/scala/SbtNativePackagerHelpers.scala | 37 ++++++++++++++++++ .../native-packager/build.sbt | 10 +++++ .../native-packager_2.12-0.1.0-SNAPSHOT.jar | Bin 0 -> 3011 bytes .../native-packager/project/build.properties | 1 + .../native-packager/project/plugins.sbt | 7 ++++ .../native-packager/src/main/scala/Main.scala | 5 +++ .../native-packager/test | 9 +++++ .../simple/project/plugins.sbt | 3 ++ 10 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 src/main/scala/SbtNativePackagerHelpers.scala create mode 100644 src/sbt-test/sbt-reproducible-builds/native-packager/build.sbt create mode 100644 src/sbt-test/sbt-reproducible-builds/native-packager/expected/native-packager_2.12-0.1.0-SNAPSHOT.jar create mode 100644 src/sbt-test/sbt-reproducible-builds/native-packager/project/build.properties create mode 100644 src/sbt-test/sbt-reproducible-builds/native-packager/project/plugins.sbt create mode 100644 src/sbt-test/sbt-reproducible-builds/native-packager/src/main/scala/Main.scala create mode 100644 src/sbt-test/sbt-reproducible-builds/native-packager/test diff --git a/build.sbt b/build.sbt index 27047b2..e9d55c8 100644 --- a/build.sbt +++ b/build.sbt @@ -19,6 +19,9 @@ libraryDependencies += "net.bzzt" % "reproducible-build" % "0.2" libraryDependencies += "com.jsuereth" % "sbt-pgp" % sbtPgpVersion libraryDependencies += "io.spray" %% "spray-json" % "1.3.4" +// Optional integration: +addSbtPlugin("com.typesafe.sbt" %% "sbt-native-packager" % "1.3.9" % Provided) + // Dogfood^WChampagne time! import net.bzzt.reproduciblebuilds.ReproducibleBuildsPlugin._ reproducibleBuildsUploadPrefix := uri("http://pi.bzzt.net:8081/") diff --git a/src/main/scala/ReproducibleBuildsPlugin.scala b/src/main/scala/ReproducibleBuildsPlugin.scala index d5e7ffa..d34a81a 100644 --- a/src/main/scala/ReproducibleBuildsPlugin.scala +++ b/src/main/scala/ReproducibleBuildsPlugin.scala @@ -17,12 +17,16 @@ import io.github.zlika.reproducible._ import sbt.io.syntax.{URI, uri} import sbt.librarymanagement.Http.http -import scala.util.Success +import scala.util.{Success, Try} import spray.json._ + import scala.concurrent.ExecutionContext.Implicits.global object ReproducibleBuildsPlugin extends AutoPlugin { // To make sure we're loaded after the defaults + val universalPluginOnClasspath = + Try(getClass.getClassLoader.loadClass("com.typesafe.sbt.packager.universal.UniversalPlugin")).isSuccess + override def requires: Plugins = JvmPlugin val reproducibleBuildsPackageName = taskKey[String]("Package name of this build, including version but excluding disambiguation string") @@ -124,16 +128,23 @@ object ReproducibleBuildsPlugin extends AutoPlugin { }) } } + ) ++ ( + if (universalPluginOnClasspath) SbtNativePackagerHelpers.settings + else Seq.empty ) - def postProcessJar(jar: File): File = { - val dir = jar.getParentFile.toPath.resolve("stripped") - dir.toFile.mkdir() - val out = dir.resolve(jar.getName).toFile - new ZipStripper() + def postProcessJar(jar: File): File = postProcessWith(jar, new ZipStripper() .addFileStripper("META-INF/MANIFEST.MF", new ManifestStripper()) - .addFileStripper("META-INF/maven/\\S*/pom.properties", new PomPropertiesStripper()) - .strip(jar, out) + .addFileStripper("META-INF/maven/\\S*/pom.properties", new PomPropertiesStripper())) + + def postProcessZip(zip: File): File = postProcessWith(zip, new ZipStripper()) + + // TODO make the signature `Stripper` + private def postProcessWith(file: File, stripper: ZipStripper): File = { + val dir = file.getParentFile.toPath.resolve("stripped") + dir.toFile.mkdir() + val out = dir.resolve(file.getName).toFile + stripper.strip(file, out) out } diff --git a/src/main/scala/SbtNativePackagerHelpers.scala b/src/main/scala/SbtNativePackagerHelpers.scala new file mode 100644 index 0000000..899fb0c --- /dev/null +++ b/src/main/scala/SbtNativePackagerHelpers.scala @@ -0,0 +1,37 @@ +package net.bzzt.reproduciblebuilds + +import com.typesafe.sbt.packager.universal.UniversalPlugin +import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport._ +import sbt._ +import sbt.Keys._ + +/** + * Helper code for sbt-native-packager integration. + * + * The main ReproducibleBuildsPlugin code should not rely on any + * sbt-native-packager code, since this plugin should be usable without + * sbt-native-packager and not introduce it to projects not already using it. + * + * Any code dependent on sbt-native-packager classes + * should go here, and only be called in case it is indeed available. + * + * To avoid 'leaking' references to sbt-native-packager classes into other + * classes, care should be taken that none appear in parameter or return + * value types either. + */ +object SbtNativePackagerHelpers { + val plugin: Plugins.Basic = UniversalPlugin + + val none: File = new File("none") + + val settings: Seq[Setting[_]] = Seq( + // Make sure there's always a value defined, even when the Universal plugin isn't loaded: + packageBin in Global := none, + packageBin in Universal := { + val upstream = (packageBin in Universal).value + // If the value is still `none`, the Universal plugin isn't loaded. + if (upstream == none) none + else ReproducibleBuildsPlugin.postProcessZip(upstream) + } + ) +} diff --git a/src/sbt-test/sbt-reproducible-builds/native-packager/build.sbt b/src/sbt-test/sbt-reproducible-builds/native-packager/build.sbt new file mode 100644 index 0000000..21adf00 --- /dev/null +++ b/src/sbt-test/sbt-reproducible-builds/native-packager/build.sbt @@ -0,0 +1,10 @@ +import net.bzzt.reproduciblebuilds.ReproducibleBuildsPlugin.disambiguation + +enablePlugins(ReproducibleBuildsPlugin) +enablePlugins(JavaAppPackaging) + +// Universal plugin settings: +maintainer := "arnout@bzzt.net" + +// Make the filename static for easier validation: +disambiguation in Compile := (_ => Some("STATIC")) diff --git a/src/sbt-test/sbt-reproducible-builds/native-packager/expected/native-packager_2.12-0.1.0-SNAPSHOT.jar b/src/sbt-test/sbt-reproducible-builds/native-packager/expected/native-packager_2.12-0.1.0-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..44733043166a502d4f5b88c0969c0a82b15d3741 GIT binary patch literal 3011 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 addSbtPlugin("net.bzzt" % "sbt-reproducible-builds" % sys.props("plugin.version")) + case _ => sys.error("""|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) +} + +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.9") diff --git a/src/sbt-test/sbt-reproducible-builds/native-packager/src/main/scala/Main.scala b/src/sbt-test/sbt-reproducible-builds/native-packager/src/main/scala/Main.scala new file mode 100644 index 0000000..f06dc23 --- /dev/null +++ b/src/sbt-test/sbt-reproducible-builds/native-packager/src/main/scala/Main.scala @@ -0,0 +1,5 @@ +package net.bzzt + +object Main extends App { + println("Hello, Reproducible World") +} diff --git a/src/sbt-test/sbt-reproducible-builds/native-packager/test b/src/sbt-test/sbt-reproducible-builds/native-packager/test new file mode 100644 index 0000000..2361014 --- /dev/null +++ b/src/sbt-test/sbt-reproducible-builds/native-packager/test @@ -0,0 +1,9 @@ +> package +$ exists target/scala-2.12/stripped/native-packager_2.12-0.1.0-SNAPSHOT.jar +$ must-mirror target/scala-2.12/stripped/native-packager_2.12-0.1.0-SNAPSHOT.jar expected/native-packager_2.12-0.1.0-SNAPSHOT.jar +> reproducibleBuildsCertification +$ exists target/scala-2.12/native-packager_2.12_0.1.0-SNAPSHOT_all_STATIC.buildinfo +# Not on travis: +#> signedReproducibleBuildsCertification +#> reproducibleBuildsUploadCertification +#> reproducibleBuildsCheckCertification diff --git a/src/sbt-test/sbt-reproducible-builds/simple/project/plugins.sbt b/src/sbt-test/sbt-reproducible-builds/simple/project/plugins.sbt index eef3d38..eb97215 100644 --- a/src/sbt-test/sbt-reproducible-builds/simple/project/plugins.sbt +++ b/src/sbt-test/sbt-reproducible-builds/simple/project/plugins.sbt @@ -3,3 +3,6 @@ sys.props.get("plugin.version") match { case _ => sys.error("""|The system property 'plugin.version' is not defined. |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) } + +// Included but not used, to catch problems with that combination: +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.9") \ No newline at end of file