Skip to content

Commit

Permalink
Add minimal RCP, add BundleMacosJdk test, fix readme
Browse files Browse the repository at this point in the history
  • Loading branch information
vlsi committed Jul 17, 2020
1 parent bc8b549 commit ed66303
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 66 deletions.
48 changes: 34 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,20 @@ Groovy:

```gradle
task buildDmg(type: de.itemis.mps.gradle.CreateDmg) {
rcpArtifact file('path/to/RCP.tgz')
rcpArtifact = file('path/to/RCP.tgz')
jdkDependency "com.jetbrains.jdk:jdk:${jdkVersion}:osx_x64@tgz"
// -or -
jdk file('path/to/jdk.tgz')
jdk = file('path/to/jdk.zip')
backgroundImage file('path/to/background.png')
dmgFile file('output.dmg')
backgroundImage = file('path/to/background.png')
dmgFile = file('output.dmg')
signKeyChain file("/path/to/my.keychain-db")
signKeyChain = file("/path/to/my.keychain-db")
signKeyChainPassword "my.keychain-db-password"
signKeyChainPassword = "my.keychain-db-password"
signIdentity "my Application ID Name"
signIdentity = "my Application ID Name"
}
```

Expand All @@ -114,7 +114,7 @@ val buildDmg by tasks.registering(CreateDmg::class) {
// -or-
jdk.set(layout.file(provider { jdkConfiguration.singleFile }))
// -or-
jdk.set(file("path/to/jdk.tgz"))
jdk.set(file("path/to/jdk.zip"))

backgroundImage.set(file("path/to/background.png"))
dmgFile.set(file("output.dmg"))
Expand All @@ -130,7 +130,7 @@ Parameters:
* `rcpArtifact` - the path to the RCP artifact produced by a build script.
* `jdkDependency` - the coordinates of a JDK in case it's available in
a repository and can be resolved as a Gradle dependency.
* `jdk` - the path to a JDK .tgz file.
* `jdk` - the path to a JDK .zip file.
* `backgroundImage` - the path to the background image.
* `dmgFile` - the path and file name of the output DMG image. Must end
with `.dmg`.
Expand All @@ -155,23 +155,43 @@ task.

### Usage

```
Groovy:

```gradle
task bundleMacosJdk(type: de.itemis.mps.gradle.BundleMacosJdk) {
rcpArtifact file('path/to/RCP.tgz')
rcpArtifact = file('path/to/RCP.tgz')
jdkDependency "com.jetbrains.jdk:jdk:${jdkVersion}:osx_x64@tgz"
// -or -
jdk file('path/to/jdk.tgz')
jdk = file('path/to/jdk.tgz')
outputFile = file('output.tar.gz')
}
```

Kotlin:

```kotlin
import de.itemis.mps.gradle.BundleMacosJdk

val buildDmg by tasks.registering(BundleMacosJdk::class) {
rcpArtifact.set(file("path/to/RCP.tgz"))

jdkDependency("com.jetbrains.jdk:jdk:${jdkVersion}:osx_x64@tgz")
// -or-
jdk.set(layout.file(provider { jdkConfiguration.singleFile }))
// -or-
jdk.set(file("path/to/jdk.tgz"))

outputFile file('output.tar.gz')
outputFile.set(file("output.dmg"))
}
```

Parameters:
* `rcpArtifact` - the path to the RCP artifact produced by a build script.
* `jdkDependency` - the coordinates of a JDK in case it's available in
a repository and can be resolved as a Gradle dependency.
* `jdk` - the path to a JDK .tgz file.
* `jdk` - the path to a JDK .zip file.
* `outputFile` - the path and file name of the output gzipped tar archive.

### Operation
Expand Down
7 changes: 3 additions & 4 deletions src/main/kotlin/de/itemis/mps/gradle/BaseBundleMacOsTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import java.io.File

abstract class BaseBundleMacOsTask(
objects: ObjectFactory,
protected val providers: ProviderFactory,
protected val layout: ProjectLayout
private val providers: ProviderFactory,
private val layout: ProjectLayout
) : DefaultTask() {
@InputFile
val rcpArtifact = objects.fileProperty()
Expand All @@ -36,8 +36,7 @@ abstract class BaseBundleMacOsTask(
// Do not use File.deleteDir() because it follows symlinks!
// (e.g. the symlink to /Applications inside tmpDir)
project.exec {
commandLine("rm", "-rf")
commandLine(*directory)
commandLine("rm", "-rf", *directory)
}
}
}
7 changes: 6 additions & 1 deletion src/main/kotlin/de/itemis/mps/gradle/BundleMacosJdk.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ open class BundleMacosJdk @Inject constructor(
try {
val scriptName = "bundle_macos_jdk.sh"
BundledScripts.extractScriptsToDir(scriptsDir, scriptName)
scriptsDir.listFiles()?.let {
for (file in it) {
println(file.absolutePath)
}
}
project.exec {
executable(File(scriptsDir, scriptName))
executable = "./$scriptName"
workingDir = scriptsDir
args(rcpArtifact.get().asFile, tmpDir, jdk.get().asFile, outputFile.get().asFile)
}
Expand Down
18 changes: 9 additions & 9 deletions src/main/kotlin/de/itemis/mps/gradle/CreateDmg.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.property
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FilterOutputStream
import javax.inject.Inject

open class CreateDmg @Inject constructor(
Expand Down Expand Up @@ -54,25 +56,23 @@ open class CreateDmg @Inject constructor(
val dmgDir = dmgDir.get().asFile
try {
rmdirs(dmgDir)
project.mkdir(dmgDir)
project.mkdir(scriptsDir)
dmgDir.mkdirs()
BundledScripts.extractScriptsToDir(scriptsDir, *scripts)
project.exec {
executable(File(scriptsDir, "mpssign.sh"))
executable = "./mpssign.sh"
workingDir = scriptsDir

args("-r", rcpArtifact, "-o", dmgDir, "-j", jdk)
args("-r", rcpArtifact.get().asFile, "-o", dmgDir, "-j", jdk.get().asFile)

if (signingInfo.all { it.isPresent }) {
args("-p", signKeyChainPassword)
args("-p", signKeyChainPassword.get())
args("-k", signKeyChain.get().asFile)
args("-i", signIdentity)
args("-i", signIdentity.get())
} else if (signingInfo.any { it.isPresent }) {
throw IllegalArgumentException("Not all signing paramters set. signKeyChain: ${signKeyChain.orNull}, signIdentity: ${signIdentity.orNull} and signKeyChainPassword needs to be set. ")
throw IllegalArgumentException("Not all signing parameters are set. signKeyChain: ${signKeyChain.orNull}, signIdentity: ${signIdentity.orNull} and signKeyChainPassword needs to be set. ")
}
}
project.exec {
executable(File(scriptsDir, "mpsdmg.sh"))
executable = "./mpsdmg.sh"
workingDir = scriptsDir
args(dmgDir, dmgFile, backgroundImage.get().asFile)
}
Expand Down
156 changes: 118 additions & 38 deletions src/test/kotlin/de/itemis/mps/gradle/test/CreateDmgTest.kt
Original file line number Diff line number Diff line change
@@ -1,81 +1,161 @@
package de.itemis.mps.gradle.test

import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Assert.assertEquals
import org.junit.Assume
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import kotlin.jvm.JvmField
import java.io.File
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

const val JBR_REPOSITORY = """
repositories {
ivy {
url = uri("https://dl.bintray.com/jetbrains/intellij-jdk/")
content {
includeGroupByRegex("com.jetbrains.jdk")
}
patternLayout {
artifact("[module]-[revision]-[classifier].[ext]")
}
metadataSources { // skip downloading ivy.xml
artifact()
}
}
}
"""

class CreateDmgTest {
@Rule @JvmField
@Rule
@JvmField
val testProjectDir: TemporaryFolder = TemporaryFolder()
private lateinit var settingsFile: File
private lateinit var buildFile: File
private lateinit var backgroundImage: File
private lateinit var rcpArchive: File
private lateinit var gradleRunner: GradleRunner
val jbrDependency = "com.jetbrains.jdk:jbr:11_0_4:[email protected]"

@Before
fun setup() {
Assume.assumeTrue(
assumeTrue(
"This test uses macOS-specific commands, so it requires macOS for execution",
System.getProperty("os.name").toLowerCase().contains("mac")
)
settingsFile = testProjectDir.newFile("settings.gradle.kts")
buildFile = testProjectDir.newFile("build.gradle.kts")
gradleRunner = GradleRunner.create()
.withProjectDir(testProjectDir.root)
.withPluginClasspath()
.forwardOutput()
settingsFile = testProjectDir.newFile("settings.gradle.kts").apply {
val cp = gradleRunner.pluginClasspath.joinToString { "\"${it.absolutePath}\"" }
writeText("""
rootProject.name = "create-dmg-test"
buildscript {
dependencies {
classpath(files($cp))
}
}
""".trimIndent())
}
buildFile = testProjectDir.newFile("build.gradle.kts")
val resources = testProjectDir.newFolder("resources")
backgroundImage = File(resources, "background.png").apply {
writeText("not a png file, however background is required")
}
// Generate a minimal RCP
val appName = "hello world"
rcpArchive = File(resources, "$appName.zip").apply {
outputStream().use { os ->
ZipOutputStream(os).use { zos ->
zos.putNextEntry(ZipEntry("$appName.app/Contents/Info.plist"))
CreateDmgTest::class.java.getResourceAsStream("Info.plist.xml").use {
it.copyTo(zos)
}
zos.putNextEntry(ZipEntry("$appName.app/Contents/Resources/"))
// This is a "mps launcher" binary, and mpssign.sh sets executable bit,
// so we create a dummy file here
zos.putNextEntry(ZipEntry("$appName.app/Contents/MacOS/mps"))
// required for chmod
zos.putNextEntry(ZipEntry("$appName.app/Contents/bin/printenv.py"))
// required for chmod
zos.putNextEntry(ZipEntry("$appName.app/Contents/bin/fsnotifier"))
// required for chmod
zos.putNextEntry(ZipEntry("$appName.app/Contents/bin/restarter"))
}
}
}
}

@Test
fun `test generate dmg`() {
val cp = gradleRunner.pluginClasspath.joinToString { "\"${it.absolutePath}\"" }
settingsFile.writeText("""
rootProject.name = "create-dmg-test"
buildscript {
dependencies {
classpath(files($cp))
}
fun `CreateDmg, non signed dmg, kotlin dsl`() {
buildFile.writeText("""
import de.itemis.mps.gradle.CreateDmg
$JBR_REPOSITORY
val createDmg by tasks.registering(CreateDmg::class) {
rcpArtifact.set(file("resources/${rcpArchive.name}"))
jdkDependency("$jbrDependency")
backgroundImage.set(file("resources/${backgroundImage.name}"))
dmgFile.set(layout.buildDirectory.file("distributions/output.dmg"))
}
""".trimIndent())

val result = gradleRunner
.withArguments("-i", "-s", "createDmg", "--warning-mode", "all")
.build()

assertEquals("createDmg task outcome", TaskOutcome.SUCCESS, result.task(":createDmg")?.outcome)
}

@Test
fun `CreateDmg, non signed dmg, groovy dsl`() {
buildFile.writeText("""
import de.itemis.mps.gradle.CreateDmg
repositories {
ivy {
url = uri("https://dl.bintray.com/jetbrains/intellij-jdk/")
content {
includeGroupByRegex("com.jetbrains.jdk")
}
patternLayout {
artifact("[module]-[revision]-[classifier].[ext]")
}
metadataSources { // skip downloading ivy.xml
artifact()
}
}
}
val createDmg by tasks.registering(CreateDmg::class) {
rcpArtifact.set(file("path/to/RCP.tgz"))
jdkDependency("com.jetbrains.jdk:jbr:11_0_4:[email protected]")
backgroundImage.set(file("path/to/background.png"))
dmgFile.set(layout.buildDirectory.file("distributions/output.dmg"))
$JBR_REPOSITORY
tasks.register('createDmg', CreateDmg.class) {
rcpArtifact = file("resources/${rcpArchive.name}")
jdkDependency "$jbrDependency"
backgroundImage = file("resources/${backgroundImage.name}")
dmgFile = layout.buildDirectory.file("distributions/output.dmg")
}
""".trimIndent())

// Rename file, so Groovy DSL is used
buildFile.renameTo(File(buildFile.parent, "build.gradle"))

val result = gradleRunner
.forwardOutput()
.withArguments("createDmg")
.withArguments("-i", "-s", "createDmg", "--warning-mode", "all")
.build()

assertEquals("createDmg task outcome", TaskOutcome.SUCCESS, result.task(":createDmg")?.outcome)
}

@Test
fun bundleMacosJdk() {
buildFile.writeText("""
import de.itemis.mps.gradle.BundleMacosJdk
$JBR_REPOSITORY
val bundleJdk by tasks.registering(BundleMacosJdk::class) {
rcpArtifact.set(file("resources/${rcpArchive.name}"))
jdkDependency("$jbrDependency")
outputFile.set(layout.buildDirectory.file("distributions/output.tgz"))
}
""".trimIndent())

val result = gradleRunner
.withArguments("-i", "-s", "bundleJdk", "--warning-mode", "all")
.build()

assertEquals("bundleJdk task outcome", TaskOutcome.SUCCESS, result.task(":bundleJdk")?.outcome)
}
}

Loading

0 comments on commit ed66303

Please sign in to comment.