-
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 expirimental support for app center publish (#6)
Description =========== > On November 16, 2019, HockeyApp will transition fully to App Center. This patch adds a new task type `AppCenterUploadTask` which works similar to the old `HockeyUploadTask`. The new task allows to upload a binary (`ipa`,`apk`) to a appcenter app. The configuration looks as follows: ```groovy publishAppCenter { owner = "" apiToken = "" applicationIdentifier = "" binary = File destination "", "" buildInfo { branchName = "" commitHash = "" commitMessage = "" } } ``` > the API is not yet stable! Properties ---------- | name | type | description | required | | --------------------- | -------------- | ----------- | -------- | | owner | String | app center user/owner | yes | | applicationIdentifier | String | app center application name | yes | | apiToken | String | app center api token with write access to specified `owner/applicationIdentifier` | yes | | binary | String or File | file path to binary for upload | destination | - | this is a method which either accepts a list of strings or variadic argument list of strings | no | buildInfo | - | this is a configuration method which can be called with a closure to configure optional build informations | no Changes ======= ![ADD] ![NEW] task type `AppCenterUploadTask`
- Loading branch information
Showing
5 changed files
with
639 additions
and
7 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
234 changes: 234 additions & 0 deletions
234
...ntegrationTest/groovy/wooga/gradle/hockey/tasks/AppCenterUploadTaskIntegrationSpec.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,234 @@ | ||
/* | ||
* Copyright 2019 Wooga GmbH | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
*/ | ||
|
||
package wooga.gradle.hockey.tasks | ||
|
||
import groovy.json.JsonOutput | ||
import groovy.json.JsonSlurper | ||
import org.apache.http.HttpResponse | ||
import org.apache.http.client.HttpClient | ||
import org.apache.http.client.methods.HttpGet | ||
import org.apache.http.client.methods.HttpPost | ||
import org.apache.http.client.methods.HttpDelete | ||
import org.apache.http.entity.ContentType | ||
import org.apache.http.entity.StringEntity | ||
import org.apache.http.impl.client.HttpClientBuilder | ||
import wooga.gradle.hockey.HockeyPlugin | ||
import wooga.gradle.hockey.IntegrationSpec | ||
|
||
class AppCenterUploadTaskIntegrationSpec extends IntegrationSpec { | ||
static String apiToken = System.env["ATLAS_APP_CENTER_INTEGRATION_API_TOKEN"] | ||
static String owner = System.env["ATLAS_APP_CENTER_OWNER"] | ||
static String applicationIdentifier = System.env["ATLAS_APP_CENTER_INTEGRATION_APPLICATION_IDENTIFIER"] | ||
|
||
def setup() { | ||
buildFile << """ | ||
version = "0.1.0" | ||
${applyPlugin(HockeyPlugin)} | ||
publishAppCenter { | ||
owner = "$owner" | ||
apiToken = "$apiToken" | ||
applicationIdentifier = "$applicationIdentifier" | ||
} | ||
""".stripIndent() | ||
} | ||
|
||
def "uploads dummy ipa to AppCenter successfully"() { | ||
given: "a dummy ipa binary to upload" | ||
|
||
def testFile = getClass().getClassLoader().getResource("test.ipa").path | ||
buildFile << """ | ||
publishAppCenter.binary = "$testFile" | ||
""".stripIndent() | ||
|
||
expect: | ||
runTasksSuccessfully("publishAppCenter") | ||
} | ||
|
||
def "writes json file with uploaded version meta data"() { | ||
given: "a dummy ipa binary to upload" | ||
def testFile = getClass().getClassLoader().getResource("test.ipa").path | ||
buildFile << """ | ||
publishAppCenter.binary = "$testFile" | ||
""".stripIndent() | ||
|
||
and: "a future version meta file" | ||
def versionMeta = new File(projectDir,"build/tmp/publishAppCenter/${owner}_${applicationIdentifier}.json") | ||
assert !versionMeta.exists() | ||
|
||
when: | ||
runTasksSuccessfully("publishAppCenter") | ||
|
||
then: | ||
versionMeta.exists() | ||
} | ||
|
||
def "publishes to Collaborators group when no groups are configured"() { | ||
given: "a dummy ipa binary to upload" | ||
def testFile = getClass().getClassLoader().getResource("test.ipa").path | ||
buildFile << """ | ||
publishAppCenter.binary = "$testFile" | ||
""".stripIndent() | ||
|
||
and: "a future version meta file" | ||
def versionMeta = new File(projectDir,"build/tmp/publishAppCenter/${owner}_${applicationIdentifier}.json") | ||
assert !versionMeta.exists() | ||
|
||
and: "no configured distribution groups" | ||
|
||
when: | ||
runTasksSuccessfully("publishAppCenter") | ||
|
||
then: | ||
def release = getRelease(versionMeta) | ||
def destinations = release["destinations"] | ||
destinations.any {it["name"] == "Collaborators"} | ||
} | ||
|
||
def "can publish to custom distribution groups"() { | ||
given: "a new distribution group" | ||
ensureDistributionGroup("Test") | ||
ensureDistributionGroup("Test2") | ||
|
||
buildFile << """ | ||
publishAppCenter.destination "Test", "Test2" | ||
""".stripIndent() | ||
|
||
and: "a dummy ipa binary to upload" | ||
def testFile = getClass().getClassLoader().getResource("test.ipa").path | ||
buildFile << """ | ||
publishAppCenter.binary = "$testFile" | ||
""".stripIndent() | ||
|
||
and: "a future version meta file" | ||
def versionMeta = new File(projectDir,"build/tmp/publishAppCenter/${owner}_${applicationIdentifier}.json") | ||
assert !versionMeta.exists() | ||
|
||
when: | ||
runTasksSuccessfully("publishAppCenter") | ||
|
||
then: | ||
def release = getRelease(versionMeta) | ||
def destinations = release["destinations"] | ||
destinations.any {it["name"] == "Test" || it["name"] == "Test2"} | ||
!destinations.any {it["name"] == "Collaborators"} | ||
} | ||
|
||
def "fails when distribution group is invalid"() { | ||
given: "a publish task with invalid distribution groups" | ||
buildFile << """ | ||
publishAppCenter.destination "some value", "some other group" | ||
""".stripIndent() | ||
|
||
and: "a dummy ipa binary to upload" | ||
def testFile = getClass().getClassLoader().getResource("test.ipa").path | ||
buildFile << """ | ||
publishAppCenter.binary = "$testFile" | ||
""".stripIndent() | ||
|
||
expect: | ||
runTasksWithFailure("publishAppCenter") | ||
} | ||
|
||
def "can publish custom build infos"() { | ||
given: "publish task with build infos" | ||
buildFile << """ | ||
publishAppCenter.buildInfo { | ||
branchName = "master" | ||
commitHash = "000000000000" | ||
commitMessage = "Fix tests" | ||
} | ||
""".stripIndent() | ||
|
||
and: "a dummy ipa binary to upload" | ||
def testFile = getClass().getClassLoader().getResource("test.ipa").path | ||
buildFile << """ | ||
publishAppCenter.binary = "$testFile" | ||
""".stripIndent() | ||
|
||
and: "a future version meta file" | ||
def versionMeta = new File(projectDir,"build/tmp/publishAppCenter/${owner}_${applicationIdentifier}.json") | ||
assert !versionMeta.exists() | ||
|
||
when: | ||
runTasksSuccessfully("publishAppCenter") | ||
|
||
then: | ||
versionMeta.exists() | ||
def jsonSlurper = new JsonSlurper() | ||
def releaseMeta = jsonSlurper.parse(versionMeta) | ||
|
||
def releaseId = releaseMeta["release_id"] | ||
def release = getRelease(releaseId) | ||
|
||
def buildInfo = release["build"] | ||
buildInfo["branch_name"] == "master" | ||
buildInfo["commit_hash"] == "000000000000" | ||
buildInfo["commit_message"] == "Fix tests" | ||
} | ||
|
||
void deleteDistributionGroup(String name) { | ||
HttpClient client = HttpClientBuilder.create().build() | ||
HttpDelete request = new HttpDelete("https://api.appcenter.ms/v0.1/apps/${owner}/${applicationIdentifier}/distribution_groups/${URLEncoder.encode(name,"UTF-8")}") | ||
|
||
request.setHeader("Accept", 'application/json') | ||
request.setHeader("X-API-Token", apiToken) | ||
|
||
HttpResponse response = client.execute(request) | ||
|
||
if (response.statusLine.statusCode != 204) { | ||
throw new Exception("Failed to delete distribution group") | ||
} | ||
} | ||
|
||
void ensureDistributionGroup(String name) { | ||
HttpClient client = HttpClientBuilder.create().build() | ||
HttpPost request = new HttpPost("https://api.appcenter.ms/v0.1/apps/${owner}/${applicationIdentifier}/distribution_groups") | ||
|
||
request.setHeader("Accept", 'application/json') | ||
request.setHeader("X-API-Token", apiToken) | ||
|
||
def body = ["name": name] | ||
request.setEntity(new StringEntity(JsonOutput.toJson(body), ContentType.APPLICATION_JSON)) | ||
|
||
HttpResponse response = client.execute(request) | ||
|
||
if (response.statusLine.statusCode != 201 && response.statusLine.statusCode != 409) { | ||
throw new Exception("Failed to create distribution group") | ||
} | ||
} | ||
|
||
Map getRelease(File versionMeta) { | ||
def jsonSlurper = new JsonSlurper() | ||
def releaseMeta = jsonSlurper.parse(versionMeta) | ||
|
||
String releaseId = releaseMeta["release_id"] | ||
getRelease(releaseId) | ||
} | ||
|
||
Map getRelease(String releaseId) { | ||
HttpClient client = HttpClientBuilder.create().build() | ||
HttpGet request = new HttpGet("https://api.appcenter.ms/v0.1/apps/${owner}/${applicationIdentifier}/releases/${releaseId}") | ||
|
||
request.setHeader("Accept", 'application/json') | ||
request.setHeader("X-API-Token", apiToken) | ||
|
||
HttpResponse response = client.execute(request) | ||
def jsonSlurper = new JsonSlurper() | ||
jsonSlurper.parseText(response.entity.content.text) as Map | ||
} | ||
} |
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
33 changes: 33 additions & 0 deletions
33
src/main/groovy/wooga/gradle/hockey/api/AppCenterBuildInfo.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,33 @@ | ||
/* | ||
* Copyright 2019 Wooga GmbH | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
*/ | ||
|
||
package wooga.gradle.hockey.api | ||
|
||
import org.gradle.api.tasks.Input | ||
import org.gradle.api.tasks.Optional | ||
|
||
class AppCenterBuildInfo { | ||
@Input | ||
@Optional | ||
String branchName | ||
@Input | ||
@Optional | ||
String commitHash | ||
@Input | ||
@Optional | ||
String commitMessage | ||
} |
Oops, something went wrong.