From a82f6466f4aabb694ec160817345e45eedbacba8 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Wed, 30 May 2018 08:41:35 +0100 Subject: [PATCH 01/16] --wip-- [skip ci] --- .../org/openbakery/CommandRunner.groovy | 2 +- .../groovy/org/openbakery/XcodePlugin.groovy | 8 +- .../carthage/AbstractCarthageTaskBase.groovy | 13 +- .../carthage/CarthageBootStrapTask.groovy | 122 +++++++++++++++--- .../carthage/CarthageBootstrapRunnable.groovy | 70 ++++++++++ 5 files changed, 188 insertions(+), 27 deletions(-) create mode 100644 plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy diff --git a/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy b/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy index b52aeeff..86be35ff 100644 --- a/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy +++ b/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy @@ -23,7 +23,7 @@ import org.openbakery.output.OutputAppender import org.slf4j.Logger import org.slf4j.LoggerFactory -class CommandRunner { +class CommandRunner implements Serializable{ private static Logger logger = LoggerFactory.getLogger(CommandRunner.class) diff --git a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy index 60727419..40beeb79 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy @@ -692,7 +692,13 @@ class XcodePlugin implements Plugin { private void configureCarthage(Project project) { project.task(CARTHAGE_CLEAN_TASK_NAME, type: CarthageCleanTask, group: CARTHAGE_GROUP_NAME) project.task(CARTHAGE_UPDATE_TASK_NAME, type: CarthageUpdateTask, group: CARTHAGE_GROUP_NAME) - project.task(CARTHAGE_BOOTSTRAP_TASK_NAME, type: CarthageBootStrapTask, group: CARTHAGE_GROUP_NAME) +// project.task(CARTHAGE_BOOTSTRAP_TASK_NAME, type: CarthageBootStrapTask, group: CARTHAGE_GROUP_NAME) + + project.tasks.create(CARTHAGE_BOOTSTRAP_TASK_NAME, CarthageBootStrapTask.class) { + it.group = CARTHAGE_GROUP_NAME + it.commandRunnerProperty.set(commandRunner) + it.platform.set(xcodeBuildPluginExtension.type) + } } private configureCarthageDependencies(Project project) { diff --git a/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy b/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy index abbb6664..2e70c2be 100644 --- a/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy +++ b/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy @@ -1,10 +1,14 @@ package org.openbakery.carthage +import groovy.transform.CompileStatic import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.openbakery.AbstractXcodeTask +import org.openbakery.CommandRunnerException +import org.openbakery.XcodeBuildPluginExtension import org.openbakery.xcode.Type +@CompileStatic abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { static final String ACTION_BOOTSTRAP = "bootstrap" @@ -31,7 +35,6 @@ abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { @InputFile @Optional - @PathSensitive(PathSensitivity.RELATIVE) Provider getCartFile() { // Cf https://github.com/gradle/gradle/issues/2016 File file = project.rootProject.file(CARTHAGE_FILE) @@ -43,7 +46,6 @@ abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { @InputFile @Optional - @PathSensitive(PathSensitivity.RELATIVE) Provider getCartResolvedFile() { // Cf https://github.com/gradle/gradle/issues/2016 File file = project.rootProject.file(CARTHAGE_FILE_RESOLVED) @@ -55,7 +57,7 @@ abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { @Input String getCarthagePlatformName() { - switch (project.xcodebuild.type) { + switch (project.extensions.findByType(XcodeBuildPluginExtension).type.get()) { case Type.iOS: return CARTHAGE_PLATFORM_IOS case Type.tvOS: return CARTHAGE_PLATFORM_TVOS case Type.macOS: return CARTHAGE_PLATFORM_MACOS @@ -65,6 +67,7 @@ abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { } @OutputDirectory + @PathSensitive(PathSensitivity.NAME_ONLY) Provider getOutputDirectory() { return project.provider { project.rootProject.file("Carthage/Build/" + getCarthagePlatformName()) @@ -74,14 +77,14 @@ abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { String getCarthageCommand() { try { return commandRunner.runWithResult("which", "carthage") - } catch (CommandRunnerException) { + } catch (CommandRunnerException exception) { // ignore, because try again with full path below } try { commandRunner.runWithResult("ls", CARTHAGE_USR_BIN_PATH) return CARTHAGE_USR_BIN_PATH - } catch (CommandRunnerException) { + } catch (CommandRunnerException exception) { // ignore, because blow an exception is thrown } throw new IllegalStateException("The carthage command was not found. Make sure that Carthage is installed") diff --git a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy index 7c6e8c43..5938d5d4 100644 --- a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy @@ -1,35 +1,117 @@ package org.openbakery.carthage import groovy.transform.CompileStatic -import org.gradle.api.tasks.TaskAction -import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.openbakery.output.ConsoleOutputAppender +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.* +import org.gradle.workers.IsolationMode +import org.gradle.workers.WorkerConfiguration +import org.gradle.workers.WorkerExecutor +import org.openbakery.CommandRunner +import org.openbakery.xcode.Type +import javax.inject.Inject +import java.util.regex.Pattern + +@CacheableTask @CompileStatic -class CarthageBootStrapTask extends AbstractCarthageTaskBase { +class CarthageBootStrapTask extends DefaultTask { + + @InputFile + @PathSensitive(PathSensitivity.NAME_ONLY) + RegularFileProperty cartFile = project.layout.fileProperty() + + Property platform = project.objects.property(Type) + + @Input + Provider carthagePlatformName = platform.map { + this.typeToCarthagePlatform(it) + } as Provider + + final Property commandRunnerProperty = project.objects.property(CommandRunner) + + final WorkerExecutor workerExecutor + + static final String CARTHAGE_FILE = "Cartfile" + static final String CARTHAGE_PLATFORM_IOS = "iOS" + static final String CARTHAGE_PLATFORM_MACOS = "Mac" + static final String CARTHAGE_PLATFORM_TVOS = "tvOS" + static final String CARTHAGE_PLATFORM_WATCHOS = "watchOS" - CarthageBootStrapTask() { + static final Pattern LINE_PATTERN = ~/^(binary|github|git)\s"([^"^\/]+)\/(([^\/]+)||([^"]+)\/([^"]+).json)"."([^"]+)"$/ + + @Inject + CarthageBootStrapTask(WorkerExecutor workerExecutor) { super() + this.workerExecutor = workerExecutor + setDescription "Check out and build the Carthage project dependencies" + + cartFile.set(new File(project.rootProject.rootDir, "Cartfile.resolved")) + + onlyIf { + return cartFile.asFile.get().exists() + } + } + + @OutputDirectories + Map getOutputFiles() { + HashMap result = new HashMap<>() + cartFile.asFile + .get() + .getText() + .readLines() + .collect { return LINE_PATTERN.matcher(it) } + .findAll { it.matches() } + .collect { it.group(3) } + .each { + result.put(it, new File(project.rootProject.projectDir, + "Carthage/Build/${carthagePlatformName.get()}/${it}.framework")) + } + + return result } @TaskAction void update() { - if (hasCartFile()) { - logger.info('Boostrap Carthage for platform ' + carthagePlatformName) - def output = services.get(StyledTextOutputFactory) - .create(CarthageBootStrapTask) - - List args = [getCarthageCommand(), - ACTION_BOOTSTRAP, - ARG_PLATFORM, - carthagePlatformName, - ARG_CACHE_BUILDS] - - commandRunner.run(project.projectDir.absolutePath, - args, - getRequiredXcodeVersion() != null ? xcode.getXcodeSelectEnvValue(getRequiredXcodeVersion()) : null, - new ConsoleOutputAppender(output)) + logger.warn('Bootstrap Carthage for platform ' + carthagePlatformName) + + List names = cartFile.asFile + .get() + .getText() + .readLines() + .collect { return LINE_PATTERN.matcher(it) } + .findAll { it.matches() } + .collect { it.group(3) } + .each { createWorker(it) } + + workerExecutor.await() + } + + private void createWorker(String source) { + workerExecutor.submit(CarthageBootstrapRunnable.class) { WorkerConfiguration config -> + // Use the minimum level of isolation + config.isolationMode = IsolationMode.PROCESS + + // Constructor parameters for the unit of work implementation + config.params project.rootProject.projectDir, + source, + carthagePlatformName.get(), + commandRunnerProperty.get() + + config.displayName = "Bootstrap " + source + } + } + + private String typeToCarthagePlatform(Type type) { + switch (type) { + case Type.iOS: return CARTHAGE_PLATFORM_IOS + case Type.tvOS: return CARTHAGE_PLATFORM_TVOS + case Type.macOS: return CARTHAGE_PLATFORM_MACOS + case Type.watchOS: return CARTHAGE_PLATFORM_WATCHOS + default: return 'all' } } } diff --git a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy new file mode 100644 index 00000000..932f06fc --- /dev/null +++ b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy @@ -0,0 +1,70 @@ +package org.openbakery.carthage + +import groovy.util.logging.Slf4j +import org.openbakery.CommandRunner +import org.openbakery.CommandRunnerException +import org.openbakery.output.OutputAppender + +import javax.inject.Inject + +@Slf4j +class CarthageBootstrapRunnable implements Runnable { + + static final String ACTION_BOOTSTRAP = "bootstrap" + static final String ARG_PLATFORM = "--platform" + static final String ARG_CACHE_BUILDS = "--cache-builds" + static final String CARTHAGE_USR_BIN_PATH = "/usr/local/bin/carthage" + + final File projectDir + final OutputAppender outputAppender + final String platform + final String source + final CommandRunner commandRunner + + @Inject + CarthageBootstrapRunnable(File projectDir, + String source, + String platform, + CommandRunner commandRunner) { + println "platform : " + platform + assert false + this.projectDir = projectDir + this.source = source + this.platform = platform + this.outputAppender = outputAppender + this.commandRunner = commandRunner + } + + @Override + void run() { + commandRunner.run([getCarthageCommand(), + ACTION_BOOTSTRAP, + "--color", "always", + "--project-directory", "${projectDir.absolutePath}", + ARG_CACHE_BUILDS, + ARG_PLATFORM, platform, + source], + new OutputAppender() { + @Override + void append(String output) { + log.debug(output) + } + }) + } + + String getCarthageCommand() { + try { + return commandRunner.runWithResult("which", "carthage") + } catch (CommandRunnerException exception) { + // ignore, because try again with full path below + } + + try { + commandRunner.runWithResult("ls", CARTHAGE_USR_BIN_PATH) + return CARTHAGE_USR_BIN_PATH + } catch (CommandRunnerException exception) { + // ignore, because blow an exception is thrown + } + throw new IllegalStateException("The carthage command was not found. Make sure that Carthage is installed") + } +} From 4f57ba5d283252a334f2a13204d612146dcfd797 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Wed, 30 May 2018 15:25:31 +0100 Subject: [PATCH 02/16] Add the carthage bootstrap caching support --- .../groovy/org/openbakery/xcode/Xcode.groovy | 2 +- .../XcodeBuildPluginExtension.groovy | 4 + .../groovy/org/openbakery/XcodePlugin.groovy | 3 +- .../carthage/AbstractCarthageTaskBase.groovy | 2 +- .../carthage/CarthageBootStrapTask.groovy | 143 +++++++++++------- .../carthage/CarthageBootstrapRunnable.groovy | 45 ++---- 6 files changed, 114 insertions(+), 85 deletions(-) diff --git a/libxcode/src/main/groovy/org/openbakery/xcode/Xcode.groovy b/libxcode/src/main/groovy/org/openbakery/xcode/Xcode.groovy index 89f80ad2..274fb4df 100644 --- a/libxcode/src/main/groovy/org/openbakery/xcode/Xcode.groovy +++ b/libxcode/src/main/groovy/org/openbakery/xcode/Xcode.groovy @@ -58,7 +58,7 @@ class Xcode { if (file.exists()) { result.put(ENV_DEVELOPER_DIR, file.absolutePath) } - println file.absolutePath + return result } diff --git a/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy b/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy index 4823ee50..207649e8 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy @@ -35,6 +35,7 @@ class XcodeBuildPluginExtension { final Property bitcode = project.objects.property(Boolean) final Property version = project.objects.property(String) + final Property targetType = project.objects.property(Type) final Property scheme = project.objects.property(String) final DirectoryProperty archiveDirectory = project.layout.directoryProperty() final DirectoryProperty schemeArchiveFile = project.layout.directoryProperty() @@ -108,6 +109,8 @@ class XcodeBuildPluginExtension { this.symRoot.set(project.layout.buildDirectory.dir("sym")) this.sharedPrecompsDir.set(project.layout.buildDirectory.dir("shared")) this.derivedDataPath.set(project.layout.buildDirectory.dir("derivedData")) + + this.targetType.set(Type.iOS) } private void configureServices() { @@ -358,6 +361,7 @@ class XcodeBuildPluginExtension { void setType(String type) { this.type = Type.typeFromString(type) + this.targetType.set(this.type) } Type getType() { diff --git a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy index 40beeb79..4a989c0d 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy @@ -696,8 +696,9 @@ class XcodePlugin implements Plugin { project.tasks.create(CARTHAGE_BOOTSTRAP_TASK_NAME, CarthageBootStrapTask.class) { it.group = CARTHAGE_GROUP_NAME + it.requiredXcodeVersion.set(xcodeBuildPluginExtension.version) it.commandRunnerProperty.set(commandRunner) - it.platform.set(xcodeBuildPluginExtension.type) + it.platform.set(xcodeBuildPluginExtension.targetType) } } diff --git a/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy b/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy index 2e70c2be..d26c96ad 100644 --- a/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy +++ b/plugin/src/main/groovy/org/openbakery/carthage/AbstractCarthageTaskBase.groovy @@ -57,7 +57,7 @@ abstract class AbstractCarthageTaskBase extends AbstractXcodeTask { @Input String getCarthagePlatformName() { - switch (project.extensions.findByType(XcodeBuildPluginExtension).type.get()) { + switch (project.extensions.findByType(XcodeBuildPluginExtension).type) { case Type.iOS: return CARTHAGE_PLATFORM_IOS case Type.tvOS: return CARTHAGE_PLATFORM_TVOS case Type.macOS: return CARTHAGE_PLATFORM_MACOS diff --git a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy index 5938d5d4..dbb86216 100644 --- a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy @@ -1,46 +1,54 @@ package org.openbakery.carthage import groovy.transform.CompileStatic +import org.gradle.api.Action import org.gradle.api.DefaultTask +import org.gradle.api.Transformer import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider import org.gradle.api.tasks.* -import org.gradle.workers.IsolationMode -import org.gradle.workers.WorkerConfiguration +import org.gradle.process.ExecSpec import org.gradle.workers.WorkerExecutor import org.openbakery.CommandRunner +import org.openbakery.CommandRunnerException import org.openbakery.xcode.Type +import org.openbakery.xcode.Xcode import javax.inject.Inject -import java.util.regex.Pattern @CacheableTask @CompileStatic class CarthageBootStrapTask extends DefaultTask { + @Input + @Optional + Property requiredXcodeVersion = project.objects.property(String) + + @Input + Property carthagePlatformName = project.objects.property(String) + @InputFile @PathSensitive(PathSensitivity.NAME_ONLY) RegularFileProperty cartFile = project.layout.fileProperty() - Property platform = project.objects.property(Type) - - @Input - Provider carthagePlatformName = platform.map { - this.typeToCarthagePlatform(it) - } as Provider + @OutputDirectory + Property outputDirectory = project.objects.property(File) + final Property platform = project.objects.property(Type) + final Property xcodeProperty = project.objects.property(Xcode) final Property commandRunnerProperty = project.objects.property(CommandRunner) final WorkerExecutor workerExecutor - static final String CARTHAGE_FILE = "Cartfile" + static final String CARTHAGE_FILE = "Cartfile.resolved" static final String CARTHAGE_PLATFORM_IOS = "iOS" static final String CARTHAGE_PLATFORM_MACOS = "Mac" static final String CARTHAGE_PLATFORM_TVOS = "tvOS" static final String CARTHAGE_PLATFORM_WATCHOS = "watchOS" - - static final Pattern LINE_PATTERN = ~/^(binary|github|git)\s"([^"^\/]+)\/(([^\/]+)||([^"]+)\/([^"]+).json)"."([^"]+)"$/ + static final String CARTHAGE_USR_BIN_PATH = "/usr/local/bin/carthage" + static final String ACTION_BOOTSTRAP = "bootstrap" + static final String ARG_PLATFORM = "--platform" + static final String ARG_CACHE_BUILDS = "--cache-builds" @Inject CarthageBootStrapTask(WorkerExecutor workerExecutor) { @@ -49,60 +57,70 @@ class CarthageBootStrapTask extends DefaultTask { setDescription "Check out and build the Carthage project dependencies" - cartFile.set(new File(project.rootProject.rootDir, "Cartfile.resolved")) + cartFile.set(new File(project.rootProject.rootDir, CARTHAGE_FILE)) + + carthagePlatformName.set(platform.map(new Transformer() { + @Override + String transform(Type type) { + return typeToCarthagePlatform(type) + } + })) + + outputDirectory.set(carthagePlatformName.map(new Transformer() { + @Override + File transform(String platformName) { + return new File(project.rootProject.rootDir, "Carthage/Build/" + platformName) + } + })) + + xcodeProperty.set(commandRunnerProperty.map(new Transformer() { + @Override + Xcode transform(CommandRunner commandRunner) { + return new Xcode(commandRunner) + } + })) onlyIf { return cartFile.asFile.get().exists() } } - @OutputDirectories - Map getOutputFiles() { - HashMap result = new HashMap<>() - cartFile.asFile - .get() - .getText() - .readLines() - .collect { return LINE_PATTERN.matcher(it) } - .findAll { it.matches() } - .collect { it.group(3) } - .each { - result.put(it, new File(project.rootProject.projectDir, - "Carthage/Build/${carthagePlatformName.get()}/${it}.framework")) - } - - return result + public void setXcode(Xcode xcode) { + this.xcode = xcode } @TaskAction void update() { logger.warn('Bootstrap Carthage for platform ' + carthagePlatformName) - - List names = cartFile.asFile - .get() - .getText() - .readLines() - .collect { return LINE_PATTERN.matcher(it) } - .findAll { it.matches() } - .collect { it.group(3) } - .each { createWorker(it) } - - workerExecutor.await() + println "getCarthageCommand : " + getCarthageCommand() + + project.exec(new Action() { + @Override + void execute(ExecSpec execSpec) { + execSpec.args = [ACTION_BOOTSTRAP, + ARG_CACHE_BUILDS, + "--new-resolver", + "--color", "always", + ARG_PLATFORM, + carthagePlatformName.getOrNull().toString()] as List + + execSpec.environment(getEnvValues()) + execSpec.executable = getCarthageCommand() + execSpec.workingDir(project.rootProject.projectDir) + } + }) } - private void createWorker(String source) { - workerExecutor.submit(CarthageBootstrapRunnable.class) { WorkerConfiguration config -> - // Use the minimum level of isolation - config.isolationMode = IsolationMode.PROCESS - - // Constructor parameters for the unit of work implementation - config.params project.rootProject.projectDir, - source, - carthagePlatformName.get(), - commandRunnerProperty.get() - - config.displayName = "Bootstrap " + source + private final Map getEnvValues() { + final Map envValues + if (requiredXcodeVersion.present) { + envValues = xcodeProperty.get() + .getXcodeSelectEnvValue(requiredXcodeVersion.getOrNull()) + } else { + envValues = [:] } + + return envValues } private String typeToCarthagePlatform(Type type) { @@ -114,4 +132,23 @@ class CarthageBootStrapTask extends DefaultTask { default: return 'all' } } + + private String getCarthageCommand() { + try { + return commandRunnerProperty.get() + .runWithResult("which", "carthage") + } catch (CommandRunnerException exception) { + // ignore, because try again with full path below + } + + try { + commandRunnerProperty.get() + .runWithResult("ls", CARTHAGE_USR_BIN_PATH) + return CARTHAGE_USR_BIN_PATH + } catch (CommandRunnerException exception) { + // ignore, because blow an exception is thrown + } + + throw new IllegalStateException("The carthage command was not found. Make sure that Carthage is installed") + } } diff --git a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy index 932f06fc..5e6160a6 100644 --- a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy +++ b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy @@ -1,49 +1,52 @@ package org.openbakery.carthage -import groovy.util.logging.Slf4j +import groovy.util.logging.Log4j import org.openbakery.CommandRunner -import org.openbakery.CommandRunnerException import org.openbakery.output.OutputAppender import javax.inject.Inject -@Slf4j +@Log4j class CarthageBootstrapRunnable implements Runnable { - static final String ACTION_BOOTSTRAP = "bootstrap" - static final String ARG_PLATFORM = "--platform" - static final String ARG_CACHE_BUILDS = "--cache-builds" - static final String CARTHAGE_USR_BIN_PATH = "/usr/local/bin/carthage" + + final CommandRunner commandRunner + final String carthageCommand final File projectDir + final Map environmentValues final OutputAppender outputAppender final String platform final String source - final CommandRunner commandRunner @Inject CarthageBootstrapRunnable(File projectDir, + String carthageCommand, String source, String platform, - CommandRunner commandRunner) { - println "platform : " + platform - assert false + CommandRunner commandRunner, + Map environmentValues) { + this.carthageCommand = carthageCommand this.projectDir = projectDir this.source = source this.platform = platform this.outputAppender = outputAppender this.commandRunner = commandRunner + this.environmentValues = environmentValues } @Override void run() { - commandRunner.run([getCarthageCommand(), + log.debug("Carthage bootstrap source : " + source) + commandRunner.run([carthageCommand, ACTION_BOOTSTRAP, + ARG_CACHE_BUILDS, + "--new-resolver", "--color", "always", "--project-directory", "${projectDir.absolutePath}", - ARG_CACHE_BUILDS, ARG_PLATFORM, platform, source], + environmentValues, new OutputAppender() { @Override void append(String output) { @@ -51,20 +54,4 @@ class CarthageBootstrapRunnable implements Runnable { } }) } - - String getCarthageCommand() { - try { - return commandRunner.runWithResult("which", "carthage") - } catch (CommandRunnerException exception) { - // ignore, because try again with full path below - } - - try { - commandRunner.runWithResult("ls", CARTHAGE_USR_BIN_PATH) - return CARTHAGE_USR_BIN_PATH - } catch (CommandRunnerException exception) { - // ignore, because blow an exception is thrown - } - throw new IllegalStateException("The carthage command was not found. Make sure that Carthage is installed") - } } From be9afa92bc78cd762cee555ab2fa3537cf8bec65 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Wed, 30 May 2018 15:25:53 +0100 Subject: [PATCH 03/16] The runnable is no more needed --- .../carthage/CarthageBootstrapRunnable.groovy | 57 ------------------- 1 file changed, 57 deletions(-) delete mode 100644 plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy diff --git a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy deleted file mode 100644 index 5e6160a6..00000000 --- a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootstrapRunnable.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.openbakery.carthage - -import groovy.util.logging.Log4j -import org.openbakery.CommandRunner -import org.openbakery.output.OutputAppender - -import javax.inject.Inject - -@Log4j -class CarthageBootstrapRunnable implements Runnable { - - - - final CommandRunner commandRunner - final String carthageCommand - final File projectDir - final Map environmentValues - final OutputAppender outputAppender - final String platform - final String source - - @Inject - CarthageBootstrapRunnable(File projectDir, - String carthageCommand, - String source, - String platform, - CommandRunner commandRunner, - Map environmentValues) { - this.carthageCommand = carthageCommand - this.projectDir = projectDir - this.source = source - this.platform = platform - this.outputAppender = outputAppender - this.commandRunner = commandRunner - this.environmentValues = environmentValues - } - - @Override - void run() { - log.debug("Carthage bootstrap source : " + source) - commandRunner.run([carthageCommand, - ACTION_BOOTSTRAP, - ARG_CACHE_BUILDS, - "--new-resolver", - "--color", "always", - "--project-directory", "${projectDir.absolutePath}", - ARG_PLATFORM, platform, - source], - environmentValues, - new OutputAppender() { - @Override - void append(String output) { - log.debug(output) - } - }) - } -} From a35c3a153df1f30e7bc225906f49398eb4982140 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Wed, 30 May 2018 15:42:52 +0100 Subject: [PATCH 04/16] Cleanup --- plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy index 4a989c0d..bfa6e3c6 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy @@ -692,7 +692,6 @@ class XcodePlugin implements Plugin { private void configureCarthage(Project project) { project.task(CARTHAGE_CLEAN_TASK_NAME, type: CarthageCleanTask, group: CARTHAGE_GROUP_NAME) project.task(CARTHAGE_UPDATE_TASK_NAME, type: CarthageUpdateTask, group: CARTHAGE_GROUP_NAME) -// project.task(CARTHAGE_BOOTSTRAP_TASK_NAME, type: CarthageBootStrapTask, group: CARTHAGE_GROUP_NAME) project.tasks.create(CARTHAGE_BOOTSTRAP_TASK_NAME, CarthageBootStrapTask.class) { it.group = CARTHAGE_GROUP_NAME From 55da6f491fe87dd0a560e8614b08c0519eeddf21 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Thu, 31 May 2018 10:28:35 +0100 Subject: [PATCH 05/16] Convert the old unit to a functional one --- .../KeychainCreateTaskFunctionalTest.groovy | 8 +- ...CarthageBootStrapTaskFunctionalTest.groovy | 127 +++++++++++++++ ...ovisioningInstallTaskFunctionalTest.groovy | 6 +- .../groovy/org/openbakery/XcodePlugin.groovy | 7 +- .../carthage/CarthageBootStrapTask.groovy | 6 +- .../carthage/CarthageBootStrapTaskTest.groovy | 150 ------------------ 6 files changed, 142 insertions(+), 162 deletions(-) create mode 100644 plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy delete mode 100644 plugin/src/test/groovy/org/openbakery/carthage/CarthageBootStrapTaskTest.groovy diff --git a/plugin/src/functionalTest/groovy/org/openbakery/KeychainCreateTaskFunctionalTest.groovy b/plugin/src/functionalTest/groovy/org/openbakery/KeychainCreateTaskFunctionalTest.groovy index c93801a1..71b02662 100644 --- a/plugin/src/functionalTest/groovy/org/openbakery/KeychainCreateTaskFunctionalTest.groovy +++ b/plugin/src/functionalTest/groovy/org/openbakery/KeychainCreateTaskFunctionalTest.groovy @@ -75,7 +75,7 @@ class KeychainCreateTaskFunctionalTest extends Specification { buildFile << """ xcodebuild { signing { - certificate = project.provisioningFile1("$certificate") + certificateURI = "$certificate.absolutePath" } } """ @@ -84,6 +84,7 @@ class KeychainCreateTaskFunctionalTest extends Specification { BuildResult result = GradleRunner.create() .withProjectDir(testProjectDir.root) .withArguments(KeychainCreateTask.TASK_NAME) + .withDebug(true) .withPluginClasspath(pluginClasspath) .build() @@ -96,7 +97,7 @@ class KeychainCreateTaskFunctionalTest extends Specification { buildFile << """ xcodebuild { signing { - certificate = project.provisioningFile1("$certificate") + certificateURI = "${certificate.toURI().toString()}" certificatePassword = "p4ssword" } } @@ -107,6 +108,7 @@ class KeychainCreateTaskFunctionalTest extends Specification { .withProjectDir(testProjectDir.root) .withArguments(KeychainCreateTask.TASK_NAME) .withPluginClasspath(pluginClasspath) + .withDebug(true) .build() then: @@ -118,7 +120,7 @@ class KeychainCreateTaskFunctionalTest extends Specification { buildFile << """ xcodebuild { signing { - certificate = project.provisioningFile1("$certificate") + certificateURI = "${certificate.toURI().toString()}" certificatePassword = "p4ssword" } } diff --git a/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy b/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy new file mode 100644 index 00000000..a753b3c4 --- /dev/null +++ b/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy @@ -0,0 +1,127 @@ +package org.openbakery.carthage + +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner +import org.gradle.testkit.runner.TaskOutcome +import org.junit.Rule +import org.junit.rules.TemporaryFolder +import spock.lang.Specification + +class CarthageBootStrapTaskFunctionalTest extends Specification { + @Rule + final TemporaryFolder testProjectDir = new TemporaryFolder() + + List pluginClasspath + File buildFile + GradleRunner gradleRunner + File carthageFolder + + void setup() { + buildFile = testProjectDir.newFile('build.gradle') + + buildFile << """ + plugins { + id 'org.openbakery.xcode-plugin' + } + """ + + def pluginClasspathResource = getClass().classLoader.findResource("plugin-classpath.txt") + if (pluginClasspathResource == null) { + throw new IllegalStateException("Did not find plugin classpath resource, run `testClasses` build task.") + } + + pluginClasspath = pluginClasspathResource.readLines().collect { new File(it) } + + gradleRunner = GradleRunner.create() + .withProjectDir(testProjectDir.root) + .withArguments(CarthageBootStrapTask.NAME) + .withPluginClasspath(pluginClasspath) + + carthageFolder = new File(testProjectDir.root, "Carthage") + } + + def "The task list should contain the task"() { + when: + BuildResult result = gradleRunner.build() + + then: + result.output.contains(CarthageBootStrapTask.NAME) + } + + def "The task should be skipped if no cartfile is present"() { + when: + BuildResult result = gradleRunner.build() + + then: + result.task(":" + CarthageBootStrapTask.NAME) + .outcome == TaskOutcome.SKIPPED + } + + def "The task should be executed with success if a `cartfile.resolved` file is present"() { + setup: + testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_FILE) + + when: + BuildResult result = gradleRunner.build() + + then: + result.task(":" + CarthageBootStrapTask.NAME) + .outcome == TaskOutcome.SUCCESS + } + + def "The task should resolve the defined carthage dependencies"() { + setup: + File carthageFile = testProjectDir.newFile("Cartfile") + carthageFile << """ + github "ashleymills/Reachability.swift" + """ + + File carthageResolvedFile = testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_FILE) + carthageResolvedFile << """ + github "ashleymills/Reachability.swift" "v4.1.0" + """ + + when: + BuildResult result = gradleRunner.build() + + then: + result.task(":" + CarthageBootStrapTask.NAME) + .outcome == TaskOutcome.SUCCESS + + and: "The resolved framework should be existing only for iOS (default target)" + carthageFolder.exists() + new File(carthageFolder, "Build/iOS/Reachability.framework").exists() + !new File(carthageFolder, "Build/tvOS/Reachability.framework").exists() + } + + def "The task should resolve the defined carthage dependencies depending of the configured target"() { + setup: + File carthageFile = testProjectDir.newFile("Cartfile") + carthageFile << """ + github "ashleymills/Reachability.swift" + """ + + File carthageResolvedFile = testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_FILE) + carthageResolvedFile << """ + github "ashleymills/Reachability.swift" "v4.1.0" + """ + + buildFile << """ + xcodebuild { + type = "tvOS" + } + """ + + when: + BuildResult result = gradleRunner.build() + + then: + result.task(":" + CarthageBootStrapTask.NAME) + .outcome == TaskOutcome.SUCCESS + + and: "The resolved framework should be existing only for iOS (default target)" + carthageFolder.exists() + !new File(carthageFolder, "Build/iOS/Reachability.framework").exists() + new File(carthageFolder, "Build/tvOS/Reachability.framework").exists() + } +} diff --git a/plugin/src/functionalTest/groovy/org/openbakery/signing/ProvisioningInstallTaskFunctionalTest.groovy b/plugin/src/functionalTest/groovy/org/openbakery/signing/ProvisioningInstallTaskFunctionalTest.groovy index d20157ff..16dce6f6 100644 --- a/plugin/src/functionalTest/groovy/org/openbakery/signing/ProvisioningInstallTaskFunctionalTest.groovy +++ b/plugin/src/functionalTest/groovy/org/openbakery/signing/ProvisioningInstallTaskFunctionalTest.groovy @@ -30,7 +30,9 @@ class ProvisioningInstallTaskFunctionalTest extends Specification { provisioningFile1 = findResource("test1.mobileprovision") assert provisioningFile1.exists() - def pluginClasspathResource = getClass().classLoader.findResource("plugin-classpath.txt") + def pluginClasspathResource = getClass().classLoader + .findResource("plugin-classpath.txt") + if (pluginClasspathResource == null) { throw new IllegalStateException("Did not find plugin classpath resource, run `testClasses` build task.") } @@ -70,7 +72,7 @@ class ProvisioningInstallTaskFunctionalTest extends Specification { buildFile << """ xcodebuild { signing { - mobileProvisionURI = [] + mobileProvisionList = [] } } """ diff --git a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy index bfa6e3c6..ce142110 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy @@ -116,7 +116,6 @@ class XcodePlugin implements Plugin { public static final String OCLINT_TASK_NAME = 'oclint' public static final String OCLINT_REPORT_TASK_NAME = 'oclintReport' public static final String CPD_TASK_NAME = 'cpd' - public static final String CARTHAGE_BOOTSTRAP_TASK_NAME = 'carthageBootstrap' public static final String CARTHAGE_UPDATE_TASK_NAME = 'carthageUpdate' public static final String CARTHAGE_CLEAN_TASK_NAME = 'carthageClean' @@ -522,7 +521,7 @@ class XcodePlugin implements Plugin { } private void configureSimulatorTasks(Project project) { - project.task(SIMULATORS_LIST_TASK_NAME, type: SimulatorsListTask, group: SIMULATORS_LIST_TASK_NAME) + project.task(SIMULATORS_LIST_TASK_NAME, type: SimulatorsListTask.class, group: SIMULATORS_LIST_TASK_NAME) project.task(SIMULATORS_CREATE_TASK_NAME, type: SimulatorsCreateTask, group: SIMULATORS_LIST_TASK_NAME) project.task(SIMULATORS_CLEAN_TASK_NAME, type: SimulatorsCleanTask, group: SIMULATORS_LIST_TASK_NAME) @@ -693,7 +692,7 @@ class XcodePlugin implements Plugin { project.task(CARTHAGE_CLEAN_TASK_NAME, type: CarthageCleanTask, group: CARTHAGE_GROUP_NAME) project.task(CARTHAGE_UPDATE_TASK_NAME, type: CarthageUpdateTask, group: CARTHAGE_GROUP_NAME) - project.tasks.create(CARTHAGE_BOOTSTRAP_TASK_NAME, CarthageBootStrapTask.class) { + project.tasks.create(CarthageBootStrapTask.NAME, CarthageBootStrapTask.class) { it.group = CARTHAGE_GROUP_NAME it.requiredXcodeVersion.set(xcodeBuildPluginExtension.version) it.commandRunnerProperty.set(commandRunner) @@ -702,7 +701,7 @@ class XcodePlugin implements Plugin { } private configureCarthageDependencies(Project project) { - CarthageBootStrapTask bootStrapTask = project.getTasks().getByName(CARTHAGE_BOOTSTRAP_TASK_NAME) + CarthageBootStrapTask bootStrapTask = project.getTasks().getByName(CarthageBootStrapTask.NAME) as CarthageBootStrapTask addDependencyToBuild(project, bootStrapTask) project.getTasks() diff --git a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy index dbb86216..94df3517 100644 --- a/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/carthage/CarthageBootStrapTask.groovy @@ -34,6 +34,8 @@ class CarthageBootStrapTask extends DefaultTask { @OutputDirectory Property outputDirectory = project.objects.property(File) + public static final String NAME = "carthageBootstrap" + final Property platform = project.objects.property(Type) final Property xcodeProperty = project.objects.property(Xcode) final Property commandRunnerProperty = project.objects.property(CommandRunner) @@ -85,15 +87,13 @@ class CarthageBootStrapTask extends DefaultTask { } } - public void setXcode(Xcode xcode) { + void setXcode(Xcode xcode) { this.xcode = xcode } @TaskAction void update() { logger.warn('Bootstrap Carthage for platform ' + carthagePlatformName) - println "getCarthageCommand : " + getCarthageCommand() - project.exec(new Action() { @Override void execute(ExecSpec execSpec) { diff --git a/plugin/src/test/groovy/org/openbakery/carthage/CarthageBootStrapTaskTest.groovy b/plugin/src/test/groovy/org/openbakery/carthage/CarthageBootStrapTaskTest.groovy deleted file mode 100644 index 8f45eeb5..00000000 --- a/plugin/src/test/groovy/org/openbakery/carthage/CarthageBootStrapTaskTest.groovy +++ /dev/null @@ -1,150 +0,0 @@ -package org.openbakery.carthage - -import org.gradle.api.Project -import org.gradle.api.provider.Provider -import org.gradle.testfixtures.ProjectBuilder -import org.junit.Rule -import org.junit.rules.ExpectedException -import org.openbakery.CommandRunner -import org.openbakery.output.ConsoleOutputAppender -import org.openbakery.xcode.Xcode -import spock.lang.Specification -import spock.lang.Unroll - -import static org.openbakery.carthage.AbstractCarthageTaskBase.* -import static org.openbakery.xcode.Type.* - -class CarthageBootStrapTaskTest extends Specification { - - CarthageBootStrapTask subject - CommandRunner commandRunner = Mock(CommandRunner) - Xcode mockXcode = Mock(Xcode) - File projectDir - File cartFile - Project project - - @Rule - public ExpectedException exception = ExpectedException.none() - - void setup() { - projectDir = File.createTempDir() - - cartFile = new File(projectDir, "Cartfile") - cartFile << 'github "Alamofire/Alamofire"' - - project = ProjectBuilder.builder() - .withProjectDir(projectDir) - .build() - - project.buildDir = new File(projectDir, 'build').absoluteFile - project.apply plugin: org.openbakery.XcodePlugin - - subject = project.getTasks().getByPath('carthageBootstrap') - assert subject != null - - subject.commandRunner = commandRunner - } - - def "The carthage bootstrap task should be present"() { - expect: - subject instanceof CarthageBootStrapTask - } - - @Unroll - def "When bootstrap is executed should only update the platform: #platform"() { - given: - commandRunner.runWithResult("which", "carthage") >> "/usr/local/bin/carthage" - project.xcodebuild.type = platform - - when: - subject.update() - - then: - 1 * commandRunner.run(_, - [CARTHAGE_USR_BIN_PATH, - ACTION_BOOTSTRAP, - ARG_PLATFORM, - carthagePlatform, - ARG_CACHE_BUILDS] - , _ - , _) >> { - args -> args[3] instanceof ConsoleOutputAppender - } - - where: - platform | carthagePlatform - tvOS | CARTHAGE_PLATFORM_TVOS - macOS | CARTHAGE_PLATFORM_MACOS - watchOS | CARTHAGE_PLATFORM_WATCHOS - iOS | CARTHAGE_PLATFORM_IOS - } - - def "The task should not be executed if the 'Cartfile` file is missing"() { - given: - commandRunner.runWithResult("which", "carthage") >> "/usr/local/bin/carthage" - project.xcodebuild.type = platform - - when: - cartFile.delete() - subject.update() - - then: - 0 * commandRunner.run(_, - getCommandRunnerArgsForPlatform(carthagePlatform), - _, - _) >> { - args -> args[3] instanceof ConsoleOutputAppender - } - - where: - platform | carthagePlatform - tvOS | CARTHAGE_PLATFORM_TVOS - macOS | CARTHAGE_PLATFORM_MACOS - watchOS | CARTHAGE_PLATFORM_WATCHOS - iOS | CARTHAGE_PLATFORM_IOS - } - - def "The subject output directory should be platform dependant"() { - when: - subject.xcode.getXcodeSelectEnvValue(_) >> new HashMap() - project.xcodebuild.type = platform - - then: - Provider outputDirectory = subject.outputDirectory - outputDirectory.isPresent() - outputDirectory.get().name == carthagePlatform - - where: - platform | carthagePlatform - tvOS | CARTHAGE_PLATFORM_TVOS - macOS | CARTHAGE_PLATFORM_MACOS - watchOS | CARTHAGE_PLATFORM_WATCHOS - iOS | CARTHAGE_PLATFORM_IOS - } - - def "The xcode selection should be applied if a xcode version is defined"() { - when: - subject.xcode.getXcodeSelectEnvValue(_) >> new HashMap() - project.xcodebuild.type = iOS - project.xcodebuild.version = version - - subject.xcode = mockXcode - subject.xcode.setVersionFromString(_) >> _ - subject.update() - - then: - 1 * mockXcode.getXcodeSelectEnvValue(version) - - where: - version | _ - "7.1.1" | _ - } - - private List getCommandRunnerArgsForPlatform(String carthagePlatform) { - return [CARTHAGE_USR_BIN_PATH, - ACTION_UPDATE, - ARG_PLATFORM, - carthagePlatform, - ARG_CACHE_BUILDS] - } -} From c372b0ea52d22e1c04e506d0190c2aed2fcba71d Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Thu, 31 May 2018 10:48:39 +0100 Subject: [PATCH 06/16] Add a FROM_CACHE functional test --- .../CarthageBootStrapTaskFunctionalTest.groovy | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy b/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy index a753b3c4..ec6a21fc 100644 --- a/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy +++ b/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy @@ -82,7 +82,8 @@ class CarthageBootStrapTaskFunctionalTest extends Specification { """ when: - BuildResult result = gradleRunner.build() + BuildResult result = gradleRunner + .build() then: result.task(":" + CarthageBootStrapTask.NAME) @@ -92,6 +93,18 @@ class CarthageBootStrapTaskFunctionalTest extends Specification { carthageFolder.exists() new File(carthageFolder, "Build/iOS/Reachability.framework").exists() !new File(carthageFolder, "Build/tvOS/Reachability.framework").exists() + + when: "Force reset and build with cache enabled" + assert carthageFolder.deleteDir() + result = gradleRunner.withArguments('--build-cache', CarthageBootStrapTask.NAME) + .build() + + then: "Should resolve the carthage dependencies from cache" + result.task(":" + CarthageBootStrapTask.NAME) + .outcome == TaskOutcome.FROM_CACHE + + new File(carthageFolder, "Build/iOS/Reachability.framework").exists() + !new File(carthageFolder, "Build/tvOS/Reachability.framework").exists() } def "The task should resolve the defined carthage dependencies depending of the configured target"() { From ac6025a9a2b84b039b7f8fa63530afef57253de9 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Thu, 31 May 2018 10:49:14 +0100 Subject: [PATCH 07/16] No more necessary --- libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy b/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy index 86be35ff..b52aeeff 100644 --- a/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy +++ b/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy @@ -23,7 +23,7 @@ import org.openbakery.output.OutputAppender import org.slf4j.Logger import org.slf4j.LoggerFactory -class CommandRunner implements Serializable{ +class CommandRunner { private static Logger logger = LoggerFactory.getLogger(CommandRunner.class) From 2f6d65bb30bff7de5b17fd0b641eddbd01852385 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Mon, 4 Jun 2018 16:27:45 +0100 Subject: [PATCH 08/16] --wip-- [skip ci] --- build.gradle | 50 +++++++--- .../ExampleOSX.xcodeproj/project.pbxproj | 4 +- .../org/openbakery/CommandRunner.groovy | 6 +- .../org/openbakery/xcode/Xcodebuild.groovy | 12 ++- ...CarthageBootStrapTaskFunctionalTest.groovy | 6 +- .../openbakery/AbstractXcodeBuildTask.groovy | 4 +- .../org/openbakery/InfoPlistModifyTask.groovy | 4 +- .../PrepareXcodeArchivingTask.groovy | 97 ++++++++++++++++--- .../XcodeBuildPluginExtension.groovy | 43 ++++---- .../groovy/org/openbakery/XcodePlugin.groovy | 11 ++- .../org/openbakery/XcodeProjectFile.groovy | 7 +- .../XcodeBuildArchiveTaskIosAndTvOS.groovy | 11 +-- .../openbakery/coverage/CoverageTask.groovy | 2 +- .../groovy/org/openbakery/cpd/CpdTask.groovy | 2 +- .../org/openbakery/extension/Signing.groovy | 10 +- .../signing/ProvisioningInstallTask.groovy | 4 +- .../openbakery/signing/SigningMethod.groovy | 1 + .../openbakery/util/VariableResolver.groovy | 4 +- 18 files changed, 183 insertions(+), 95 deletions(-) diff --git a/build.gradle b/build.gradle index 8889fd2a..d403b2a7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,22 +1,44 @@ -allprojects { - apply plugin: 'java-gradle-plugin' - apply plugin: 'groovy' - - def versionNumber = "0.16.0.a603076-SNAPSHOT" - - if (project.hasProperty("versionNumber")) { - versionNumber = project.versionNumber - } - if (project.hasProperty("versionSuffix")) { - versionNumber += project.versionSuffix +buildscript { + repositories { + maven { + url "https://plugins.gradle.org/m2/" + } } - if (project.hasProperty("buildNumber")) { - versionNumber += "." + project.buildNumber + dependencies { + classpath "org.ajoberstar.reckon:reckon-gradle:0.7.0" } +} + +apply plugin: "org.ajoberstar.reckon" + +reckon { + scopeFromProp() + stageFromProp('snapshot', 'rc', 'final') +} + +reckonTagCreate.dependsOn 'check' +// + +allprojects { + apply plugin: 'java-gradle-plugin' + apply plugin: 'groovy' +// +// def versionNumber = "0.16.0.a603076-SNAPSHOT" +// +// if (project.hasProperty("versionNumber")) { +// versionNumber = project.versionNumber +// } +// if (project.hasProperty("versionSuffix")) { +// versionNumber += project.versionSuffix +// } +// if (project.hasProperty("buildNumber")) { +// versionNumber += "." + project.buildNumber +// } +// group = 'org.openbakery' - version = versionNumber + version = project.version sourceCompatibility = "1.6" targetCompatibility = "1.6" diff --git a/example/OSX/ExampleOSX/ExampleOSX.xcodeproj/project.pbxproj b/example/OSX/ExampleOSX/ExampleOSX.xcodeproj/project.pbxproj index 5a9d55a3..0e7cec4c 100644 --- a/example/OSX/ExampleOSX/ExampleOSX.xcodeproj/project.pbxproj +++ b/example/OSX/ExampleOSX/ExampleOSX.xcodeproj/project.pbxproj @@ -187,7 +187,7 @@ TargetAttributes = { A7F1890E1A6FE161002D206F = { CreatedOnToolsVersion = 6.1.1; - DevelopmentTeam = Z7L2YCUH45; + DevelopmentTeam = 2YFT3F89TY; }; A7F189211A6FE161002D206F = { CreatedOnToolsVersion = 6.1.1; @@ -404,6 +404,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Developer ID Application"; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 2YFT3F89TY; INFOPLIST_FILE = ExampleOSX/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -417,6 +418,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Developer ID Application"; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 2YFT3F89TY; INFOPLIST_FILE = ExampleOSX/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy b/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy index b52aeeff..2f3dba20 100644 --- a/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy +++ b/libxcode/src/main/groovy/org/openbakery/CommandRunner.groovy @@ -23,7 +23,7 @@ import org.openbakery.output.OutputAppender import org.slf4j.Logger import org.slf4j.LoggerFactory -class CommandRunner { +class CommandRunner implements Serializable{ private static Logger logger = LoggerFactory.getLogger(CommandRunner.class) @@ -34,10 +34,6 @@ class CommandRunner { Thread readerThread - public CommandRunner() { - - } - void setOutputFile(File outputFile) { if (outputFile.exists()) { diff --git a/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy b/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy index b84bae48..4d2a9f43 100644 --- a/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy +++ b/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy @@ -66,10 +66,9 @@ class Xcodebuild { static void archive(CommandRunner commandRunner, String scheme, File outputPath, - File xcConfig, + String configuration, @Nullable File xcodeApp) { assert scheme != null - assert xcConfig.exists() && !xcConfig.isDirectory() HashMap envMap = new HashMap<>() @@ -80,8 +79,13 @@ class Xcodebuild { List args = [EXECUTABLE, ACTION_ARCHIVE, ARGUMENT_SCHEME, scheme, - ARGUMENT_ARCHIVE_PATH, outputPath.absolutePath, - ARGUMENT_XCCONFIG, xcConfig.absolutePath] + "-configuration", configuration, + ARGUMENT_ARCHIVE_PATH, outputPath.absolutePath] + +// if (xcConfig != null) { +// args.push(ARGUMENT_XCCONFIG) +// args.push(xcConfig.absolutePath) +// } commandRunner.run(args, envMap) } diff --git a/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy b/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy index ec6a21fc..0587774e 100644 --- a/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy +++ b/plugin/src/functionalTest/groovy/org/openbakery/carthage/CarthageBootStrapTaskFunctionalTest.groovy @@ -59,7 +59,7 @@ class CarthageBootStrapTaskFunctionalTest extends Specification { def "The task should be executed with success if a `cartfile.resolved` file is present"() { setup: - testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_FILE) + testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_RESOLVED_FILE) when: BuildResult result = gradleRunner.build() @@ -76,7 +76,7 @@ class CarthageBootStrapTaskFunctionalTest extends Specification { github "ashleymills/Reachability.swift" """ - File carthageResolvedFile = testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_FILE) + File carthageResolvedFile = testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_RESOLVED_FILE) carthageResolvedFile << """ github "ashleymills/Reachability.swift" "v4.1.0" """ @@ -114,7 +114,7 @@ class CarthageBootStrapTaskFunctionalTest extends Specification { github "ashleymills/Reachability.swift" """ - File carthageResolvedFile = testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_FILE) + File carthageResolvedFile = testProjectDir.newFile(CarthageBootStrapTask.CARTHAGE_RESOLVED_FILE) carthageResolvedFile << """ github "ashleymills/Reachability.swift" "v4.1.0" """ diff --git a/plugin/src/main/groovy/org/openbakery/AbstractXcodeBuildTask.groovy b/plugin/src/main/groovy/org/openbakery/AbstractXcodeBuildTask.groovy index b50c49a7..edd69479 100644 --- a/plugin/src/main/groovy/org/openbakery/AbstractXcodeBuildTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/AbstractXcodeBuildTask.groovy @@ -107,7 +107,7 @@ abstract class AbstractXcodeBuildTask extends AbstractXcodeTask { } String getBundleIdentifier() { - File infoPlist = new File(project.projectDir, getXcodeExtension().infoPlist) + File infoPlist = new File(project.rootProject.rootDir, getXcodeExtension().infoPlist) return plistHelper.getValueFromPlist(infoPlist, "CFBundleIdentifier") } @@ -119,8 +119,6 @@ abstract class AbstractXcodeBuildTask extends AbstractXcodeTask { List provisioningList = getProvisioningUriList() .collect { it -> new File(new URI(it)) } - println "provisioningList : " + provisioningList - return Optional.ofNullable(ProvisioningProfileReader.getProvisionFileForIdentifier(bundleIdentifier, provisioningList, commandRunner, diff --git a/plugin/src/main/groovy/org/openbakery/InfoPlistModifyTask.groovy b/plugin/src/main/groovy/org/openbakery/InfoPlistModifyTask.groovy index 51b972a5..dda4ad00 100644 --- a/plugin/src/main/groovy/org/openbakery/InfoPlistModifyTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/InfoPlistModifyTask.groovy @@ -43,7 +43,7 @@ class InfoPlistModifyTask extends AbstractDistributeTask { throw new IllegalArgumentException("No Info.plist was found! Check you xcode project settings if the specified target has a Info.plist set.") } - infoPlist = new File(project.projectDir, project.xcodebuild.infoPlist) + infoPlist = new File(project.rootProject.projectDir, project.xcodebuild.infoPlist) logger.debug("Try to updating {}", infoPlist) @@ -148,7 +148,7 @@ class InfoPlistModifyTask extends AbstractDistributeTask { setValueForPlist(KeyBundleIdentifier, extension.bundleIdentifier) } else { xcodeExtension.getBuildTargetConfiguration(xcodeExtension.scheme.getOrNull(), - xcodeExtension.configuration) + xcodeExtension.configuration.get()) .map { it -> it.bundleIdentifier } .ifPresent { it -> setValueForPlist(KeyBundleIdentifier, it) } } diff --git a/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy b/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy index 57364b9c..e75ca53a 100644 --- a/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy @@ -11,6 +11,7 @@ import org.gradle.api.tasks.* import org.openbakery.codesign.ProvisioningProfileReader import org.openbakery.signing.KeychainCreateTask import org.openbakery.signing.ProvisioningInstallTask +import org.openbakery.util.PathHelper import org.openbakery.util.PlistHelper @CompileStatic @@ -21,7 +22,14 @@ class PrepareXcodeArchivingTask extends DefaultTask { final Provider entitlementsFile = newInputFile() @OutputFile - final Provider outputFile = newOutputFile() + final Property outputFile = newOutputFile() + + @InputDirectory + final Provider projectFile = newInputFile() + + final Provider scheme = project.objects.property(String) + final Provider buildConfiguration = project.objects.property(String) + final Provider target = project.objects.property(String) final ListProperty registeredProvisioningFiles = project.objects.listProperty(File) final Property commandRunnerProperty = project.objects.property(CommandRunner) @@ -79,38 +87,97 @@ class PrepareXcodeArchivingTask extends DefaultTask { } })) + this.outputFile.set(project.layout + .buildDirectory + .file(PathHelper.FOLDER_ARCHIVE + "/" + PathHelper.GENERATED_XCARCHIVE_FILE_NAME)) + this.onlyIf { return certificateFriendlyName.present && configurationBundleIdentifier.present && - outputFile.present && provisioningForConfiguration.present } } + private File getPbxProjFile() { + return new File(projectFile.get().asFile, "project.pbxproj") + } + + private Serializable getValueFromPbxProjFile(String value) { + return plistHelperProperty.get() + .getValueFromPlist(toXml(getPbxProjFile()), value) as Serializable + } + + private Serializable getObjectValueFromPbxProjFile(String value) { + return getValueFromPbxProjFile("objects:${value}") + } + + private String findProductId(String rootKey) { + return getValueFromPbxProjFile("objects:${rootKey}:targets") + .find { it -> getObjectValueFromPbxProjFile("${it}:productName") == target.get() } + } + + private String getBuildConfigurationIdentifier(String targetId) { + String configurationId = getObjectValueFromPbxProjFile("$targetId:buildConfigurationList") + List list = getObjectValueFromPbxProjFile("${configurationId}:buildConfigurations") as List + return list.find { + getValueFromPbxProjFile("objects:${it}:name") == buildConfiguration.get() + } + } + + private void setBuildConfigurationBuildSetting(String bcId, + String key, + String value) { + String completeKey = "objects:${bcId}:buildSettings:${key}" + Object property = plistHelperProperty.get().getValueFromPlist(getPbxProjFile(), completeKey) + + if (property == null) { + plistHelperProperty.get() + .addValueForPlist(getPbxProjFile(), completeKey, value) + } else { + + plistHelperProperty.get() + .setValueForPlist(getPbxProjFile(), completeKey, value) + } + } + @TaskAction void generate() { - logger.info("Preparing archiving") + String rootKey = getValueFromPbxProjFile("rootObject") + + String buildConfigurationId = getBuildConfigurationIdentifier(findProductId(rootKey)) + + HashMap map = new HashMap<>() - outputFile.get().asFile.text = "" + map.put("CODE_SIGN_STYLE", "Manual") - append(KEY_CODE_SIGN_IDENTITY, certificateFriendlyName.get()) - append(KEY_BUNDLE_IDENTIFIER, configurationBundleIdentifier.get()) + map.put(KEY_CODE_SIGN_IDENTITY, certificateFriendlyName.get()) + map.put(KEY_BUNDLE_IDENTIFIER, configurationBundleIdentifier.get()) if (provisioningReader.present) { ProvisioningProfileReader reader = provisioningReader.get() - append(KEY_DEVELOPMENT_TEAM, reader.getTeamIdentifierPrefix()) - append(KEY_PROVISIONING_PROFILE_ID, reader.getUUID()) - append(KEY_PROVISIONING_PROFILE_SPEC, reader.getName()) + map.put(KEY_DEVELOPMENT_TEAM, reader.getTeamIdentifierPrefix()) + map.put(KEY_PROVISIONING_PROFILE_ID, reader.getUUID()) + map.put(KEY_PROVISIONING_PROFILE_SPEC, reader.getName()) } - if (entitlementsFilePath.present) { - append(KEY_CODE_SIGN_ENTITLEMENTS, entitlementsFilePath.get()) + if (entitlementsFile.present) { + map.put("CODE_SIGN_ENTITLEMENTS", entitlementsFile.get().asFile.absolutePath) + } + + map.each { k, v -> + setBuildConfigurationBuildSetting(buildConfigurationId, k, v) } } - private void append(String key, String value) { - outputFile.get() - .asFile - .append(System.getProperty("line.separator") + key + " = " + value) + private File toXml(File source) { + File file = File.createTempFile("project.plist", "") + commandRunnerProperty.get() + .run(["plutil", + "-convert", + "xml1", + source.absolutePath, + "-o", file.absolutePath]) + + return file } } diff --git a/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy b/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy index 207649e8..b68305ca 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodeBuildPluginExtension.groovy @@ -35,6 +35,8 @@ class XcodeBuildPluginExtension { final Property bitcode = project.objects.property(Boolean) final Property version = project.objects.property(String) + final Property configuration = project.objects.property(String) + final Property target = project.objects.property(String) final Property targetType = project.objects.property(Type) final Property scheme = project.objects.property(String) final DirectoryProperty archiveDirectory = project.layout.directoryProperty() @@ -52,12 +54,9 @@ class XcodeBuildPluginExtension { String infoPlist = null - String configuration = 'Debug' boolean simulator = true Type type = Type.iOS - String target - def additionalParameters = null String bundleNameSuffix = null List arch = null @@ -260,7 +259,7 @@ class XcodeBuildPluginExtension { // should be removed an replaced by the xcodebuildParameters.outputPath File getOutputPath() { - String path = getConfiguration() + String path = configuration.get() if (type != Type.macOS) { path += "-" if (type == Type.iOS) { @@ -289,7 +288,7 @@ class XcodeBuildPluginExtension { projectSettings.each { String key, BuildTargetConfiguration buildConfiguration -> - BuildConfiguration settings = buildConfiguration.buildSettings[configuration]; + BuildConfiguration settings = buildConfiguration.buildSettings[configuration.get()]; if (settings != null && settings.bundleIdentifier.equalsIgnoreCase(bundleIdentifier)) { result = settings return @@ -303,9 +302,9 @@ class XcodeBuildPluginExtension { File getApplicationBundle() { - BuildTargetConfiguration buildConfiguration = projectSettings[target] + BuildTargetConfiguration buildConfiguration = projectSettings[target.get()] if (buildConfiguration != null) { - BuildConfiguration buildSettings = buildConfiguration.buildSettings[configuration]; + BuildConfiguration buildSettings = buildConfiguration.buildSettings[configuration.get()]; if (buildSettings != null && buildSettings.sdkRoot.equalsIgnoreCase("watchos")) { BuildConfiguration parent = getParent(buildSettings) return new File(getOutputPath(), parent.productName + "." + this.productType) @@ -316,9 +315,9 @@ class XcodeBuildPluginExtension { File getBinary() { logger.debug("getBinary") - BuildTargetConfiguration buildConfiguration = projectSettings[target] + BuildTargetConfiguration buildConfiguration = projectSettings[target.get()] if (buildConfiguration != null) { - BuildConfiguration buildSettings = buildConfiguration.buildSettings[configuration]; + BuildConfiguration buildSettings = buildConfiguration.buildSettings[configuration.get()]; logger.debug("buildSettings: {}", buildSettings) if (type == Type.macOS) { return new File(getOutputPath(), buildSettings.productName + ".app/Contents/MacOS/" + buildSettings.productName) @@ -330,17 +329,17 @@ class XcodeBuildPluginExtension { BuildConfiguration getBuildConfiguration() { - BuildTargetConfiguration buildTargetConfiguration = projectSettings[target] + BuildTargetConfiguration buildTargetConfiguration = projectSettings[target.get()] if (buildTargetConfiguration != null) { - return buildTargetConfiguration.buildSettings[configuration]; + return buildTargetConfiguration.buildSettings[configuration.get()]; } - throw new IllegalStateException("No build configuration found for + target '" + parameters.target + "' and configuration '" + configuration + "'") + throw new IllegalStateException("No build configuration found for + target '" + parameters.target.get() + "' and configuration '" + configuration.get() + "'") } BuildConfiguration getBuildConfiguration(String bundleIdentifier) { BuildConfiguration result = null projectSettings.each() { target, buildTargetConfiguration -> - BuildConfiguration settings = buildTargetConfiguration.buildSettings[configuration] + BuildConfiguration settings = buildTargetConfiguration.buildSettings[configuration.get()] if (settings != null) { @@ -383,10 +382,12 @@ class XcodeBuildPluginExtension { this.simulator = simulator.toString().equalsIgnoreCase("true") || simulator.toString().equalsIgnoreCase("yes") } - void setProjectFile(def projectFile) { - if (projectFile instanceof File) { - this.projectFile = projectFile - } + void setProjectFile(File projectFile) { + assert projectFile.exists() + this.projectFile = projectFile + } + + void setProjectFile(String projectFile) { this.projectFile = new File(project.projectDir.absolutePath, projectFile) } @@ -395,12 +396,12 @@ class XcodeBuildPluginExtension { return this.projectFile } - String[] projectFiles = project.projectDir.list(new SuffixFileFilter(".xcodeproj")) + String[] projectFiles = project.rootProject.projectDir.list(new SuffixFileFilter(".xcodeproj")) if (!projectFiles || projectFiles.length < 1) { throw new FileNotFoundException("No Xcode project files were found in ${project.projectDir}") } - return new File(project.projectDir, projectFiles.first()) + return new File(project.rootProject.projectDir, projectFiles.first()) } // should be remove in the future, so that every task has its own xcode object @@ -416,11 +417,11 @@ class XcodeBuildPluginExtension { XcodebuildParameters getXcodebuildParameters() { def result = new XcodebuildParameters() result.scheme = this.scheme.getOrNull() - result.target = this.target + result.target = this.target.get() result.simulator = this.simulator result.type = this.type result.workspace = getWorkspace() - result.configuration = this.configuration + result.configuration = this.configuration.get() result.dstRoot = this.getDstRoot().asFile.getOrNull() result.objRoot = this.getObjRoot().asFile.getOrNull() result.symRoot = this.getSymRoot().asFile.getOrNull() diff --git a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy index ce142110..d0727015 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy @@ -133,7 +133,6 @@ class XcodePlugin implements Plugin { private Signing signingExtension private XcodeBuildPluginExtension xcodeBuildPluginExtension private InfoPlistExtension infoPlistExtension - private CommandRunner commandRunner private PlistHelper plistHelper private Security securityTool @@ -488,26 +487,30 @@ class XcodePlugin implements Plugin { .create(PrepareXcodeArchivingTask.NAME, PrepareXcodeArchivingTask.class) { it.group = XCODE_GROUP_NAME - it.certificateFriendlyName.set(signingExtension.certificateFriendlyName) it.commandRunnerProperty.set(commandRunner) it.configurationBundleIdentifier.set(infoPlistExtension.configurationBundleIdentifier) it.entitlementsFile.set(signingExtension.entitlementsFile) - it.outputFile.set(signingExtension.xcConfigFile) + it.projectFile.set(xcodeBuildPluginExtension.projectFile) + signingExtension.xcConfigFile.set(it.outputFile) it.plistHelperProperty.set(plistHelper) it.registeredProvisioningFiles.set(signingExtension.registeredProvisioningFiles) + + it.buildConfiguration.set(xcodeBuildPluginExtension.configuration) + it.scheme.set(xcodeBuildPluginExtension.scheme) + it.target.set(xcodeBuildPluginExtension.target) } project.getTasks().create(XcodeBuildArchiveTaskIosAndTvOS.NAME, XcodeBuildArchiveTaskIosAndTvOS.class) { it.setGroup(XCODE_GROUP_NAME) it.buildType.set(xcodeBuildPluginExtension.type) + it.buildConfiguration.set(xcodeBuildPluginExtension.configuration) it.commandRunnerProperty.set(commandRunner) it.outputArchiveFile.set(xcodeBuildPluginExtension.schemeArchiveFile) it.scheme.set(xcodeBuildPluginExtension.scheme) it.xcode.set(xcode) it.xcodeVersion.set(xcodeBuildPluginExtension.version) - it.xcConfigFile.set(signingExtension.xcConfigFile) it.xcodeServiceProperty.set(xcodeBuildPluginExtension.xcodeServiceProperty) } diff --git a/plugin/src/main/groovy/org/openbakery/XcodeProjectFile.groovy b/plugin/src/main/groovy/org/openbakery/XcodeProjectFile.groovy index ce139146..05ea6f24 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodeProjectFile.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodeProjectFile.groovy @@ -97,14 +97,13 @@ class XcodeProjectFile { throw new IllegalArgumentException("Project file does not exist: " + this.projectFile) } - if (project.xcodebuild.target == null) { + if (!project.xcodebuild.target.present) { throw new IllegalArgumentException("'xcodebuild.target' is null"); } - BuildConfiguration settings = getBuildConfiguration(project.xcodebuild.target, project.xcodebuild.configuration) + BuildConfiguration settings = getBuildConfiguration(project.xcodebuild.target.get(), project.xcodebuild.configuration.get()) logger.debug("rootObjectKey {}", rootObjectKey); - verifyTarget(project.xcodebuild.target) - + verifyTarget(project.xcodebuild.target.get()) if (StringUtils.isEmpty(project.xcodebuild.productName)) { project.xcodebuild.productName = settings.productName diff --git a/plugin/src/main/groovy/org/openbakery/archiving/XcodeBuildArchiveTaskIosAndTvOS.groovy b/plugin/src/main/groovy/org/openbakery/archiving/XcodeBuildArchiveTaskIosAndTvOS.groovy index f1ebe023..142046c2 100644 --- a/plugin/src/main/groovy/org/openbakery/archiving/XcodeBuildArchiveTaskIosAndTvOS.groovy +++ b/plugin/src/main/groovy/org/openbakery/archiving/XcodeBuildArchiveTaskIosAndTvOS.groovy @@ -5,12 +5,10 @@ import org.gradle.api.DefaultTask import org.gradle.api.Task import org.gradle.api.Transformer import org.gradle.api.file.Directory -import org.gradle.api.file.RegularFile import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.specs.Spec import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction import org.openbakery.CommandRunner @@ -33,8 +31,7 @@ class XcodeBuildArchiveTaskIosAndTvOS extends DefaultTask { @Input final Provider buildType = project.objects.property(Type) - @InputFile - final Property xcConfigFile = newInputFile() + final Provider buildConfiguration = project.objects.property(String) @OutputDirectory final Provider outputArchiveFile = newOutputDirectory() @@ -65,17 +62,17 @@ class XcodeBuildArchiveTaskIosAndTvOS extends DefaultTask { void archive() { assert scheme.present: "No target scheme configured" assert outputArchiveFile.present: "No output file folder configured" - assert xcConfigFile.present: "No 'xcconfig' file configured" + + outputArchiveFile.get().asFile.parentFile.mkdirs() logger.lifecycle("Archive project with configuration: " + "\n\tScheme : ${scheme.get()} " + "\n\tXcode version : ${xcodeVersion.getOrElse("System default")}") - Xcodebuild.archive(commandRunnerProperty.get(), scheme.get(), outputArchiveFile.get().asFile, - xcConfigFile.get().asFile, + buildConfiguration.get(), getXcodeAppForConfiguration().getOrNull()) } diff --git a/plugin/src/main/groovy/org/openbakery/coverage/CoverageTask.groovy b/plugin/src/main/groovy/org/openbakery/coverage/CoverageTask.groovy index 4c47646e..5f677228 100644 --- a/plugin/src/main/groovy/org/openbakery/coverage/CoverageTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/coverage/CoverageTask.groovy @@ -94,7 +94,7 @@ class CoverageTask extends AbstractXcodeTask { } def possibleDirectories = [ - "Build/Intermediates/CodeCoverage/" + project.xcodebuild.target + "/Coverage.profdata", + "Build/Intermediates/CodeCoverage/" + project.xcodebuild.target.get() + "/Coverage.profdata", "Build/Intermediates/CodeCoverage/Coverage.profdata" ] diff --git a/plugin/src/main/groovy/org/openbakery/cpd/CpdTask.groovy b/plugin/src/main/groovy/org/openbakery/cpd/CpdTask.groovy index 70e9d78c..2a186fad 100644 --- a/plugin/src/main/groovy/org/openbakery/cpd/CpdTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/cpd/CpdTask.groovy @@ -47,7 +47,7 @@ class CpdTask extends AbstractXcodeTask { "-cp", "\"${cp.join(':')}\"", 'net.sourceforge.pmd.cpd.CPD', "--minimum-tokens", "10", - "--files", "${projectDir.absolutePath}/${xcodebuild.target}", "${projectDir.absolutePath}/${xcodebuild.target}Tests", + "--files", "${projectDir.absolutePath}/${xcodebuild.target.get()}", "${projectDir.absolutePath}/${xcodebuild.target}Tests", "--language", "ObjectiveC", "--encoding", "UTF-8", "--format", "net.sourceforge.pmd.cpd.XMLRenderer" diff --git a/plugin/src/main/groovy/org/openbakery/extension/Signing.groovy b/plugin/src/main/groovy/org/openbakery/extension/Signing.groovy index 6d93319a..a3847149 100644 --- a/plugin/src/main/groovy/org/openbakery/extension/Signing.groovy +++ b/plugin/src/main/groovy/org/openbakery/extension/Signing.groovy @@ -11,7 +11,6 @@ import org.openbakery.CommandRunner import org.openbakery.codesign.CodesignParameters import org.openbakery.signing.ProvisioningFile import org.openbakery.signing.SigningMethod -import org.openbakery.util.PathHelper import javax.inject.Inject @@ -69,10 +68,6 @@ class Signing { + System.currentTimeMillis() + ".keychain")) this.timeout.set(3600) - - this.xcConfigFile.set(project.layout - .buildDirectory - .file(PathHelper.FOLDER_ARCHIVE + "/" + PathHelper.GENERATED_XCARCHIVE_FILE_NAME)) } void setKeychain(Object keychain) { @@ -82,7 +77,8 @@ class Signing { this.keychain.set(project.file(keychain)) } - public void setMethod(String method) { + void setMethod(String method) { + println "setMethod : " + method signingMethod.set(SigningMethod.fromString(method) .orElseThrow { new IllegalArgumentException("Method : $method is not a valid export method") @@ -145,7 +141,7 @@ class Signing { } @Override - public String toString() { + String toString() { if (this.keychain != null) { return "Signing{" + " identity='" + identity + '\'' + diff --git a/plugin/src/main/groovy/org/openbakery/signing/ProvisioningInstallTask.groovy b/plugin/src/main/groovy/org/openbakery/signing/ProvisioningInstallTask.groovy index 92d913fb..ab71ba10 100644 --- a/plugin/src/main/groovy/org/openbakery/signing/ProvisioningInstallTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/signing/ProvisioningInstallTask.groovy @@ -43,7 +43,9 @@ class ProvisioningInstallTask extends Download { super() this.description = TASK_DESCRIPTION - this.onlyIf { !mobileProvisioningList.get().empty } + this.onlyIf { + !mobileProvisioningList.get().empty + } } @TaskAction diff --git a/plugin/src/main/groovy/org/openbakery/signing/SigningMethod.groovy b/plugin/src/main/groovy/org/openbakery/signing/SigningMethod.groovy index 307710f1..94efc93c 100644 --- a/plugin/src/main/groovy/org/openbakery/signing/SigningMethod.groovy +++ b/plugin/src/main/groovy/org/openbakery/signing/SigningMethod.groovy @@ -20,6 +20,7 @@ enum SigningMethod { } static Optional fromString(value) { + println "fromString : " + value return Optional.ofNullable(values().find { it.getValue() == value }) } } diff --git a/plugin/src/main/groovy/org/openbakery/util/VariableResolver.groovy b/plugin/src/main/groovy/org/openbakery/util/VariableResolver.groovy index 895a0881..5111dbae 100644 --- a/plugin/src/main/groovy/org/openbakery/util/VariableResolver.groovy +++ b/plugin/src/main/groovy/org/openbakery/util/VariableResolver.groovy @@ -57,7 +57,7 @@ class VariableResolver { return [ "PRODUCT_NAME": project.xcodebuild.productName, "SRC_ROOT" : project.projectDir.absolutePath, - "TARGET_NAME" : project.xcodebuild.target + "TARGET_NAME" : project.xcodebuild.target.get() ] } -} \ No newline at end of file +} From 07f9a82de70b046a2e970930985c789304cc6156 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Mon, 4 Jun 2018 16:31:26 +0100 Subject: [PATCH 09/16] --wip-- [skip ci] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d403b2a7..20e207be 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ apply plugin: "org.ajoberstar.reckon" reckon { scopeFromProp() - stageFromProp('snapshot', 'rc', 'final') + stageFromProp('dev', 'snapshot', 'rc', 'final') } reckonTagCreate.dependsOn 'check' From 426d56a42abbfaa5e1a592787e0d05560755c276 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Mon, 4 Jun 2018 16:33:38 +0100 Subject: [PATCH 10/16] Tweak versioning --- build.gradle | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/build.gradle b/build.gradle index 20e207be..89610554 100644 --- a/build.gradle +++ b/build.gradle @@ -1,22 +1,11 @@ buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - } + repositories { jcenter() } dependencies { - classpath "org.ajoberstar.reckon:reckon-gradle:0.7.0" + classpath 'com.netflix.nebula:nebula-release-plugin:6.0.0' } } +apply plugin: 'nebula.release' -apply plugin: "org.ajoberstar.reckon" - -reckon { - scopeFromProp() - stageFromProp('dev', 'snapshot', 'rc', 'final') -} - -reckonTagCreate.dependsOn 'check' // @@ -38,7 +27,7 @@ allprojects { // group = 'org.openbakery' - version = project.version + version = project.version.toString() sourceCompatibility = "1.6" targetCompatibility = "1.6" From 92d5a95a3ceca1556d626904d3e4da5296849905 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Tue, 5 Jun 2018 08:34:45 +0100 Subject: [PATCH 11/16] Add reckon back --- build.gradle | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 89610554..ea90633f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,22 @@ buildscript { - repositories { jcenter() } + repositories { + maven { + url "https://plugins.gradle.org/m2/" + } + } dependencies { - classpath 'com.netflix.nebula:nebula-release-plugin:6.0.0' + classpath "org.ajoberstar.reckon:reckon-gradle:0.7.0" } } -apply plugin: 'nebula.release' +apply plugin: "org.ajoberstar.reckon" + +reckon { + scopeFromProp() + stageFromProp('dev', 'rc', 'final') +} + +reckonTagCreate.dependsOn 'check' // @@ -27,7 +38,7 @@ allprojects { // group = 'org.openbakery' - version = project.version.toString() + version = project.version sourceCompatibility = "1.6" targetCompatibility = "1.6" From 1b4f70ce236e09047a9002ef7f60cc28988baddc Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Tue, 5 Jun 2018 08:38:48 +0100 Subject: [PATCH 12/16] Add SNAPSHOT suffix --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ea90633f..e2e1d878 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ allprojects { // group = 'org.openbakery' - version = project.version + version = project.version.toString() + "-SNAPSHOT" sourceCompatibility = "1.6" targetCompatibility = "1.6" From 42bb84e3c559072f774729bbdd2d91e315b30f3c Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Tue, 5 Jun 2018 15:00:20 +0100 Subject: [PATCH 13/16] Temp fix --- .../main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy b/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy index e75ca53a..d812e2c2 100644 --- a/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy +++ b/plugin/src/main/groovy/org/openbakery/PrepareXcodeArchivingTask.groovy @@ -151,6 +151,7 @@ class PrepareXcodeArchivingTask extends DefaultTask { map.put("CODE_SIGN_STYLE", "Manual") map.put(KEY_CODE_SIGN_IDENTITY, certificateFriendlyName.get()) + map.put("CODE_SIGN_IDENTITY[sdk=iphoneos*]", certificateFriendlyName.get()) map.put(KEY_BUNDLE_IDENTIFIER, configurationBundleIdentifier.get()) if (provisioningReader.present) { From 1dd6bff7c7308fff02566618a4a52d8bc76b4860 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Tue, 5 Jun 2018 15:54:30 +0100 Subject: [PATCH 14/16] Make the packaging xcode version dependant too --- .../org/openbakery/xcode/Xcodebuild.groovy | 26 ++++++++++-------- .../groovy/org/openbakery/XcodePlugin.groovy | 2 ++ .../packaging/PackageTaskIosAndTvOS.groovy | 27 ++++++++++++++++++- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy b/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy index 4d2a9f43..dc6a1243 100644 --- a/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy +++ b/libxcode/src/main/groovy/org/openbakery/xcode/Xcodebuild.groovy @@ -50,17 +50,26 @@ class Xcodebuild { static void packageIpa(CommandRunner commandRunner, File archivePath, File exportPath, - File exportOptionsPlist) { + File exportOptionsPlist, + @Nullable File xcodeApp) { assert archivePath != null && archivePath.exists() assert exportPath != null && exportPath.exists() assert exportOptionsPlist != null && exportOptionsPlist.exists() - commandRunner.run(EXECUTABLE, - ACTION_EXPORT_ARCHIVE, - ARGUMENT_ARCHIVE_PATH, archivePath.absolutePath, - ARGUMENT_EXPORT_PATH, exportPath.absolutePath, - ARGUMENT_EXPORT_OPTIONS_PLIST, exportOptionsPlist.absolutePath) + // Env value + HashMap envMap = new HashMap<>() + if (xcodeApp != null) { + envMap.put(Xcode.ENV_DEVELOPER_DIR, xcodeApp.absolutePath) + } + + List args = [EXECUTABLE, + ACTION_EXPORT_ARCHIVE, + ARGUMENT_ARCHIVE_PATH, archivePath.absolutePath, + ARGUMENT_EXPORT_PATH, exportPath.absolutePath, + ARGUMENT_EXPORT_OPTIONS_PLIST, exportOptionsPlist.absolutePath] + + commandRunner.run(args, envMap) } static void archive(CommandRunner commandRunner, @@ -82,11 +91,6 @@ class Xcodebuild { "-configuration", configuration, ARGUMENT_ARCHIVE_PATH, outputPath.absolutePath] -// if (xcConfig != null) { -// args.push(ARGUMENT_XCCONFIG) -// args.push(xcConfig.absolutePath) -// } - commandRunner.run(args, envMap) } diff --git a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy index d0727015..24e2e2db 100644 --- a/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy +++ b/plugin/src/main/groovy/org/openbakery/XcodePlugin.groovy @@ -499,6 +499,8 @@ class XcodePlugin implements Plugin { it.buildConfiguration.set(xcodeBuildPluginExtension.configuration) it.scheme.set(xcodeBuildPluginExtension.scheme) it.target.set(xcodeBuildPluginExtension.target) + it.xcodeVersion.set(xcodeBuildPluginExtension.version) + it.xcodeServiceProperty.set(xcodeBuildPluginExtension.xcodeServiceProperty) } project.getTasks().create(XcodeBuildArchiveTaskIosAndTvOS.NAME, diff --git a/plugin/src/main/groovy/org/openbakery/packaging/PackageTaskIosAndTvOS.groovy b/plugin/src/main/groovy/org/openbakery/packaging/PackageTaskIosAndTvOS.groovy index 5f13fdc6..320f5fef 100644 --- a/plugin/src/main/groovy/org/openbakery/packaging/PackageTaskIosAndTvOS.groovy +++ b/plugin/src/main/groovy/org/openbakery/packaging/PackageTaskIosAndTvOS.groovy @@ -4,12 +4,14 @@ import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode import org.gradle.api.DefaultTask import org.gradle.api.Task +import org.gradle.api.Transformer import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.openbakery.CommandRunner import org.openbakery.XcodePlugin +import org.openbakery.XcodeService import org.openbakery.signing.KeychainCreateTask import org.openbakery.signing.ProvisioningFile import org.openbakery.signing.ProvisioningInstallTask @@ -22,6 +24,9 @@ import org.openbakery.xcode.Xcodebuild @CompileStatic class PackageTaskIosAndTvOS extends DefaultTask { + @Input + final Provider xcodeVersion = project.objects.property(String) + @Input public final Property signingMethod = project.objects.property(SigningMethod) @@ -42,6 +47,8 @@ class PackageTaskIosAndTvOS extends DefaultTask { final Provider commandRunner = project.objects.property(CommandRunner) final Provider plistHelper = project.objects.property(PlistHelper) + final Property xcodeServiceProperty = project.objects.property(XcodeService) + public static final String DESCRIPTION = "Package the archive with Xcode-build" public static final String NAME = "packageWithXcodeBuild" @@ -162,6 +169,24 @@ class PackageTaskIosAndTvOS extends DefaultTask { Xcodebuild.packageIpa(commandRunner.get(), getArchiveFile(), getOutputDirectory(), - getExportOptionsPlistFile()) + getExportOptionsPlistFile(), + getXcodeAppForConfiguration().getOrNull()) + } + + private Provider getXcodeAppForConfiguration() { + + Provider xcodeApp + if (xcodeVersion.present) { + xcodeApp = xcodeServiceProperty.map(new Transformer() { + @Override + File transform(XcodeService xcodeService) { + XcodeService.XcodeApp app = xcodeService.getInstallationForVersion(xcodeVersion.get()) + return app.contentDeveloperFile + } + }) + } else { + xcodeApp = project.objects.property(File) + } + return xcodeApp } } From bc11e1714f6ba08f26aa97edb2901d49cc227003 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Tue, 5 Jun 2018 16:02:06 +0100 Subject: [PATCH 15/16] Cleanup --- build.gradle | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/build.gradle b/build.gradle index e2e1d878..1404de0f 100644 --- a/build.gradle +++ b/build.gradle @@ -23,19 +23,6 @@ reckonTagCreate.dependsOn 'check' allprojects { apply plugin: 'java-gradle-plugin' apply plugin: 'groovy' -// -// def versionNumber = "0.16.0.a603076-SNAPSHOT" -// -// if (project.hasProperty("versionNumber")) { -// versionNumber = project.versionNumber -// } -// if (project.hasProperty("versionSuffix")) { -// versionNumber += project.versionSuffix -// } -// if (project.hasProperty("buildNumber")) { -// versionNumber += "." + project.buildNumber -// } -// group = 'org.openbakery' version = project.version.toString() + "-SNAPSHOT" From 587039a424e669a232ced0f8e77087d6cae50262 Mon Sep 17 00:00:00 2001 From: Johann Martinache Date: Tue, 5 Jun 2018 16:05:35 +0100 Subject: [PATCH 16/16] Switch versioning to nebula.release more simple and reliable --- build.gradle | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 1404de0f..0fe87927 100644 --- a/build.gradle +++ b/build.gradle @@ -1,23 +1,7 @@ -buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - } - dependencies { - classpath "org.ajoberstar.reckon:reckon-gradle:0.7.0" - } +plugins { + id 'nebula.release' version '6.0.0' } -apply plugin: "org.ajoberstar.reckon" - -reckon { - scopeFromProp() - stageFromProp('dev', 'rc', 'final') -} - -reckonTagCreate.dependsOn 'check' - // allprojects {