-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add discrete install provisioning profile task (#5)
Add discrete install profile task Description =========== We use fastlane at the moment to import provisional and install provisioning profiles. The install part is indirect because fastlane itself does it for us under the hood. This worked for us very well over the years. But there is no real chance to install profiles in any other way. Hence a discrete install profile task. To be able to install provisioning profiles one needs to be able to read the UUID out of the included meta data. The reason is that all profiles are stored on the system with the UUID as the file name. I created a new helper class + test mock class to read provisioning profiles and fetch the metadata from them. A profile consists of 3 pieces: 1. A header (some bytes long) I have no information what information is stored there 2. The meta data in plist format 3. a series of certificates (unknown format) We are mainly interested in the meta data. I removed the import provisioning profiles task from the direct task dependency list. Instead the new task `installProvisioningProfiles` will be used in it's place. This new task will have a dependency (_indirect_) to the `importProvisioningProfiles` task. This means that one could reconfigure the `importProvisioningProfiles` tasks and skip the fastlane backed task `importProvisioningProfiles` all together. This is needed for out new alternative flow where we store the profiles in the aws secrets manager. Changes ======= * ![ADD] `InstallProvisioningProfiles` task type
- Loading branch information
Showing
12 changed files
with
829 additions
and
237 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
423 changes: 216 additions & 207 deletions
423
src/integrationTest/groovy/wooga/gradle/build/unity/ios/IOSBuildPluginIntegrationSpec.groovy
Large diffs are not rendered by default.
Oops, something went wrong.
13 changes: 13 additions & 0 deletions
13
...egrationTest/groovy/wooga/gradle/build/unity/ios/tasks/IOSBuildTaskIntegrationSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package wooga.gradle.build.unity.ios.tasks | ||
|
||
import com.wooga.gradle.test.TaskIntegrationSpec | ||
import org.gradle.api.Task | ||
import wooga.gradle.build.unity.ios.IOSBuildIntegrationSpec | ||
|
||
abstract class IOSBuildTaskIntegrationSpec<T extends Task> extends IOSBuildIntegrationSpec implements TaskIntegrationSpec<T> { | ||
def setup() { | ||
buildFile << """ | ||
task ${subjectUnderTestName}(type: ${subjectUnderTestTypeName}) | ||
""".stripIndent() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
...oovy/wooga/gradle/build/unity/ios/tasks/InstallProvisioningProfilesIntegrationSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package wooga.gradle.build.unity.ios.tasks | ||
|
||
import com.wooga.gradle.PlatformUtils | ||
import com.wooga.gradle.test.PropertyQueryTaskWriter | ||
import com.wooga.gradle.test.ios.MobileProvisionMock | ||
import spock.lang.Requires | ||
import spock.lang.Unroll | ||
|
||
import static com.wooga.gradle.test.PropertyUtils.toProviderSet | ||
import static com.wooga.gradle.test.PropertyUtils.toSetter | ||
|
||
class InstallProvisioningProfilesIntegrationSpec extends IOSBuildTaskIntegrationSpec<InstallProvisionProfiles> { | ||
|
||
@Requires({ PlatformUtils.mac }) | ||
@Unroll("can set property #property with #method and type #type") | ||
def "can set property"() { | ||
given: "a task to read back the value" | ||
def query = new PropertyQueryTaskWriter("${subjectUnderTestName}.${property}") | ||
query.write(buildFile) | ||
|
||
and: "a set property" | ||
appendToSubjectTask("${method}($value)") | ||
|
||
when: | ||
def result = runTasksSuccessfully(query.taskName) | ||
|
||
then: | ||
query.matches(result, expectedValue) | ||
|
||
where: | ||
property | method | rawValue | returnValue | type | ||
"outputDirectory" | property | "/path/to/outputDir" | _ | "File" | ||
"outputDirectory" | property | "/path/to/outputDir" | _ | "Provider<Directory>" | ||
"outputDirectory" | toProviderSet(property) | "/path/to/outputDir" | _ | "File" | ||
"outputDirectory" | toProviderSet(property) | "/path/to/outputDir" | _ | "Provider<Directory>" | ||
"outputDirectory" | toSetter(property) | "/path/to/outputDir" | _ | "File" | ||
"outputDirectory" | toSetter(property) | "/path/to/outputDir" | _ | "Provider<Directory>" | ||
|
||
"logFile" | property | "/path/to/log" | _ | "File" | ||
"logFile" | property | "/path/to/log" | _ | "Provider<RegularFile>" | ||
"logFile" | toProviderSet(property) | "/path/to/log" | _ | "File" | ||
"logFile" | toProviderSet(property) | "/path/to/log" | _ | "Provider<RegularFile>" | ||
"logFile" | toSetter(property) | "/path/to/log" | _ | "File" | ||
"logFile" | toSetter(property) | "/path/to/log" | _ | "Provider<RegularFile>" | ||
|
||
"logToStdout" | toProviderSet(property) | true | _ | "Boolean" | ||
"logToStdout" | toProviderSet(property) | true | _ | "Provider<Boolean>" | ||
"logToStdout" | toSetter(property) | true | _ | "Boolean" | ||
"logToStdout" | toSetter(property) | true | _ | "Provider<Boolean>" | ||
value = wrapValueBasedOnType(rawValue, type, wrapValueFallback) | ||
expectedValue = returnValue == _ ? rawValue : returnValue | ||
} | ||
|
||
def "installs provided provisioning profiles to the output directory"() { | ||
given: "a mock mobile provisioning file with a known uuid" | ||
def files = uuids.collect { UUID id -> | ||
def mock = MobileProvisionMock.createMock({ | ||
it.uuid = id | ||
}) | ||
def installedProfile = new File(projectDir, "build/profiles/${id}.mobileprovision") | ||
new Tuple2<File, File>(mock, installedProfile) | ||
} | ||
|
||
and: "a future provisioning profile location" | ||
assert !files.any { it.second.exists() } | ||
|
||
and: | ||
appendToSubjectTask(""" | ||
provisioningProfiles.from(${wrapValueBasedOnType(files.collect { it.first }, "List<File>")}) | ||
outputDirectory = ${wrapValueBasedOnType(new File(projectDir, "build/profiles"), "File")} | ||
""".stripIndent()) | ||
|
||
when: | ||
runTasksSuccessfully(subjectUnderTestName) | ||
|
||
then: | ||
files.every { it.second.exists() } | ||
files.every { | ||
def mockBytes = it.first.bytes | ||
def profileBytes = it.second.bytes | ||
mockBytes == profileBytes | ||
} | ||
|
||
where: | ||
uuids = [UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()] | ||
} | ||
|
||
def "writes log to logfile and stdout when configured"() { | ||
given: "a mock mobile provisioning file with a known uuid" | ||
def files = uuids.collect { UUID id -> | ||
def mock = MobileProvisionMock.createMock({ | ||
it.uuid = id | ||
}) | ||
def installedProfile = new File(projectDir, "build/profiles/${id}.mobileprovision") | ||
new Tuple2<File, File>(mock, installedProfile) | ||
} | ||
|
||
and: "a future logfile" | ||
def logFile = new File(projectDir, logFilePath) | ||
assert !logFile.exists() | ||
|
||
and: | ||
appendToSubjectTask(""" | ||
provisioningProfiles.from(${wrapValueBasedOnType(files.collect { it.first }, "List<File>")}) | ||
outputDirectory = ${wrapValueBasedOnType(new File(projectDir, "build/profiles"), "File")} | ||
logFile = ${wrapValueBasedOnType(logFile, "File")} | ||
logToStdout = ${wrapValueBasedOnType(logToStdout, "Boolean")} | ||
""".stripIndent()) | ||
|
||
when: | ||
def result = runTasksSuccessfully(subjectUnderTestName) | ||
|
||
then: | ||
logFile.exists() | ||
logFile.text.contains("Install Profiles: ${uuids.size()}") | ||
result.standardOutput.contains(logFile.text) == logToStdout | ||
|
||
where: | ||
uuids = [UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()] | ||
logFilePath = osPath("build/logs/custom.log") | ||
logToStdout << [true, false] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
src/main/groovy/wooga/gradle/build/unity/ios/MobileProvisioning.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package wooga.gradle.build.unity.ios | ||
|
||
trait MobileProvisioning { | ||
abstract String getName() | ||
|
||
abstract String getAppIdName() | ||
|
||
abstract String getUuid() | ||
|
||
abstract String getTeamName() | ||
|
||
abstract List<String> getTeamIdentifier() | ||
|
||
abstract Date getExpirationDate() | ||
|
||
abstract Date getCreationDate() | ||
|
||
abstract Boolean isExpired() | ||
|
||
abstract Integer getTimeToLive() | ||
|
||
abstract Boolean isXcodeManaged() | ||
|
||
abstract Integer getVersion() | ||
|
||
abstract Map getEntitlements() | ||
|
||
boolean equals(MobileProvisioning o) { | ||
if (this.is(o)) return true | ||
|
||
if (!(o instanceof MobileProvisioning)) { | ||
return false | ||
} | ||
|
||
MobileProvisioning that = (MobileProvisioning) o | ||
|
||
if (appIdName != that.appIdName) return false | ||
if (creationDate != that.creationDate) return false | ||
if (entitlements != that.entitlements) return false | ||
if (expirationDate != that.expirationDate) return false | ||
if (name != that.name) return false | ||
if (teamIdentifier != that.teamIdentifier) return false | ||
if (teamName != that.teamName) return false | ||
if (timeToLive != that.timeToLive) return false | ||
if (uuid != that.uuid) return false | ||
if (version != that.version) return false | ||
if (xcodeManaged != that.xcodeManaged) return false | ||
|
||
return true | ||
} | ||
|
||
int hashCode() { | ||
int result | ||
result = (uuid != null ? uuid.hashCode() : 0) | ||
result = 31 * result + (appIdName != null ? appIdName.hashCode() : 0) | ||
result = 31 * result + (name != null ? name.hashCode() : 0) | ||
result = 31 * result + (teamIdentifier != null ? teamIdentifier.hashCode() : 0) | ||
result = 31 * result + (teamName != null ? teamName.hashCode() : 0) | ||
result = 31 * result + (timeToLive != null ? timeToLive.hashCode() : 0) | ||
result = 31 * result + (version != null ? version.hashCode() : 0) | ||
result = 31 * result + (creationDate != null ? creationDate.hashCode() : 0) | ||
result = 31 * result + (expirationDate != null ? expirationDate.hashCode() : 0) | ||
result = 31 * result + (xcodeManaged != null ? xcodeManaged.hashCode() : 0) | ||
result = 31 * result + (entitlements != null ? entitlements.hashCode() : 0) | ||
return result | ||
} | ||
} |
Oops, something went wrong.