Skip to content

Commit b0f3ae4

Browse files
Merge pull request #124 from leanix/feature/CID-3774/move-logic-of-processing-installation-events-to-backend
CID-3774: Move logic of processing installation event to backend
2 parents a66c20d + b275f1f commit b0f3ae4

File tree

7 files changed

+135
-127
lines changed

7 files changed

+135
-127
lines changed

src/main/kotlin/net/leanix/githubagent/dto/InstallationEventPayload.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package net.leanix.githubagent.dto
2+
3+
data class InstallationRequestDTO(
4+
val id: Long,
5+
val account: Account,
6+
)

src/main/kotlin/net/leanix/githubagent/handler/BrokerStompSessionHandler.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.springframework.stereotype.Component
1414
class BrokerStompSessionHandler(
1515
private val artifactDownloadHandler: ArtifactDownloadHandler,
1616
private val repositoryGetHandler: RepositoryGetHandler,
17+
private val installationGetHandler: InstallationGetHandler,
1718
) : StompSessionHandlerAdapter() {
1819
@Lazy
1920
@Autowired
@@ -28,6 +29,7 @@ class BrokerStompSessionHandler(
2829
isConnected = true
2930
session.subscribe("/user/queue/message/artifact", artifactDownloadHandler)
3031
session.subscribe("/user/queue/message/repository", repositoryGetHandler)
32+
session.subscribe("/user/queue/message/installation", installationGetHandler)
3133
}
3234

3335
override fun handleException(
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package net.leanix.githubagent.handler
2+
3+
import net.leanix.githubagent.client.GitHubClient
4+
import net.leanix.githubagent.dto.InstallationRequestDTO
5+
import net.leanix.githubagent.exceptions.JwtTokenNotFound
6+
import net.leanix.githubagent.services.CachingService
7+
import net.leanix.githubagent.services.GitHubAuthenticationService
8+
import net.leanix.githubagent.services.GitHubEnterpriseService
9+
import net.leanix.githubagent.services.GitHubScanningService
10+
import net.leanix.githubagent.services.SyncLogService
11+
import net.leanix.githubagent.shared.INSTALLATION_LABEL
12+
import org.slf4j.LoggerFactory
13+
import org.springframework.beans.factory.annotation.Autowired
14+
import org.springframework.beans.factory.annotation.Value
15+
import org.springframework.context.annotation.Lazy
16+
import org.springframework.messaging.simp.stomp.StompFrameHandler
17+
import org.springframework.messaging.simp.stomp.StompHeaders
18+
import org.springframework.stereotype.Component
19+
import java.lang.reflect.Type
20+
21+
@Component
22+
class InstallationGetHandler(
23+
@Lazy @Autowired
24+
private val gitHubAuthenticationService: GitHubAuthenticationService,
25+
@Lazy @Autowired
26+
private val gitHubScanningService: GitHubScanningService,
27+
@Lazy @Autowired
28+
private val gitHubEnterpriseService: GitHubEnterpriseService,
29+
@Lazy @Autowired
30+
private val cachingService: CachingService,
31+
@Lazy @Autowired
32+
private val syncLogService: SyncLogService,
33+
@Lazy @Autowired
34+
private val gitHubClient: GitHubClient,
35+
@Value("\${webhookEventService.waitingTime}") private val waitingTime: Long,
36+
) : StompFrameHandler {
37+
38+
private val logger = LoggerFactory.getLogger(InstallationGetHandler::class.java)
39+
40+
override fun getPayloadType(headers: StompHeaders): Type {
41+
return InstallationRequestDTO::class.java
42+
}
43+
44+
override fun handleFrame(headers: StompHeaders, payload: Any?) {
45+
payload?.let {
46+
val dto = payload as InstallationRequestDTO
47+
logger.info("Received installation get message from server for organisation: ${dto.account.login}")
48+
runCatching {
49+
fetchAndSendOrganisationData(dto)
50+
}
51+
}
52+
}
53+
54+
fun fetchAndSendOrganisationData(installationRequestDTO: InstallationRequestDTO) {
55+
while (cachingService.get("runId") != null) {
56+
logger.info("A full scan is already in progress, waiting for it to finish.")
57+
Thread.sleep(waitingTime)
58+
}
59+
syncLogService.sendFullScanStart(installationRequestDTO.account.login)
60+
kotlin.runCatching {
61+
val jwtToken = cachingService.get("jwtToken") ?: throw JwtTokenNotFound()
62+
val installation = gitHubClient.getInstallation(
63+
installationRequestDTO.id,
64+
"Bearer $jwtToken"
65+
)
66+
gitHubEnterpriseService.validateEnabledPermissionsAndEvents(
67+
INSTALLATION_LABEL,
68+
installation.permissions,
69+
installation.events
70+
)
71+
gitHubAuthenticationService.refreshTokens()
72+
gitHubScanningService.fetchAndSendOrganisationsData(listOf(installation))
73+
gitHubScanningService.fetchAndSendRepositoriesData(installation).forEach { repository ->
74+
gitHubScanningService.fetchManifestFilesAndSend(installation, repository)
75+
}
76+
}.onSuccess {
77+
syncLogService.sendFullScanSuccess()
78+
}.onFailure {
79+
syncLogService.sendFullScanFailure(it.message)
80+
}
81+
}
82+
}

src/main/kotlin/net/leanix/githubagent/services/WebhookEventService.kt

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,22 @@ package net.leanix.githubagent.services
22

33
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
44
import com.fasterxml.jackson.module.kotlin.readValue
5-
import net.leanix.githubagent.client.GitHubClient
6-
import net.leanix.githubagent.dto.InstallationEventPayload
75
import net.leanix.githubagent.dto.ManifestFileAction
86
import net.leanix.githubagent.dto.ManifestFileUpdateDto
97
import net.leanix.githubagent.dto.PushEventCommit
108
import net.leanix.githubagent.dto.PushEventPayload
11-
import net.leanix.githubagent.exceptions.JwtTokenNotFound
12-
import net.leanix.githubagent.shared.INSTALLATION_LABEL
139
import net.leanix.githubagent.shared.MANIFEST_FILE_NAME
1410
import net.leanix.githubagent.shared.fileNameMatchRegex
1511
import net.leanix.githubagent.shared.generateFullPath
1612
import org.slf4j.LoggerFactory
17-
import org.springframework.beans.factory.annotation.Value
1813
import org.springframework.stereotype.Service
1914

2015
@SuppressWarnings("TooManyFunctions")
2116
@Service
2217
class WebhookEventService(
2318
private val webSocketService: WebSocketService,
2419
private val gitHubGraphQLService: GitHubGraphQLService,
25-
private val cachingService: CachingService,
2620
private val gitHubAuthenticationService: GitHubAuthenticationService,
27-
private val gitHubScanningService: GitHubScanningService,
28-
private val syncLogService: SyncLogService,
29-
@Value("\${webhookEventService.waitingTime}") private val waitingTime: Long,
30-
private val gitHubClient: GitHubClient,
31-
private val gitHubEnterpriseService: GitHubEnterpriseService
3221
) {
3322

3423
private val logger = LoggerFactory.getLogger(WebhookEventService::class.java)
@@ -37,7 +26,6 @@ class WebhookEventService(
3726
fun consumeWebhookEvent(eventType: String, payload: String) {
3827
when (eventType.uppercase()) {
3928
"PUSH" -> handlePushEvent(payload)
40-
"INSTALLATION" -> handleInstallationEvent(payload)
4129
else -> {
4230
logger.debug("Sending event of type: $eventType")
4331
webSocketService.sendMessage("/events/other/$eventType", payload)
@@ -67,42 +55,6 @@ class WebhookEventService(
6755
}
6856
}
6957

70-
private fun handleInstallationEvent(payload: String) {
71-
val installationEventPayload: InstallationEventPayload = objectMapper.readValue(payload)
72-
if (installationEventPayload.action == "created") {
73-
handleInstallationCreated(installationEventPayload)
74-
}
75-
}
76-
77-
private fun handleInstallationCreated(installationEventPayload: InstallationEventPayload) {
78-
while (cachingService.get("runId") != null) {
79-
logger.info("A full scan is already in progress, waiting for it to finish.")
80-
Thread.sleep(waitingTime)
81-
}
82-
syncLogService.sendFullScanStart(installationEventPayload.installation.account.login)
83-
kotlin.runCatching {
84-
val jwtToken = cachingService.get("jwtToken") ?: throw JwtTokenNotFound()
85-
val installation = gitHubClient.getInstallation(
86-
installationEventPayload.installation.id.toLong(),
87-
"Bearer $jwtToken"
88-
)
89-
gitHubEnterpriseService.validateEnabledPermissionsAndEvents(
90-
INSTALLATION_LABEL,
91-
installation.permissions,
92-
installation.events
93-
)
94-
gitHubAuthenticationService.refreshTokens()
95-
gitHubScanningService.fetchAndSendOrganisationsData(listOf(installation))
96-
gitHubScanningService.fetchAndSendRepositoriesData(installation).forEach { repository ->
97-
gitHubScanningService.fetchManifestFilesAndSend(installation, repository)
98-
}
99-
}.onSuccess {
100-
syncLogService.sendFullScanSuccess()
101-
}.onFailure {
102-
syncLogService.sendFullScanFailure(it.message)
103-
}
104-
}
105-
10658
private fun handleManifestFileChanges(
10759
defaultBranch: String,
10860
headCommit: PushEventCommit,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package net.leanix.githubagent.services
2+
3+
import com.ninjasquad.springmockk.MockkBean
4+
import com.ninjasquad.springmockk.SpykBean
5+
import io.mockk.every
6+
import io.mockk.just
7+
import io.mockk.runs
8+
import io.mockk.verify
9+
import net.leanix.githubagent.dto.Account
10+
import net.leanix.githubagent.dto.InstallationRequestDTO
11+
import net.leanix.githubagent.handler.InstallationGetHandler
12+
import org.junit.jupiter.api.Test
13+
import org.springframework.boot.test.context.SpringBootTest
14+
import org.springframework.test.context.ActiveProfiles
15+
16+
@SpringBootTest
17+
@ActiveProfiles("test")
18+
class InstallationGetHandlerTest {
19+
20+
@MockkBean
21+
private lateinit var webSocketService: WebSocketService
22+
23+
@MockkBean
24+
private lateinit var cachingService: CachingService
25+
26+
@SpykBean
27+
private lateinit var installationGetHandler: InstallationGetHandler
28+
29+
@Test
30+
fun `should wait for active scan to finish before starting scanning new org`() {
31+
every { cachingService.get("runId") } returnsMany listOf("value", "value", "value", null)
32+
every { cachingService.set("runId", any(), any()) } just runs
33+
every { cachingService.remove("runId") } just runs
34+
every { webSocketService.sendMessage(any(), any()) } returns Unit
35+
36+
val installationRequestDTO = InstallationRequestDTO(
37+
30,
38+
Account("test-org")
39+
)
40+
41+
installationGetHandler.fetchAndSendOrganisationData(installationRequestDTO)
42+
43+
verify(exactly = 6) { cachingService.get("runId") }
44+
}
45+
}

src/test/kotlin/net/leanix/githubagent/services/WebhookEventServiceTest.kt

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,20 @@ package net.leanix.githubagent.services
22

33
import com.ninjasquad.springmockk.MockkBean
44
import io.mockk.every
5-
import io.mockk.just
6-
import io.mockk.runs
75
import io.mockk.verify
86
import net.leanix.githubagent.client.GitHubClient
97
import net.leanix.githubagent.dto.Account
108
import net.leanix.githubagent.dto.Installation
119
import net.leanix.githubagent.dto.ItemResponse
1210
import net.leanix.githubagent.dto.ManifestFileAction
1311
import net.leanix.githubagent.dto.ManifestFileUpdateDto
14-
import net.leanix.githubagent.dto.Organization
1512
import net.leanix.githubagent.dto.RepositoryItemResponse
1613
import net.leanix.githubagent.shared.MANIFEST_FILE_NAME
1714
import org.junit.jupiter.api.BeforeEach
1815
import org.junit.jupiter.api.Test
1916
import org.springframework.beans.factory.annotation.Autowired
2017
import org.springframework.boot.test.context.SpringBootTest
2118
import org.springframework.test.context.ActiveProfiles
22-
import java.util.UUID
2319

2420
const val UNSUPPORTED_MANIFEST_EXTENSION = "leanix.yml"
2521

@@ -413,29 +409,6 @@ class WebhookEventServiceTest {
413409
}
414410
}
415411

416-
@Test
417-
fun `should wait for active scan to finish before starting scanning new org`() {
418-
every { cachingService.get("runId") } returnsMany listOf("value", "value", "value", null)
419-
every { cachingService.set("runId", any(), any()) } just runs
420-
every { cachingService.remove("runId") } just runs
421-
422-
val eventType = "INSTALLATION"
423-
val payload = """{
424-
"action": "created",
425-
"installation": {
426-
"id": 30,
427-
"account": {
428-
"login": "test-org",
429-
"id": 20
430-
}
431-
}
432-
}"""
433-
434-
webhookEventService.consumeWebhookEvent(eventType, payload)
435-
436-
verify(exactly = 6) { cachingService.get("runId") }
437-
}
438-
439412
@Test
440413
fun `should ignore push events without a head commit`() {
441414
val payload = """{
@@ -456,37 +429,6 @@ class WebhookEventServiceTest {
456429
}
457430
}
458431

459-
@Test
460-
fun `should send the org to the backend when an new installation is created`() {
461-
val runId = UUID.randomUUID()
462-
every { cachingService.get("runId") } returnsMany listOf("value", null, runId)
463-
every { cachingService.set("runId", any(), any()) } just runs
464-
every { cachingService.remove("runId") } just runs
465-
every { gitHubAPIService.getPaginatedOrganizations(any()) } returns
466-
listOf(Organization("testOrganization", 1))
467-
468-
val eventType = "INSTALLATION"
469-
val payload = """{
470-
"action": "created",
471-
"installation": {
472-
"id": 30,
473-
"account": {
474-
"login": "test-org",
475-
"id": 20
476-
}
477-
}
478-
}"""
479-
480-
webhookEventService.consumeWebhookEvent(eventType, payload)
481-
482-
verify {
483-
webSocketService.sendMessage(
484-
"$runId/organizations",
485-
any()
486-
)
487-
}
488-
}
489-
490432
fun createItemResponse(repoName: String, organization: String): ItemResponse {
491433
return ItemResponse(
492434
MANIFEST_FILE_NAME,

0 commit comments

Comments
 (0)