diff --git a/.idea/libraries/kobalt__Compile_.xml b/.idea/libraries/kobalt__Compile_.xml index 5fd82a6b..f8a31249 100644 --- a/.idea/libraries/kobalt__Compile_.xml +++ b/.idea/libraries/kobalt__Compile_.xml @@ -12,9 +12,9 @@ - - + + diff --git a/.idea/libraries/kobalt__Test_.xml b/.idea/libraries/kobalt__Test_.xml index 9623dfb9..f9386500 100644 --- a/.idea/libraries/kobalt__Test_.xml +++ b/.idea/libraries/kobalt__Test_.xml @@ -1,14 +1,9 @@ - - - - - - + diff --git a/.idea/libraries/kobalt_jar.xml b/.idea/libraries/kobalt_jar.xml index 47bf75af..615f664d 100644 --- a/.idea/libraries/kobalt_jar.xml +++ b/.idea/libraries/kobalt_jar.xml @@ -1,7 +1,7 @@ - + diff --git a/.idea/libraries/kobalt_plugin_api__Compile_.xml b/.idea/libraries/kobalt_plugin_api__Compile_.xml index 14febb5c..50404fdc 100644 --- a/.idea/libraries/kobalt_plugin_api__Compile_.xml +++ b/.idea/libraries/kobalt_plugin_api__Compile_.xml @@ -3,18 +3,21 @@ - + + - + + - + + diff --git a/.idea/libraries/kobalt_plugin_api__Test_.xml b/.idea/libraries/kobalt_plugin_api__Test_.xml index 43ee40b8..18b8b5ed 100644 --- a/.idea/libraries/kobalt_plugin_api__Test_.xml +++ b/.idea/libraries/kobalt_plugin_api__Test_.xml @@ -1,15 +1,6 @@ - - - - - - - - - - + diff --git a/kobalt.iml b/kobalt.iml index 9c85fa5d..9510060e 100644 --- a/kobalt.iml +++ b/kobalt.iml @@ -7,6 +7,7 @@ + diff --git a/kobalt/src/Build.kt b/kobalt/src/Build.kt index ee96794f..a7d19ad6 100644 --- a/kobalt/src/Build.kt +++ b/kobalt/src/Build.kt @@ -71,7 +71,10 @@ val kobaltPluginApi = project { "org.apache.maven:maven-model:3.3.3", "io.reactivex:rxjava:1.0.16", "com.google.code.gson:gson:2.4", + "com.squareup.okhttp3:okhttp:3.2.0", "com.squareup.retrofit:retrofit:1.9.0", + "com.squareup.retrofit2:retrofit:2.0.0-beta4", + "com.squareup.retrofit2:converter-gson:2.0.0-beta4", "com.beust:jcommander:1.48" ) } diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties index d2b5f6dd..292c9908 100644 --- a/kobalt/wrapper/kobalt-wrapper.properties +++ b/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=0.666 \ No newline at end of file +kobalt.version=0.667 \ No newline at end of file diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/GithubApi2.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/GithubApi2.kt new file mode 100644 index 00000000..74cfb335 --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/GithubApi2.kt @@ -0,0 +1,146 @@ +package com.beust.kobalt.misc + +import com.beust.kobalt.KobaltException +import com.beust.kobalt.internal.DocUrl +import com.beust.kobalt.maven.Http +import com.google.gson.annotations.SerializedName +import com.google.inject.Inject +import com.squareup.okhttp.Headers +import retrofit.RetrofitError +import retrofit.mime.TypedFile +import retrofit2.Call +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.* +import rx.Observable +import java.io.File +import java.util.* +import java.util.concurrent.Callable +import java.util.concurrent.Future + +class GithubApi2 @Inject constructor( + val executors: KobaltExecutors, val localProperties: LocalProperties, val http: Http) { + + companion object { + const val PROPERTY_ACCESS_TOKEN = "github.accessToken" + const val PROPERTY_USERNAME = "github.username" + } + + private val DOC_URL = DocUrl.PUBLISH_PLUGIN_URL + + // + // JSON mapped classes that get sent up and down + // + class CreateRelease(@SerializedName("tag_name") var tagName: String? = null, + var name: String? = tagName) + class CreateReleaseResponse(var id: String? = null, @SerializedName("upload_url") var uploadUrl: String?) + class UploadAssetResponse(var id: String? = null, val name: String? = null) + class ReleasesResponse(@SerializedName("tag_name") var tagName: String? = null, + var name: String? = tagName) + + interface Api { + @POST("/repos/{owner}/{repo}/releases") + fun createRelease(@Path("owner") owner: String, + @Path("repo") repo: String, + @Query("access_token") accessToken: String, + @Body createRelease: CreateRelease): Call + + @GET("/repos/{owner}/{repo}/releases") + fun getReleases(@Path("owner") owner: String, + @Path("repo") repo: String, + @Query("access_token") accessToken: String): Call> + + @GET("/repos/{owner}/{repo}/releases") + fun getReleasesNoAuth(@Path("owner") owner: String, + @Path("repo") repo: String): Call> + } + + // + // Read only Api + // + private val service = Retrofit.Builder() + .baseUrl("https://api.github.com") + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(Api::class.java) + + fun uploadRelease(packageName: String, tagName: String, zipFile: File) { + log(1, "Uploading release ${zipFile.name}") + + val username = localProperties.get(PROPERTY_USERNAME, DOC_URL) + val accessToken = localProperties.get(PROPERTY_ACCESS_TOKEN, DOC_URL) + try { + val response = service.createRelease(username, packageName, accessToken, CreateRelease(tagName)) + .execute() + .body() + + uploadAsset(accessToken, response.uploadUrl!!, TypedFile("application/zip", zipFile), + tagName) + .toBlocking() + .forEach { action -> + log(1, "\n${zipFile.name} successfully uploaded") + } + } catch(e: RetrofitError) { + throw KobaltException("Couldn't upload release: " + e.message, e) +// val error = parseRetrofitError(e) +// throw KobaltException("Couldn't upload release, ${error.message}: " +// + error.errors[0].code + " field: " + error.errors[0].field) + } + } + + private fun uploadAsset(token: String, uploadUrl: String, typedFile: TypedFile, tagName: String) + : Observable { + val strippedUrl = uploadUrl.substring(0, uploadUrl.indexOf("{")) + val fileName = typedFile.file().name + val url = "$strippedUrl?name=$fileName&label=$fileName" + val headers = Headers.of("Authorization", "token $token") + val totalSize = typedFile.file().length() + http.uploadFile(url = url, file = typedFile, headers = headers, post = true, // Github requires POST + progressCallback = http.percentProgressCallback(totalSize)) + + return Observable.just(UploadAssetResponse(tagName, tagName)) + } + + val latestKobaltVersion: Future + get() { + val callable = Callable { + var result = "0" + + val username = localProperties.getNoThrows(GithubApiOld.PROPERTY_USERNAME, DOC_URL) + val accessToken = localProperties.getNoThrows(GithubApiOld.PROPERTY_ACCESS_TOKEN, DOC_URL) + try { + val req = + if (username != null && accessToken != null) { + service.getReleases(username, "kobalt", accessToken) + } else { + service.getReleasesNoAuth("cbeust", "kobalt") + } + val releases = req.execute() + .body() + releases.firstOrNull()?.let { + try { + result = listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() } + } catch(ex: NoSuchElementException) { + throw KobaltException("Couldn't find the latest release") + } + } + } catch(e: RetrofitError) { + log(1, "Couldn't retrieve releases from github: " + e.message) + e.printStackTrace() +// val error = parseRetrofitError(e) +// val details = if (error.errors != null) { +// error.errors[0] +// } else { +// null +// } +// // TODO: If the credentials didn't work ("bad credentials"), should start again +// // using cbeust/kobalt, like above. Right now, just bailing. +// log(2, "Couldn't retrieve releases from github, ${error.message ?: e}: " +// + details?.code + " field: " + details?.field) + } + result + } + + return executors.miscExecutor.submit(callable) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index 1fc07b6e..ed8d793d 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -58,7 +58,7 @@ private class Main @Inject constructor( val files: KFiles, val executors: KobaltExecutors, val checkVersions: CheckVersions, - val github: GithubApi, + val github: GithubApi2, val updateKobalt: UpdateKobalt, val client: KobaltClient, val server: KobaltServer, diff --git a/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt b/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt index cd66c7ff..0c989662 100644 --- a/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt +++ b/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt @@ -14,7 +14,7 @@ import javax.inject.Inject /** * Update Kobalt to the latest version. */ -class UpdateKobalt @Inject constructor(val github: GithubApi, val wrapperProperties: KobaltWrapperProperties) { +class UpdateKobalt @Inject constructor(val github: GithubApi2, val wrapperProperties: KobaltWrapperProperties) { fun updateKobalt() { val newVersion = github.latestKobaltVersion wrapperProperties.create(newVersion.get()) diff --git a/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt index bd892d88..db7c9e45 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt @@ -16,7 +16,7 @@ import javax.inject.Singleton @Suppress("VARIABLE_WITH_REDUNDANT_INITIALIZER") @Singleton public class PublishPlugin @Inject constructor(val files: KFiles, val factory: PomGenerator.IFactory, - val bintrayFactory: BintrayApi.IFactory, val github: GithubApi, val localProperties: LocalProperties) + val bintrayFactory: BintrayApi.IFactory, val github: GithubApi2, val localProperties: LocalProperties) : BasePlugin() { override val name = PLUGIN_NAME diff --git a/src/main/resources/kobalt.properties b/src/main/resources/kobalt.properties index 9db44ee2..529cf587 100644 --- a/src/main/resources/kobalt.properties +++ b/src/main/resources/kobalt.properties @@ -1 +1 @@ -kobalt.version=0.666 +kobalt.version=0.667