generated from leanix/repository-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from leanix/feature/CID-2776/create-a-webhook-…
…listener-endpoint Feature/cid 2776/create a webhook listener endpoint
- Loading branch information
Showing
15 changed files
with
428 additions
and
28 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
src/main/kotlin/net/leanix/githubagent/controllers/GitHubWebhookController.kt
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,34 @@ | ||
package net.leanix.githubagent.controllers | ||
|
||
import net.leanix.githubagent.services.WebhookService | ||
import net.leanix.githubagent.shared.SUPPORTED_EVENT_TYPES | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.web.bind.annotation.PostMapping | ||
import org.springframework.web.bind.annotation.RequestBody | ||
import org.springframework.web.bind.annotation.RequestHeader | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.ResponseStatus | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("/github") | ||
class GitHubWebhookController(private val webhookService: WebhookService) { | ||
|
||
private val logger = LoggerFactory.getLogger(GitHubWebhookController::class.java) | ||
|
||
@PostMapping("/webhook") | ||
@ResponseStatus(HttpStatus.ACCEPTED) | ||
fun hook( | ||
@RequestHeader("X-Github-Event") eventType: String, | ||
@RequestBody payload: String | ||
) { | ||
runCatching { | ||
if (SUPPORTED_EVENT_TYPES.contains(eventType.uppercase())) { | ||
webhookService.consumeWebhookEvent(eventType, payload) | ||
} else { | ||
logger.warn("Received an unsupported event of type: $eventType") | ||
} | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/kotlin/net/leanix/githubagent/dto/ManifestFileUpdateDto.kt
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 net.leanix.githubagent.dto | ||
|
||
data class ManifestFileUpdateDto( | ||
val repositoryFullName: String, | ||
val action: ManifestFileAction, | ||
val manifestContent: String? | ||
) | ||
|
||
enum class ManifestFileAction { | ||
ADDED, | ||
MODIFIED, | ||
REMOVED | ||
} |
41 changes: 41 additions & 0 deletions
41
src/main/kotlin/net/leanix/githubagent/dto/PushEventPayload.kt
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,41 @@ | ||
package net.leanix.githubagent.dto | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties | ||
import com.fasterxml.jackson.annotation.JsonProperty | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class PushEventPayload( | ||
val ref: String, | ||
val repository: PushEventRepository, | ||
val installation: PushEventInstallation, | ||
@JsonProperty("head_commit") | ||
val headCommit: PushEventCommit | ||
) | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class PushEventRepository( | ||
@JsonProperty("name") | ||
val name: String, | ||
@JsonProperty("full_name") | ||
val fullName: String, | ||
@JsonProperty("default_branch") | ||
val defaultBranch: String, | ||
val owner: PushEventOwner | ||
) | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class PushEventInstallation( | ||
val id: Int | ||
) | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class PushEventCommit( | ||
val added: List<String>, | ||
val removed: List<String>, | ||
val modified: List<String> | ||
) | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
data class PushEventOwner( | ||
val name: String | ||
) |
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
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
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
85 changes: 85 additions & 0 deletions
85
src/main/kotlin/net/leanix/githubagent/services/WebhookService.kt
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,85 @@ | ||
package net.leanix.githubagent.services | ||
|
||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper | ||
import com.fasterxml.jackson.module.kotlin.readValue | ||
import net.leanix.githubagent.config.GitHubEnterpriseProperties | ||
import net.leanix.githubagent.dto.ManifestFileAction | ||
import net.leanix.githubagent.dto.ManifestFileUpdateDto | ||
import net.leanix.githubagent.dto.PushEventPayload | ||
import net.leanix.githubagent.shared.MANIFEST_FILE_NAME | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class WebhookService( | ||
private val webSocketService: WebSocketService, | ||
private val gitHubGraphQLService: GitHubGraphQLService, | ||
private val gitHubEnterpriseProperties: GitHubEnterpriseProperties, | ||
private val cachingService: CachingService, | ||
private val gitHubAuthenticationService: GitHubAuthenticationService | ||
) { | ||
|
||
private val logger = LoggerFactory.getLogger(WebhookService::class.java) | ||
private val objectMapper = jacksonObjectMapper() | ||
|
||
fun consumeWebhookEvent(eventType: String, payload: String) { | ||
when (eventType.uppercase()) { | ||
"PUSH" -> handlePushEvent(payload) | ||
else -> { | ||
logger.info("Sending event of type: $eventType") | ||
webSocketService.sendMessage("/events/other", payload) | ||
} | ||
} | ||
} | ||
|
||
private fun handlePushEvent(payload: String) { | ||
val pushEventPayload: PushEventPayload = objectMapper.readValue(payload) | ||
val repositoryName = pushEventPayload.repository.name | ||
val repositoryFullName = pushEventPayload.repository.fullName | ||
val headCommit = pushEventPayload.headCommit | ||
val organizationName = pushEventPayload.repository.owner.name | ||
|
||
var installationToken = cachingService.get("installationToken:${pushEventPayload.installation.id}")?.toString() | ||
if (installationToken == null) { | ||
gitHubAuthenticationService.refreshTokens() | ||
installationToken = cachingService.get("installationToken:${pushEventPayload.installation.id}")?.toString() | ||
require(installationToken != null) { "Installation token not found/ expired" } | ||
} | ||
|
||
if (pushEventPayload.ref == "refs/heads/${pushEventPayload.repository.defaultBranch}") { | ||
when { | ||
MANIFEST_FILE_NAME in headCommit.added -> { | ||
logger.info("Manifest file added to repository $repositoryFullName") | ||
val fileContent = getManifestFileContent(organizationName, repositoryName, installationToken) | ||
sendManifestData(repositoryFullName, ManifestFileAction.ADDED, fileContent) | ||
} | ||
MANIFEST_FILE_NAME in headCommit.modified -> { | ||
logger.info("Manifest file modified in repository $repositoryFullName") | ||
val fileContent = getManifestFileContent(organizationName, repositoryName, installationToken) | ||
sendManifestData(repositoryFullName, ManifestFileAction.MODIFIED, fileContent) | ||
} | ||
MANIFEST_FILE_NAME in headCommit.removed -> { | ||
logger.info("Manifest file removed from repository $repositoryFullName") | ||
sendManifestData(repositoryFullName, ManifestFileAction.REMOVED, null) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun getManifestFileContent(organizationName: String, repositoryName: String, token: String): String { | ||
return gitHubGraphQLService.getManifestFileContent( | ||
owner = organizationName, | ||
repositoryName, | ||
"HEAD:${gitHubEnterpriseProperties.manifestFileDirectory}$MANIFEST_FILE_NAME", | ||
token | ||
) | ||
} | ||
|
||
private fun sendManifestData(repositoryFullName: String, action: ManifestFileAction, manifestContent: String?) { | ||
logger.info("Sending manifest file update event for repository $repositoryFullName") | ||
webSocketService.sendMessage( | ||
"/events/manifestFile", | ||
ManifestFileUpdateDto(repositoryFullName, action, manifestContent) | ||
) | ||
} | ||
} |
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 |
---|---|---|
@@ -1,3 +1,12 @@ | ||
package net.leanix.githubagent.shared | ||
|
||
const val TOPIC_PREFIX = "/app/ghe/" | ||
|
||
const val MANIFEST_FILE_NAME = "leanix.yaml" | ||
|
||
val SUPPORTED_EVENT_TYPES = listOf( | ||
"REPOSITORY", | ||
"PUSH", | ||
"ORGANIZATION", | ||
"INSTALLATION", | ||
) |
Oops, something went wrong.