From 94db98b01c6d2838f023063868c97993dd248907 Mon Sep 17 00:00:00 2001 From: Manfred Endres <2523575+Larusso@users.noreply.github.com> Date: Wed, 26 Apr 2023 09:27:29 +0200 Subject: [PATCH] Fix space in upm package replacement [ATLAS-1206] (#177) ## Description The regex to execute value substition for the `package.json` file assumes spaces around the properties. I removed the whole line patching logic with a two step copy setup. The task first copies the package.json to a temp directory in the build dir and adjustst the content according to the set properties. The main package copy spec will draw the content from two locations 1. the main package dir 2. the temp directory where only the adjusted package.json is located During copy only the package.json file form the temp dir will be taken into account. The solution at hand is sadly not the best to continue going forward. But I wanted a simple fix now and deal with a proper solution (parsing the whole json instead of doing line matching). The changes are quite big because I wanted to implement another set of parameters on top which I removed again. But I already refactored the test setup to make the setup less verbose (still quite verbose). I also bound the version from the `package.json` file as the default value for the archive version. ## Changes * ![FIX] space recognision in upm package replacement regex * ![IMPROVE] test setup for upm pack spec * ![IMPROVE] default version for upm pack from `package.json` [NEW]: https://resources.atlas.wooga.com/icons/icon_new.svg "New" [ADD]: https://resources.atlas.wooga.com/icons/icon_add.svg "Add" [IMPROVE]: https://resources.atlas.wooga.com/icons/icon_improve.svg "Improve" [CHANGE]: https://resources.atlas.wooga.com/icons/icon_change.svg "Change" [FIX]: https://resources.atlas.wooga.com/icons/icon_fix.svg "Fix" [UPDATE]: https://resources.atlas.wooga.com/icons/icon_update.svg "Update" [BREAK]: https://resources.atlas.wooga.com/icons/icon_break.svg "Remove" [REMOVE]: https://resources.atlas.wooga.com/icons/icon_remove.svg "Remove" [IOS]: https://resources.atlas.wooga.com/icons/icon_iOS.svg "iOS" [ANDROID]: https://resources.atlas.wooga.com/icons/icon_android.svg "Android" [WEBGL]: https://resources.atlas.wooga.com/icons/icon_webGL.svg "WebGL" [GRADLE]: https://resources.atlas.wooga.com/icons/icon_gradle.svg "GRADLE" [UNITY]: https://resources.atlas.wooga.com/icons/icon_unity.svg "Unity" [LINUX]: https://resources.atlas.wooga.com/icons/icon_linux.svg "Linux" [WIN]: https://resources.atlas.wooga.com/icons/icon_windows.svg "Windows" [MACOS]: https://resources.atlas.wooga.com/icons/icon_iOS.svg "macOS" --- ...nerateUpmPackageTaskIntegrationSpec.groovy | 237 +++++++++++++----- .../SetupProjectLayoutTestTask.groovy | 66 +++-- .../unity/tasks/GenerateUpmPackage.groovy | 61 ++++- .../unity/traits/UnityPackageSpec.groovy | 6 + .../unity/utils/PackageManifestBuilder.groovy | 19 +- 5 files changed, 299 insertions(+), 90 deletions(-) diff --git a/src/integrationTest/groovy/wooga/gradle/unity/tasks/GenerateUpmPackageTaskIntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/unity/tasks/GenerateUpmPackageTaskIntegrationSpec.groovy index d5c268b..510ccde 100644 --- a/src/integrationTest/groovy/wooga/gradle/unity/tasks/GenerateUpmPackageTaskIntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/unity/tasks/GenerateUpmPackageTaskIntegrationSpec.groovy @@ -1,12 +1,14 @@ package wooga.gradle.unity.tasks -import com.wooga.gradle.io.FileUtils + +import com.wooga.gradle.test.writers.PropertyGetterTaskWriter +import com.wooga.gradle.test.writers.PropertySetterWriter import com.wooga.spock.extensions.unity.UnityPathResolution import com.wooga.spock.extensions.unity.UnityPluginTestOptions import com.wooga.spock.extensions.uvm.UnityInstallation +import groovy.json.JsonSlurper import net.wooga.uvm.Installation import org.gradle.api.file.Directory -import org.gradle.api.tasks.Copy import spock.lang.Requires import spock.lang.Unroll import wooga.gradle.unity.UnityIntegrationSpec @@ -16,80 +18,163 @@ import wooga.gradle.utils.DirectoryComparer class GenerateUpmPackageTaskIntegrationSpec extends UnityIntegrationSpec { + @Override + String getSubjectUnderTestName() { + "generateUpmPackage" + } + + String subjectUnderTestTypeName = GenerateUpmPackage.class.name + + @Unroll + def "can set property #propertyName with #type"() { + expect: + runPropertyQuery(getter, setter).matches(value) + + where: + propertyName | type | value + "packageDirectory" | "File" | osPath("/path/to/package/dir") + "packageDirectory" | "Provider" | osPath("/path/to/package/dir") + "packageName" | "String" | "testPackageA" + "packageName" | "Provider" | "testPackageB" + + setter = new PropertySetterWriter(subjectUnderTestName, propertyName) + .set(value, type) + getter = new PropertyGetterTaskWriter(setter) + } + @Requires({ os.macOs }) @UnityPluginTestOptions(unityPath = UnityPathResolution.Default) - @UnityInstallation(version = "2019.4.38f1", cleanup = false) - def "generates unity package"(Installation unity) { + @UnityInstallation(version = "2022.1.15f1", cleanup = false) + def "generates unity package"( + String packageDisplayName, + String unityProjectPath, + String distributionsDirName, + String packageDirectory, + String packageName, + String packageVersion, + String expectedPackageFileName, + Installation unity + ) { given: "a pre installed unity editor" environmentVariables.set("UNITY_PATH", unity.getExecutable().getPath()) and: "future directory expectations" - def distributionsDirName = "build/distributions" def distributionsDir = new File(projectDir, distributionsDirName) assert !distributionsDir.exists() + and: "future package file" + def packageFile = new File(distributionsDir, expectedPackageFileName) + assert !packageFile.exists() + and: "configuration of the extension" - def unityProjectPath = SetupProjectLayoutTestTask.unityProjectDirectoryName - def packageDirRel = unityProjectPath + "/Assets/Wooga/Foobar" - def expectedProjectDir = new File(projectDir, unityProjectPath) - buildFile << """ - unity { - projectDirectory.set(${wrapValueBasedOnType(unityProjectPath, Directory)}) - } + buildFile << """\ + unity { + projectDirectory.set(${wrapValueBasedOnType(unityProjectPath, Directory)}) + } """.stripIndent() - and: "a set of values for the package" - def packageName = "com.wooga.foobar" - def packageVersion = "0.0.1" - def expectedPackageFileName = "${packageName}-${packageVersion}.tgz" - - and: "a task to create the project" - def createProjectTaskName = "createProject" - def createProjectTask = addTask("createProject", CreateProject.class.name, false, "") - - and: "a task to add additional files to the project 2" - def addFilesTaskName = "addPackageFiles" - def addFilesTask = addTask(addFilesTaskName, SetupProjectLayoutTestTask.class.name, false, """ - dependsOn ${createProjectTask} - """.stripIndent()) - - and: "a task to generate meta files" - def generateMetaFilesTaskName = "metatron" - def generateMetaFilesTask = addTask(generateMetaFilesTaskName, Unity.class.name, false, """ - dependsOn ${addFilesTask} - """.stripIndent()) + def setupProjectTask = setupUpmTestProject(unityProjectPath, packageDisplayName, packageName) - and: "a task to generate the upm package" - def generateUpmPackageTaskName = "upmPack" - addTask(generateUpmPackageTaskName, GenerateUpmPackage.class.name, false, """ - packageDirectory.set(${wrapValueBasedOnType(packageDirRel, Directory)}) - packageName = ${wrapValueBasedOnType(packageName, String)} - archiveVersion.set(${wrapValueBasedOnType(packageVersion, String)}) - dependsOn ${generateMetaFilesTask} + and: "configure task to generate the upm package" + appendToSubjectTask("""\ + packageDirectory.set(${wrapValueBasedOnType(packageDirectory, Directory)}) + packageName = ${wrapValueBasedOnType(packageName, String)} + archiveVersion.set(${wrapValueBasedOnType(packageVersion, String)}) + dependsOn ${setupProjectTask} """.stripIndent()) - and: "a task to extract the upm package so we can compare, okay?" - def extractUpmPackageName = "upmUnpack" - def packageFileRelPath = "${distributionsDirName}/${expectedPackageFileName}" - addTask(extractUpmPackageName, Copy.class.name, false, """ - from tarTree(\"${packageFileRelPath}\") - into layout.buildDirectory.dir(${wrapValueBasedOnType("unpack", String)}) - """.stripIndent()) - when: - def result = runTasksSuccessfully(createProjectTaskName, generateUpmPackageTaskName, addFilesTaskName, extractUpmPackageName) + def result = runTasksSuccessfully(subjectUnderTestName) then: result.success distributionsDir.exists() + packageFile.exists() + + def packageManifestUnpackDir = unpackPackage(packageFile) + def unpackedPackageDir = new File(packageManifestUnpackDir, "package") + unpackedPackageDir.exists() + + // Check the contents of the package manifest + def packageManifestFile = new File(unpackedPackageDir, GenerateUpmPackage.packageManifestFileName) + packageManifestFile.exists() + + def json = new JsonSlurper().parse(packageManifestFile) + json["name"] == packageName + json["version"] == packageVersion + + // Compare the contents of both unpacked and package source directories + // NOTE: We don't compare the manifests since we are patching it during the packaging + def packageSourceDir = new File(projectDir, packageDirectory) + def comparer = new DirectoryComparer(packageSourceDir, unpackedPackageDir) + comparer.ignoreFile(GenerateUpmPackage.packageManifestFileName) + comparer.ignoreTimestamps() + def comparison = comparer.compare() + assert comparison.valid: comparison.toString() + + where: + packageDisplayName = "Foobar" + unityProjectPath = "Wooga.${packageDisplayName}" + distributionsDirName = "build/distributions" + packageDirectory = unityProjectPath + "/Assets/Wooga/Foobar" + packageName = "com.wooga.foobar" + packageVersion = "0.0.1" + expectedPackageFileName = "${packageName}-${packageVersion}.tgz" + + and: "the injected unity installation" + unity = null + } + + @Requires({ os.macOs }) + @UnityPluginTestOptions(unityPath = UnityPathResolution.Default) + @UnityInstallation(version = "2019.4.38f1", cleanup = false) + def "uses package name and version from package.json when not specified"( + String packageDisplayName, + String unityProjectPath, + String distributionsDirName, + String packageDirectory, + String packageName, + String packageVersion, + String expectedPackageFileName, + Installation unity + ) { - def packageManifestUnpackDir = new File(projectDir, "build/unpack") - packageManifestUnpackDir.exists() + given: "a pre installed unity editor" + environmentVariables.set("UNITY_PATH", unity.getExecutable().getPath()) + + and: "future directory expectations" + def distributionsDir = new File(projectDir, distributionsDirName) + assert !distributionsDir.exists() + and: "future package file" def packageFile = new File(distributionsDir, expectedPackageFileName) + assert !packageFile.exists() + + and: "configuration of the extension" + buildFile << """\ + unity { + projectDirectory.set(${wrapValueBasedOnType(unityProjectPath, Directory)}) + } + """.stripIndent() + + def setupProjectTask = setupUpmTestProject(unityProjectPath, packageDisplayName, packageName, packageVersion) + + and: "configure task to generate the upm package" + appendToSubjectTask("""\ + packageDirectory.set(${wrapValueBasedOnType(packageDirectory, Directory)}) + dependsOn ${setupProjectTask} + """.stripIndent()) + + when: + def result = runTasksSuccessfully(subjectUnderTestName) + + then: + result.success + distributionsDir.exists() packageFile.exists() + def packageManifestUnpackDir = unpackPackage(packageFile) def unpackedPackageDir = new File(packageManifestUnpackDir, "package") unpackedPackageDir.exists() @@ -97,18 +182,30 @@ class GenerateUpmPackageTaskIntegrationSpec extends UnityIntegrationSpec { def packageManifestFile = new File(unpackedPackageDir, GenerateUpmPackage.packageManifestFileName) packageManifestFile.exists() - def packageJson = packageManifestFile.text - packageJson.contains("\"name\" : \"${packageName}\"") - packageJson.contains("\"version\" : \"${packageVersion}\"") + def json = new JsonSlurper().parse(packageManifestFile) + json["name"] == packageName + json["version"] == packageVersion // Compare the contents of both unpacked and package source directories // NOTE: We don't compare the manifests since we are patching it during the packaging - def packageSourceDir = new File(expectedProjectDir, "Assets/Wooga/Foobar") + def packageSourceDir = new File(projectDir, packageDirectory) def comparer = new DirectoryComparer(packageSourceDir, unpackedPackageDir) comparer.ignoreFile(GenerateUpmPackage.packageManifestFileName) comparer.ignoreTimestamps() def comparison = comparer.compare() assert comparison.valid: comparison.toString() + + where: + packageDisplayName = "Foobar" + unityProjectPath = "Wooga.${packageDisplayName}" + distributionsDirName = "build/distributions" + packageDirectory = unityProjectPath + "/Assets/Wooga/Foobar" + packageName = "com.wooga.foobar-baz" + packageVersion = "1.1.1" + expectedPackageFileName = "${packageName}-${packageVersion}.tgz" + + and: "the injected unity installation" + unity = null } @Unroll @@ -119,7 +216,7 @@ class GenerateUpmPackageTaskIntegrationSpec extends UnityIntegrationSpec { directory(projectPath) buildFile << """ unity { - projectDirectory.set(${wrapValueBasedOnType(projectPath, Directory)}) + projectDirectory.set(${wrapValueBasedOnType(projectPath, Directory)}) } """.stripIndent() @@ -154,10 +251,38 @@ class GenerateUpmPackageTaskIntegrationSpec extends UnityIntegrationSpec { where: packageName | packageVersion | predicate "com.wooga.foobar" | "0.0.1" | GenerateUpmPackage.Message.packageDirectoryNotSet - "com.wooga.foobar" | "0.0.1" | GenerateUpmPackage.Message.versionNotSet "com.wooga.foobar" | "0.0.1" | GenerateUpmPackage.Message.packageNameNotSet reason = predicate.message } + private static File unpackPackage(File packageFile) { + def packageManifestUnpackDir = File.createTempDir(packageFile.name, "_unpack") + def ant = new AntBuilder() + ant.untar(src: packageFile.path, dest: packageManifestUnpackDir.path, compression: "gzip") + packageManifestUnpackDir + } + + private String setupUpmTestProject(String unityProjectPath, String packageDisplayName, String packageName, String packageVersion = "0.0.0") { + def createProjectTaskName = "createProject" + def createProjectTask = addTask(createProjectTaskName, CreateProject.class.name, false, "") + + def addFilesTaskName = "addPackageFiles" + def addFilesTask = addTask(addFilesTaskName, SetupProjectLayoutTestTask.class.name, false, """\ + unityProjectDirectoryName = ${wrapValueBasedOnType(unityProjectPath, "String")} + packageDisplayName = ${wrapValueBasedOnType(packageDisplayName, "String")} + packageName = ${wrapValueBasedOnType(packageName, "String")} + initialPackageVersion = ${wrapValueBasedOnType(packageVersion, "String")} + dependsOn ${createProjectTask} + """.stripIndent()) + def generateMetaFilesTaskName = "generateMetafiles" + def generateMetaFilesTask = addTask(generateMetaFilesTaskName, Unity.class.name, false, """\ + dependsOn ${addFilesTask} + """.stripIndent()) + + def setupProjectTask = addTask("setupUnityProject", "org.gradle.api.DefaultTask", false, """\ + dependsOn ${createProjectTask}, ${addFilesTask}, ${generateMetaFilesTask} + """) + setupProjectTask + } } diff --git a/src/integrationTest/groovy/wooga/gradle/unity/testutils/SetupProjectLayoutTestTask.groovy b/src/integrationTest/groovy/wooga/gradle/unity/testutils/SetupProjectLayoutTestTask.groovy index 1c3ba10..aa728d4 100644 --- a/src/integrationTest/groovy/wooga/gradle/unity/testutils/SetupProjectLayoutTestTask.groovy +++ b/src/integrationTest/groovy/wooga/gradle/unity/testutils/SetupProjectLayoutTestTask.groovy @@ -1,6 +1,8 @@ package wooga.gradle.unity.testutils import org.gradle.api.DefaultTask +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import wooga.gradle.unity.utils.PackageManifestBuilder @@ -9,43 +11,71 @@ import wooga.gradle.unity.utils.PackageManifestBuilder */ class SetupProjectLayoutTestTask extends DefaultTask { - public static String packageName = "Foobar" - public static String unityProjectDirectoryName = "Wooga.${packageName}" + private final Property unityProjectDirectoryName = project.objects.property(String) + + @Input + Property getUnityProjectDirectoryName() { + unityProjectDirectoryName + } + + private final Property packageName = project.objects.property(String) + + @Input + Property getPackageName() { + packageName + } + + private final Property packageDisplayName = project.objects.property(String) + + @Input + Property getPackageDisplayName() { + packageDisplayName + } + + private final Property initialPackageVersion = project.objects.property(String) + + @Input + Property getInitialPackageVersion() { + initialPackageVersion + } @TaskAction void exec() { - File unityProjectDir = new File(project.projectDir, unityProjectDirectoryName) + def packageDisplayName = packageDisplayName.get() + def packageName = this.packageName.get() + + File unityProjectDir = new File(project.projectDir, unityProjectDirectoryName.get()) File assetsDir = new File(unityProjectDir, "Assets") - def packageDir = new File(assetsDir.path, "Wooga/${packageName}") + def packageDir = new File(assetsDir.path, "Wooga/${packageDisplayName}") packageDir.mkdirs() def packageJson = new File(packageDir.path, "package.json") - packageJson.write(new PackageManifestBuilder("com.wooga.${packageName.toLowerCase()}", "0.0.0").build()) + packageJson.write(new PackageManifestBuilder(packageName, initialPackageVersion.get()).build()) def readme = new File(packageDir.path, "README.MD") - readme.write("Here lies package ${packageName}") + readme.write("Here lies package ${packageDisplayName}") def license = new File(packageDir.path, "LICENSE.MD") license.write("Be good to each other") def runtimeDirectory = new File(packageDir.path, "Runtime") runtimeDirectory.mkdir() - def runtimeSource = new File(runtimeDirectory.path, "${packageName}.cs") - runtimeSource.write(""" -using System; -public class ${packageName} { -} -""") + def runtimeSource = new File(runtimeDirectory.path, "${packageDisplayName}.cs") + runtimeSource.write("""\ + using System; + public class ${packageDisplayName} { + } + """.stripIndent()) def editorDirectory = new File(packageDir.path, "Editor") editorDirectory.mkdir() - def editorSource = new File(editorDirectory.path, "${packageName}Editor.cs") - editorSource.write(""" -using System; -public class ${packageName}Editor { -} -""") + def editorSource = new File(editorDirectory.path, "${packageDisplayName}Editor.cs") + editorSource.write("""\ + using System; + public class ${packageDisplayName}Editor { + } + """.stripIndent()) } } diff --git a/src/main/groovy/wooga/gradle/unity/tasks/GenerateUpmPackage.groovy b/src/main/groovy/wooga/gradle/unity/tasks/GenerateUpmPackage.groovy index 7c328ac..e858faa 100644 --- a/src/main/groovy/wooga/gradle/unity/tasks/GenerateUpmPackage.groovy +++ b/src/main/groovy/wooga/gradle/unity/tasks/GenerateUpmPackage.groovy @@ -1,6 +1,7 @@ package wooga.gradle.unity.tasks import com.wooga.gradle.BaseSpec +import groovy.json.JsonOutput import groovy.json.JsonSlurper import org.gradle.api.file.Directory import org.gradle.api.file.DirectoryProperty @@ -13,6 +14,8 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.Optional import org.gradle.api.tasks.SkipWhenEmpty import org.gradle.api.tasks.bundling.Compression import org.gradle.api.tasks.bundling.Tar @@ -66,27 +69,29 @@ class GenerateUpmPackage extends Tar implements BaseSpec { project.files() } + private final Provider packageManifestFile = packageDirectory.file(packageManifestFileName) + /** * @return The package manifest file, `package.json`, which defines the package dependencies and other metadata. */ - @InputFile + @Internal("part of packageFiles") Provider getPackageManifestFile() { packageManifestFile } - private final Provider packageManifestFile = packageDirectory.file(packageManifestFileName) + + private final Property packageName = objects.property(String) /** * @return The officially registered package name. This name must conform to the Unity Package Manager naming convention, * which uses reverse domain name notation. */ @Input + @Optional Provider getPackageName() { packageName } - private final Property packageName = objects.property(String) - void setPackageName(Provider value) { packageName.set(value) } @@ -97,17 +102,45 @@ class GenerateUpmPackage extends Tar implements BaseSpec { public static final packageManifestFileName = "package.json" + protected void adjustManifestFile() { + def manifest = new File(temporaryDir, packageManifestFileName) + if(manifest.exists()) { + def j = new JsonSlurper() + def manifestContent = j.parse(manifest) + + if(packageName.present) { + manifestContent['name'] = packageName.get() + } + + if(archiveVersion.present) { + manifestContent['version'] = archiveVersion.get() + } + + String json = JsonOutput.toJson(manifestContent) + manifest.text = JsonOutput.prettyPrint(json) + } + } + @Override protected void copy() { if (!packageDirectory.present) { logger.warn(Message.packageDirectoryNotSet.message) } + + project.copy { + from(packageDirectory) + include(packageManifestFileName) + into(temporaryDir) + } + + adjustManifestFile() + + from(temporaryDir) from(packageDirectory) super.copy() } GenerateUpmPackage() { - setCompression(Compression.GZIP) // Creates a root directory inside the package @@ -120,11 +153,25 @@ class GenerateUpmPackage extends Tar implements BaseSpec { } slurper.parse(it.asFile)["name"].toString() }) + + Provider packageVersionOnFile = packageManifestFile.map({ + def slurper = new JsonSlurper() + if (!it.asFile.exists()) { + return null + } + slurper.parse(it.asFile)["version"].toString() + }) + packageName.convention(packageNameOnFile) + archiveVersion.set(packageVersionOnFile) archiveBaseName.set(packageName) + preserveFileTimestamps = false + reproducibleFileOrder = true + filesMatching(packageManifestFileName) { - filter { it.replaceAll(/"name" : ".*?"/, "\"name\" : \"${packageName.get()}\"") } - filter { it.replaceAll(/"version" : ".*?"/, "\"version\" : \"${archiveVersion.get()}\"") } + if(it.getFile().absolutePath.startsWith(packageDirectory.get().asFile.absolutePath)) { + it.exclude() + } } onlyIf(new Spec() { diff --git a/src/main/groovy/wooga/gradle/unity/traits/UnityPackageSpec.groovy b/src/main/groovy/wooga/gradle/unity/traits/UnityPackageSpec.groovy index 238971b..ddabcc2 100644 --- a/src/main/groovy/wooga/gradle/unity/traits/UnityPackageSpec.groovy +++ b/src/main/groovy/wooga/gradle/unity/traits/UnityPackageSpec.groovy @@ -5,6 +5,7 @@ import org.gradle.api.file.RegularFile import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Provider import org.gradle.api.tasks.Internal +import wooga.gradle.unity.models.UnityProjectManifest trait UnityPackageSpec extends BaseSpec { @@ -44,4 +45,9 @@ trait UnityPackageSpec extends BaseSpec { projectLockFile.set(value) } + @Internal + Provider getProjectManifest() { + projectManifestFile.map({UnityProjectManifest.deserialize(it.asFile)}) + } + } diff --git a/src/main/groovy/wooga/gradle/unity/utils/PackageManifestBuilder.groovy b/src/main/groovy/wooga/gradle/unity/utils/PackageManifestBuilder.groovy index 696683c..2b7df88 100644 --- a/src/main/groovy/wooga/gradle/unity/utils/PackageManifestBuilder.groovy +++ b/src/main/groovy/wooga/gradle/unity/utils/PackageManifestBuilder.groovy @@ -1,8 +1,15 @@ package wooga.gradle.unity.utils +import groovy.json.JsonOutput + class PackageManifestBuilder { - String packageName = "" + String name = "" + + String getPackageName() { + name + } + String version = "" String displayName = "" String description = "" @@ -11,17 +18,11 @@ class PackageManifestBuilder { } PackageManifestBuilder(String packageName, String version) { - this.packageName = packageName + this.name = packageName this.version = version } String build() { - """{ - "name" : "${packageName}", - "version" : "${version}", - "displayName" : "${displayName}", - "description" : "${description}" -} -""" + JsonOutput.toJson(this) } }