From c8d23026657f7e3b7b15fabe093de4b63a2fe5b6 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 18 Aug 2022 12:53:57 -0500 Subject: [PATCH] feat: adding json serializable classes for pull requests --- build.gradle.kts | 3 + src/main/kotlin/Client.kt | 29 +++--- src/main/kotlin/EventEmitter.kt | 4 +- src/main/kotlin/HttpClientExtensions.kt | 2 +- src/main/kotlin/Main.kt | 8 +- src/main/kotlin/structures/AutoMerge.kt | 9 ++ src/main/kotlin/structures/Base.kt | 11 +++ src/main/kotlin/structures/Comments.kt | 5 + src/main/kotlin/structures/Commits.kt | 5 + src/main/kotlin/structures/EnabledBy.kt | 22 +++++ src/main/kotlin/structures/Head.kt | 9 ++ src/main/kotlin/structures/Html.kt | 5 + src/main/kotlin/structures/Issue.kt | 5 + src/main/kotlin/structures/Label.kt | 11 +++ src/main/kotlin/structures/Links.kt | 12 +++ src/main/kotlin/structures/Milestone.kt | 13 +++ src/main/kotlin/structures/Organization.kt | 16 ++++ src/main/kotlin/structures/PullRequest.kt | 54 +++++++++++ src/main/kotlin/structures/PullRequests.kt | 10 ++ src/main/kotlin/structures/Repo.kt | 93 +++++++++++++++++++ src/main/kotlin/structures/Repository.kt | 82 ++++++++++++++++ .../kotlin/structures/RequestedReviewer.kt | 22 +++++ src/main/kotlin/structures/ReviewComment.kt | 5 + src/main/kotlin/structures/ReviewComments.kt | 5 + src/main/kotlin/structures/Self.kt | 5 + src/main/kotlin/structures/Sender.kt | 22 +++++ src/main/kotlin/structures/Statuses.kt | 5 + src/main/kotlin/structures/Team.kt | 15 +++ src/main/kotlin/structures/User.kt | 22 +++++ 29 files changed, 490 insertions(+), 19 deletions(-) create mode 100644 src/main/kotlin/structures/AutoMerge.kt create mode 100644 src/main/kotlin/structures/Base.kt create mode 100644 src/main/kotlin/structures/Comments.kt create mode 100644 src/main/kotlin/structures/Commits.kt create mode 100644 src/main/kotlin/structures/EnabledBy.kt create mode 100644 src/main/kotlin/structures/Head.kt create mode 100644 src/main/kotlin/structures/Html.kt create mode 100644 src/main/kotlin/structures/Issue.kt create mode 100644 src/main/kotlin/structures/Label.kt create mode 100644 src/main/kotlin/structures/Links.kt create mode 100644 src/main/kotlin/structures/Milestone.kt create mode 100644 src/main/kotlin/structures/Organization.kt create mode 100644 src/main/kotlin/structures/PullRequest.kt create mode 100644 src/main/kotlin/structures/PullRequests.kt create mode 100644 src/main/kotlin/structures/Repo.kt create mode 100644 src/main/kotlin/structures/Repository.kt create mode 100644 src/main/kotlin/structures/RequestedReviewer.kt create mode 100644 src/main/kotlin/structures/ReviewComment.kt create mode 100644 src/main/kotlin/structures/ReviewComments.kt create mode 100644 src/main/kotlin/structures/Self.kt create mode 100644 src/main/kotlin/structures/Sender.kt create mode 100644 src/main/kotlin/structures/Statuses.kt create mode 100644 src/main/kotlin/structures/Team.kt create mode 100644 src/main/kotlin/structures/User.kt diff --git a/build.gradle.kts b/build.gradle.kts index 41f0fb8..aaaf248 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,6 +22,9 @@ dependencies { testImplementation(kotlin("test")) implementation("io.ktor:ktor-client-core:2.1.0") implementation("io.ktor:ktor-client-cio:2.1.0") + implementation("io.ktor:ktor-client-content-negotiation:2.1.0") + // Use JSON serialization + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") implementation("io.ktor:ktor-server-core-jvm:2.0.3") implementation("io.ktor:ktor-server-netty-jvm:2.0.3") implementation("com.auth0:java-jwt:$jwt_version") diff --git a/src/main/kotlin/Client.kt b/src/main/kotlin/Client.kt index ccb3ae8..dc1e4f2 100644 --- a/src/main/kotlin/Client.kt +++ b/src/main/kotlin/Client.kt @@ -5,6 +5,12 @@ import com.auth0.jwt.JWT import com.auth0.jwt.algorithms.Algorithm import com.auth0.jwt.exceptions.JWTCreationException import io.github.cdimascio.dotenv.dotenv +import io.ktor.client.* +import io.ktor.client.engine.cio.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.utils.* +import io.ktor.http.* +import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.netty.* import kotlinx.coroutines.* @@ -13,6 +19,7 @@ import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED import kotlinx.coroutines.flow.collect import org.kohsuke.github.* import org.kohsuke.github.connector.GitHubConnector +import org.kohsuke.github.extras.authorization.JWTTokenProvider import java.security.KeyFactory import java.security.interfaces.RSAPrivateKey import java.security.spec.PKCS8EncodedKeySpec @@ -26,6 +33,12 @@ object Client : CoroutineScope { private var jwtToken: String private var gitHubApp: GHApp private var gitHub: GitHub + private val ktorClient = HttpClient(CIO) { + install(ContentNegotiation) { + + } + + } private var parentJob = Job() val eventEmitter = EventEmitter() @@ -47,13 +60,12 @@ object Client : CoroutineScope { val privateKey = processKey().use { it } val algorithm = Algorithm.RSA256(privateKey) jwtToken = JWT.create() - .withIssuer("215907") + .withIssuer(System.getProperty("APP_ID")) .withIssuedAt(Instant.now().minusMillis(6_000)) .withExpiresAt(Instant.now().plusMillis(600000)) .sign(algorithm) ?: throw JWTCreationException("Could not create JWT", Throwable()) val github = GitHubBuilder() .withJwtToken(jwtToken) - .withConnector(GitHubConnector.DEFAULT) .withEndpoint(baseLink) .build() gitHubApp = github.app @@ -67,14 +79,9 @@ object Client : CoroutineScope { } } - fun fetchRepoAsync(name: String) : Deferred> { + fun fetchRepoAsync(name: String) : Deferred { return async { - try { - Either.Right(gitHub.getRepository("$orgName/$name")) - } catch (e: Throwable) { - Either.Left(e.message ?: "Something went wrong while trying to fetch repository") - } - + gitHub.getRepository("$orgName/$name") } } fun fetchPullRequestAsync(repo : GHRepository, id: Int) : Deferred> { @@ -92,8 +99,8 @@ object Client : CoroutineScope { ) { Client.launch { eventEmitter.events.collect { - when (it) { - "Hello" -> fn(it) + when (eventName) { + "pull_request" -> fn(it) } } } diff --git a/src/main/kotlin/EventEmitter.kt b/src/main/kotlin/EventEmitter.kt index 24fb0e4..3121659 100644 --- a/src/main/kotlin/EventEmitter.kt +++ b/src/main/kotlin/EventEmitter.kt @@ -3,10 +3,10 @@ import kotlinx.coroutines.flow.asSharedFlow typealias Event = String class EventEmitter { - private val _events = MutableSharedFlow() // private mutable shared flow + private val _events = MutableSharedFlow() // private mutable shared flow val events = _events.asSharedFlow() // publicly exposed as read-only shared flow - suspend fun produceEvent(event: Event) { + suspend fun produceEvent(event: String) { _events.emit(event) // suspends until all subscribers receive it } } \ No newline at end of file diff --git a/src/main/kotlin/HttpClientExtensions.kt b/src/main/kotlin/HttpClientExtensions.kt index f294770..3882c54 100644 --- a/src/main/kotlin/HttpClientExtensions.kt +++ b/src/main/kotlin/HttpClientExtensions.kt @@ -18,7 +18,7 @@ fun Application.configureRouting() { } fun Routing.pullRequests() { - post("/payload") { + post("/pulls") { val secret = call.request.headers["X-Hub-Signature-256"]!! val text = call.receiveText() if(!HashUtils.secureCompare(secret, HashUtils.sha256(text))) { diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index e39e838..793d041 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -4,15 +4,13 @@ import kotlinx.coroutines.* fun main() = runBlocking { val client = Client + val repo = client.fetchRepoAsync("awesome-plugins").await() + + client.on("pull_request") { - client.on("pullRequest") { println(it + "2") } - client.on("issue") { - println(it + "3") - } println("Start program") - println(Thread.currentThread().name) client.startWebhookListener() } diff --git a/src/main/kotlin/structures/AutoMerge.kt b/src/main/kotlin/structures/AutoMerge.kt new file mode 100644 index 0000000..615f921 --- /dev/null +++ b/src/main/kotlin/structures/AutoMerge.kt @@ -0,0 +1,9 @@ +package structures + +@kotlinx.serialization.Serializable +data class AutoMerge( + val commit_message: String, + val commit_title: String, + val enabled_by: EnabledBy, + val merge_method: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Base.kt b/src/main/kotlin/structures/Base.kt new file mode 100644 index 0000000..f09faa0 --- /dev/null +++ b/src/main/kotlin/structures/Base.kt @@ -0,0 +1,11 @@ +package structures + +@kotlinx.serialization.Serializable +data class Base( + + val label: String, + val ref: String, + val repo: Repo, + val sha: String, + val user: User +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Comments.kt b/src/main/kotlin/structures/Comments.kt new file mode 100644 index 0000000..62d288e --- /dev/null +++ b/src/main/kotlin/structures/Comments.kt @@ -0,0 +1,5 @@ +package structures +@kotlinx.serialization.Serializable +data class Comments( + val href: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Commits.kt b/src/main/kotlin/structures/Commits.kt new file mode 100644 index 0000000..ebb6d07 --- /dev/null +++ b/src/main/kotlin/structures/Commits.kt @@ -0,0 +1,5 @@ +package structures +@kotlinx.serialization.Serializable +data class Commits( + val href: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/EnabledBy.kt b/src/main/kotlin/structures/EnabledBy.kt new file mode 100644 index 0000000..c9b645b --- /dev/null +++ b/src/main/kotlin/structures/EnabledBy.kt @@ -0,0 +1,22 @@ +package structures +@kotlinx.serialization.Serializable +data class EnabledBy( + val avatar_url: String, + val events_url: String, + val followers_url: String, + val following_url: String, + val gists_url: String, + val gravatar_id: String, + val html_url: String, + val id: Int, + val login: String, + val node_id: String, + val organizations_url: String, + val received_events_url: String, + val repos_url: String, + val site_admin: Boolean, + val starred_url: String, + val subscriptions_url: String, + val type: String, + val url: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Head.kt b/src/main/kotlin/structures/Head.kt new file mode 100644 index 0000000..a92fe11 --- /dev/null +++ b/src/main/kotlin/structures/Head.kt @@ -0,0 +1,9 @@ +package structures +@kotlinx.serialization.Serializable +data class Head( + val label: String, + val ref: String, + val repo: Repo, + val sha: String, + val user: User +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Html.kt b/src/main/kotlin/structures/Html.kt new file mode 100644 index 0000000..1e696e2 --- /dev/null +++ b/src/main/kotlin/structures/Html.kt @@ -0,0 +1,5 @@ +package structures +@kotlinx.serialization.Serializable +data class Html( + val href: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Issue.kt b/src/main/kotlin/structures/Issue.kt new file mode 100644 index 0000000..f93e1b9 --- /dev/null +++ b/src/main/kotlin/structures/Issue.kt @@ -0,0 +1,5 @@ +package structures +@kotlinx.serialization.Serializable +data class Issue( + val href: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Label.kt b/src/main/kotlin/structures/Label.kt new file mode 100644 index 0000000..17aab0a --- /dev/null +++ b/src/main/kotlin/structures/Label.kt @@ -0,0 +1,11 @@ +package structures +@kotlinx.serialization.Serializable +data class Label( + val color: String, + val default: Boolean, + val description: String, + val id: Long, + val name: String, + val node_id: String, + val url: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Links.kt b/src/main/kotlin/structures/Links.kt new file mode 100644 index 0000000..bcadae6 --- /dev/null +++ b/src/main/kotlin/structures/Links.kt @@ -0,0 +1,12 @@ +package structures +@kotlinx.serialization.Serializable +data class Links( + val comments: Comments, + val commits: Commits, + val html: Html, + val issue: Issue, + val review_comment: ReviewComment, + val review_comments: ReviewComments, + val self: Self, + val statuses: Statuses +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Milestone.kt b/src/main/kotlin/structures/Milestone.kt new file mode 100644 index 0000000..ef8d45b --- /dev/null +++ b/src/main/kotlin/structures/Milestone.kt @@ -0,0 +1,13 @@ +package structures +@kotlinx.serialization.Serializable +data class Milestone( + val creator: User, + val description: String, + val html_url: String, + val id: Int, + val labels_url: String, + val node_id: String, + val number: Int, + val title: String, + val url: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/Organization.kt b/src/main/kotlin/structures/Organization.kt new file mode 100644 index 0000000..8c5f206 --- /dev/null +++ b/src/main/kotlin/structures/Organization.kt @@ -0,0 +1,16 @@ +package structures +@kotlinx.serialization.Serializable +data class Organization( + val avatar_url: String, + val description: String, + val events_url: String, + val hooks_url: String, + val id: Int, + val issues_url: String, + val login: String, + val members_url: String, + val node_id: String, + val public_members_url: String, + val repos_url: String, + val url: String +) \ No newline at end of file diff --git a/src/main/kotlin/structures/PullRequest.kt b/src/main/kotlin/structures/PullRequest.kt new file mode 100644 index 0000000..3ca4582 --- /dev/null +++ b/src/main/kotlin/structures/PullRequest.kt @@ -0,0 +1,54 @@ +package structures + + +@kotlinx.serialization.Serializable +data class PullRequest( + val _links: Links, + val active_lock_reason: String?, + val additions: Int, + val assignee: User, + val assignees: List, + val author_association: String, + val auto_merge: AutoMerge, + val base: Base, + val body: String?, + val changed_files: Int, + val closed_at: String?, + val comments: Int, + val comments_url: String, + val commits: Int, + val commits_url: String, + val created_at: String, + val deletions: Int, + val diff_url: String, + val draft: Boolean, + val head: Head, + val html_url: String, + val id: Int, + val issue_url: String, + val labels: List