Skip to content

Commit

Permalink
chore: added some stuff to help debug some issues
Browse files Browse the repository at this point in the history
  • Loading branch information
BrianEstrada committed Mar 8, 2023
1 parent a514d9f commit ec67af1
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ class GenerateChangeLogCommand : CliktCommand() {
envvar = "CHANGELOG_GITHUB_RELEASE"
).flag("--github-release", "-R", default = false)

private val update: Boolean by option(
help = "Must be set if the github release already exists and should be update with change log instead of created",
envvar = "CHANGELOG_GITHUB_UPDATE"
).flag("--github-update", default = true)

private val githubToken: String? by option(
help = "Github Token used for creating releases",
envvar = "CHANGELOG_GITHUB_TOKEN"
Expand Down Expand Up @@ -87,7 +82,6 @@ class GenerateChangeLogCommand : CliktCommand() {
jiraAppName = jiraAppName,
tagSorter = versionMode.sorter,
githubRelease = githubRelease,
update = update,
githubToken = githubToken
)

Expand Down
211 changes: 121 additions & 90 deletions src/commonMain/kotlin/com.monta.changelog/github/GitHubService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import com.monta.changelog.util.GroupedCommitMap
import com.monta.changelog.util.LinkResolver
import com.monta.changelog.util.MarkdownFormatter
import com.monta.changelog.util.client
import com.monta.changelog.util.getBodySafe
import com.monta.changelog.util.resolve
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
Expand All @@ -20,114 +20,139 @@ class GitHubService(
private val githubToken: String?
) {

suspend fun createRelease(
suspend fun createOrUpdateRelease(
linkResolvers: List<LinkResolver>,
changeLog: ChangeLog
): String? {
val url = baseUrl(
path = "${changeLog.repoOwner}/${changeLog.repoName}/releases"
)
val htmlUrl: String? = createRelease(linkResolvers, changeLog)

val response = client.post(url) {
withGithubDefaults()
setBody(
ReleaseRequest(
body = buildBody(
markdownFormatter = MarkdownFormatter.GitHub,
linkResolvers = linkResolvers,
groupedCommitMap = changeLog.groupedCommitMap
),
draft = false,
generate_release_notes = false,
name = changeLog.tagName,
prerelease = false,
tag_name = changeLog.tagName
)
)
if (htmlUrl == null) {
return updateRelease(linkResolvers, changeLog)
}

val releaseResponse = response.getBodySafe<ReleaseResponse>()
return htmlUrl
}

if (releaseResponse == null) {
DebugLogger.error("failed to create release ${response.bodyAsText()}")
DebugLogger.error("returning with code 1")
exit(1)
}
private suspend fun createRelease(
linkResolvers: List<LinkResolver>,
changeLog: ChangeLog
): String? {
DebugLogger.info("creating release")

val response = client.githubRequest(
path = "${changeLog.repoOwner}/${changeLog.repoName}/releases",
httpMethod = HttpMethod.Post,
body = ReleaseRequest(
body = buildBody(
markdownFormatter = MarkdownFormatter.GitHub,
linkResolvers = linkResolvers,
groupedCommitMap = changeLog.groupedCommitMap
),
draft = false,
generateReleaseNotes = false,
name = changeLog.tagName,
prerelease = false,
tagName = changeLog.tagName
)
)

DebugLogger.info("successfully created release")
if (response.status.isSuccess()) {
try {
return response.body<ReleaseResponse>().htmlUrl
} catch (throwable: Throwable) {
DebugLogger.error("failed to deserialized ReleaseResponse body ${response.bodyAsText()}")
// No return just let it go to the general exit path at the end
}
} else {
try {
val errorResponse = response.body<ErrorResponse>()
if (errorResponse.hasReleaseAlreadyExists()) {
// This is ok and we can recover from this, so we return here
return null
}
} catch (throwable: Throwable) {
throwable.printStackTrace()
DebugLogger.error("failed to deserialized ErrorResponse body ${response.bodyAsText()}")
// No return just let it go to the general exit path at the end
}
}

return releaseResponse?.htmlUrl
DebugLogger.error("failed to create release ${response.bodyAsText()}")
DebugLogger.error("returning with code 1")
exit(1)
return null
}

suspend fun updateRelease(
private suspend fun updateRelease(
linkResolvers: List<LinkResolver>,
changeLog: ChangeLog
): String? {
val releaseId = getReleaseId(changeLog)
DebugLogger.info("updating release")

val url = baseUrl(
path = "${changeLog.repoOwner}/${changeLog.repoName}/releases/$releaseId"
)
val releaseId = getReleaseId(changeLog)

val response = client.patch(url) {
withGithubDefaults()
setBody(
UpdateReleaseRequest(
body = buildBody(
markdownFormatter = MarkdownFormatter.GitHub,
linkResolvers = linkResolvers,
groupedCommitMap = changeLog.groupedCommitMap
)
val response = client.githubRequest(
path = "${changeLog.repoOwner}/${changeLog.repoName}/releases/$releaseId",
httpMethod = HttpMethod.Patch,
body = ReleaseRequest(
body = buildBody(
markdownFormatter = MarkdownFormatter.GitHub,
linkResolvers = linkResolvers,
groupedCommitMap = changeLog.groupedCommitMap
)
)
}

val releaseResponse = response.getBodySafe<ReleaseResponse>()
)

if (releaseResponse == null) {
DebugLogger.error("failed to update release ${response.bodyAsText()}")
DebugLogger.error("returning with code 1")
exit(1)
if (response.status.isSuccess()) {
try {
return response.body<ReleaseResponse>().htmlUrl
} catch (throwable: Throwable) {
DebugLogger.error("failed to deserialized ReleaseResponse body ${response.bodyAsText()}")
// No return just let it go to the general exit path at the end
}
}

DebugLogger.info("successfully updated release")

return releaseResponse?.htmlUrl
DebugLogger.error("failed to update release ${response.bodyAsText()}")
DebugLogger.error("returning with code 1")
exit(1)
return null
}

private suspend fun getReleaseId(changeLog: ChangeLog): Int? {
val url = baseUrl(
path = "${changeLog.repoOwner}/${changeLog.repoName}/releases/tags/${changeLog.tagName}"
val response = client.githubRequest(
path = "${changeLog.repoOwner}/${changeLog.repoName}/releases/tags/${changeLog.tagName}",
httpMethod = HttpMethod.Get,
body = null as String?
)

val response = client.get(url) {
withGithubDefaults(false)
}

return if (response.status.value == 200) {
if (response.status.isSuccess()) {
DebugLogger.info("found release ${response.bodyAsText()}")
val responseBody = response.body<ReleaseResponse>()
responseBody.id
} else {
DebugLogger.error("could not find release ${response.bodyAsText()}")
DebugLogger.error("returning with code 1")
exit(1)
null
return response.body<ReleaseResponse>().id
}
}

private fun baseUrl(path: String): String {
return "https://api.github.com/repos/$path"
DebugLogger.error("could not find release ${response.bodyAsText()}")
DebugLogger.error("returning with code 1")
exit(1)
return null
}

private fun HttpRequestBuilder.withGithubDefaults(
isJson: Boolean = true
) {
header("Authorization", "token $githubToken")
if (isJson) {
contentType(ContentType.Application.Json)
private suspend inline fun <reified T> HttpClient.githubRequest(
path: String,
httpMethod: HttpMethod,
body: T?
): HttpResponse {
return request {
url {
url("https://api.github.com/repos/$path")
method = httpMethod
}
header("Authorization", "token $githubToken")
accept(ContentType.parse("application/vnd.github.v3+json"))
if (body != null) {
contentType(ContentType.Application.Json)
setBody(body)
}
}
accept(ContentType.parse("application/vnd.github.v3+json"))
}

private fun buildBody(
Expand Down Expand Up @@ -180,17 +205,18 @@ class GitHubService(

@Serializable
data class ReleaseRequest(
@SerialName("body")
val body: String,
val draft: Boolean,
val generate_release_notes: Boolean,
val name: String,
val prerelease: Boolean,
val tag_name: String
)

@Serializable
data class UpdateReleaseRequest(
val body: String
@SerialName("draft")
val draft: Boolean? = null,
@SerialName("generate_release_notes")
val generateReleaseNotes: Boolean? = null,
@SerialName("name")
val name: String? = null,
@SerialName("prerelease")
val prerelease: Boolean? = null,
@SerialName("tag_name")
val tagName: String? = null
)

@Serializable
Expand All @@ -201,16 +227,21 @@ class GitHubService(
val errors: List<Error>,
@SerialName("message")
val message: String
)
) {
fun hasReleaseAlreadyExists(): Boolean {
val error = errors.find { error ->
error.resource == "Release" && error.code == "already_exists" && error.field == "tag_name"
}
return error != null
}
}

@Serializable
data class Error(
@SerialName("code")
val code: String,
@SerialName("field")
val `field`: String,
@SerialName("message")
val message: String,
@SerialName("resource")
val resource: String
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class ChangeLogService(
private val jiraAppName: String?,
tagSorter: TagSorter,
private val githubRelease: Boolean,
private val update: Boolean,
githubToken: String?
) {

Expand Down Expand Up @@ -77,11 +76,10 @@ class ChangeLogService(
)

if (githubRelease) {
changeLog.githubReleaseUrl = if (update) {
gitHubService.updateRelease(linkResolvers, changeLog)
} else {
gitHubService.createRelease(linkResolvers, changeLog)
}
changeLog.githubReleaseUrl = gitHubService.createOrUpdateRelease(
linkResolvers = linkResolvers,
changeLog = changeLog
)
}

changeLogPrinter.print(linkResolvers, changeLog)
Expand Down

0 comments on commit ec67af1

Please sign in to comment.