Skip to content

Commit 57641a8

Browse files
Merge branch 'main' into feature/cid-3582-process-workflow-run-events
2 parents d3ee3a7 + bfaae4f commit 57641a8

File tree

6 files changed

+253
-7
lines changed

6 files changed

+253
-7
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
22

33
plugins {
4-
id("org.springframework.boot") version "3.4.2"
4+
id("org.springframework.boot") version "3.4.3"
55
id("io.spring.dependency-management") version "1.1.5"
66
id("com.expediagroup.graphql") version "8.3.0"
77
id("io.gitlab.arturbosch.detekt") version "1.23.7"

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class GitHubScanningService(
129129

130130
fun fetchManifestFilesAndSend(installation: Installation, repository: RepositoryDto) {
131131
if (repository.archived) return
132-
val manifestFiles = fetchManifestFiles(installation, repository.name).getOrThrow().items
132+
val manifestFiles = fetchManifestFiles(installation, repository.name).getOrThrow()
133133
val manifestFilesContents = fetchManifestContents(
134134
installation,
135135
manifestFiles,
@@ -149,13 +149,14 @@ class GitHubScanningService(
149149

150150
private fun fetchManifestFiles(installation: Installation, repositoryName: String) = runCatching {
151151
val installationToken = cachingService.get("installationToken:${installation.id}").toString()
152-
rateLimitHandler.executeWithRateLimitHandler(RateLimitType.SEARCH) {
152+
val manifestFiles = rateLimitHandler.executeWithRateLimitHandler(RateLimitType.SEARCH) {
153153
gitHubClient.searchManifestFiles(
154154
"Bearer $installationToken",
155155
"" +
156156
"repo:${installation.account.login}/$repositoryName filename:$MANIFEST_FILE_NAME"
157157
)
158158
}
159+
manifestFiles.items.filter { it.name.lowercase() == MANIFEST_FILE_NAME }
159160
}
160161
private fun fetchManifestContents(
161162
installation: Installation,

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ class WebhookEventService(
113113
repositoryName: String,
114114
installationToken: String
115115
) {
116-
val addedManifestFiles = headCommit.added.filter { it.contains(MANIFEST_FILE_NAME) }
117-
val modifiedManifestFiles = headCommit.modified.filter { it.contains(MANIFEST_FILE_NAME) }
118-
val removedManifestFiles = headCommit.removed.filter { it.contains(MANIFEST_FILE_NAME) }
116+
val addedManifestFiles = headCommit.added.filter { isLeanixManifestFile(it.lowercase()) }
117+
val modifiedManifestFiles = headCommit.modified.filter { isLeanixManifestFile(it.lowercase()) }
118+
val removedManifestFiles = headCommit.removed.filter { isLeanixManifestFile(it.lowercase()) }
119119

120120
addedManifestFiles.forEach { filePath ->
121121
handleAddedOrModifiedManifestFile(
@@ -146,6 +146,8 @@ class WebhookEventService(
146146
}
147147
}
148148

149+
private fun isLeanixManifestFile(it: String) = it == MANIFEST_FILE_NAME || it.endsWith("/$MANIFEST_FILE_NAME")
150+
149151
@SuppressWarnings("LongParameterList")
150152
private fun handleAddedOrModifiedManifestFile(
151153
repositoryFullName: String,

src/main/kotlin/net/leanix/githubagent/shared/Constants.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ val SUPPORTED_EVENT_TYPES = listOf(
1414
WORKFLOW_RUN_EVENT
1515
)
1616

17-
val fileNameMatchRegex = Regex("/?$MANIFEST_FILE_NAME\$")
17+
val fileNameMatchRegex = Regex("/?$MANIFEST_FILE_NAME\$", RegexOption.IGNORE_CASE)
1818

1919
const val GITHUB_APP_LABEL = "GitHub App"
2020
const val INSTALLATION_LABEL = "Installation"

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

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,147 @@ class GitHubScanningServiceTest {
288288
assertEquals(fileSlot.captured.manifestFiles[0].path, "")
289289
}
290290

291+
@Test
292+
fun `scanGitHubResources should not send manifest files over WebSocket for manifest files with wrong name`() {
293+
// given
294+
every { cachingService.get("runId") } returns runId
295+
every { gitHubGraphQLService.getRepositories(any(), any()) } returns PagedRepositories(
296+
repositories = listOf(
297+
RepositoryDto(
298+
id = "repo1",
299+
name = "TestRepo",
300+
organizationName = "testOrg",
301+
description = "A test repository",
302+
url = "https://github.com/testRepo",
303+
defaultBranch = "main",
304+
archived = false,
305+
visibility = RepositoryVisibility.PUBLIC,
306+
updatedAt = "2024-01-01T00:00:00Z",
307+
languages = listOf("Kotlin", "Java"),
308+
topics = listOf("test", "example"),
309+
)
310+
),
311+
hasNextPage = false,
312+
cursor = null
313+
)
314+
every { gitHubClient.searchManifestFiles(any(), any()) } returns GitHubSearchResponse(
315+
1,
316+
listOf(
317+
ItemResponse(
318+
name = MANIFEST_FILE_NAME,
319+
path = MANIFEST_FILE_NAME,
320+
repository = RepositoryItemResponse(
321+
name = "TestRepo",
322+
fullName = "testOrg/TestRepo"
323+
),
324+
url = "http://url"
325+
),
326+
ItemResponse(
327+
name = MANIFEST_FILE_NAME,
328+
path = "a/$MANIFEST_FILE_NAME",
329+
repository = RepositoryItemResponse(
330+
name = "TestRepo",
331+
fullName = "testOrg/TestRepo"
332+
),
333+
url = "http://url"
334+
),
335+
ItemResponse(
336+
name = "a-$MANIFEST_FILE_NAME",
337+
path = "a/a-$MANIFEST_FILE_NAME",
338+
repository = RepositoryItemResponse(
339+
name = "TestRepo",
340+
fullName = "testOrg/TestRepo"
341+
),
342+
url = "http://url"
343+
)
344+
)
345+
)
346+
every { gitHubGraphQLService.getManifestFileContent(any(), any(), MANIFEST_FILE_NAME, any()) } returns "content"
347+
every {
348+
gitHubGraphQLService.getManifestFileContent(any(), any(), "a/$MANIFEST_FILE_NAME", any())
349+
} returns "content"
350+
351+
// when
352+
gitHubScanningService.scanGitHubResources()
353+
354+
// then
355+
verify(exactly = 1) { webSocketService.sendMessage(eq("$runId/manifestFiles"), any()) }
356+
verify(exactly = 1) { syncLogService.sendInfoLog("Scanning repository TestRepo for manifest files.") }
357+
verify(exactly = 1) { syncLogService.sendInfoLog("Found 2 manifest files in repository TestRepo.") }
358+
}
359+
360+
@Test
361+
fun `scanGitHubResources should accept manifest files with case ignored`() {
362+
// given
363+
every { cachingService.get("runId") } returns runId
364+
every { gitHubGraphQLService.getRepositories(any(), any()) } returns PagedRepositories(
365+
repositories = listOf(
366+
RepositoryDto(
367+
id = "repo1",
368+
name = "TestRepo",
369+
organizationName = "testOrg",
370+
description = "A test repository",
371+
url = "https://github.com/testRepo",
372+
defaultBranch = "main",
373+
archived = false,
374+
visibility = RepositoryVisibility.PUBLIC,
375+
updatedAt = "2024-01-01T00:00:00Z",
376+
languages = listOf("Kotlin", "Java"),
377+
topics = listOf("test", "example"),
378+
)
379+
),
380+
hasNextPage = false,
381+
cursor = null
382+
)
383+
every { gitHubClient.searchManifestFiles(any(), any()) } returns GitHubSearchResponse(
384+
1,
385+
listOf(
386+
ItemResponse(
387+
name = "leanIX.yaml",
388+
path = "leanIX.yaml",
389+
repository = RepositoryItemResponse(
390+
name = "TestRepo",
391+
fullName = "testOrg/TestRepo"
392+
),
393+
url = "http://url"
394+
),
395+
ItemResponse(
396+
name = "lEAnIX.yaml",
397+
path = "a/lEAnIX.yaml",
398+
repository = RepositoryItemResponse(
399+
name = "TestRepo",
400+
fullName = "testOrg/TestRepo"
401+
),
402+
url = "http://url"
403+
),
404+
ItemResponse(
405+
name = MANIFEST_FILE_NAME,
406+
path = "b/$MANIFEST_FILE_NAME",
407+
repository = RepositoryItemResponse(
408+
name = "TestRepo",
409+
fullName = "testOrg/TestRepo"
410+
),
411+
url = "http://url"
412+
)
413+
)
414+
)
415+
every {
416+
gitHubGraphQLService.getManifestFileContent(any(), any(), "b/leanix.yaml", any())
417+
} returns "content"
418+
every {
419+
gitHubGraphQLService.getManifestFileContent(any(), any(), "leanIX.yaml", any())
420+
} returns "content"
421+
every {
422+
gitHubGraphQLService.getManifestFileContent(any(), any(), "a/lEAnIX.yaml", any())
423+
} returns "content"
424+
425+
// when
426+
gitHubScanningService.scanGitHubResources()
427+
428+
// then
429+
verify(exactly = 1) { syncLogService.sendInfoLog("Found 3 manifest files in repository TestRepo.") }
430+
}
431+
291432
@Test
292433
fun `scanGitHubResources should skip organizations without correct permissions and events`() {
293434
every { cachingService.get("runId") } returns runId

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

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,108 @@ class WebhookEventServiceTest {
9898
}
9999
}
100100

101+
@Test
102+
fun `should not process push event with wrong name`() {
103+
val payload = """{
104+
"repository": {
105+
"name": "repo",
106+
"full_name": "owner/repo",
107+
"owner": {"name": "owner"},
108+
"default_branch": "main"
109+
},
110+
"head_commit": {
111+
"added": [],
112+
"modified": ["$MANIFEST_FILE_NAME", "a-$MANIFEST_FILE_NAME", "a/$MANIFEST_FILE_NAME", "a/a-$MANIFEST_FILE_NAME"],
113+
"removed": []
114+
},
115+
"installation": {"id": 1},
116+
"ref": "refs/heads/main"
117+
}"""
118+
119+
webhookEventService.consumeWebhookEvent("PUSH", payload)
120+
121+
verify(exactly = 1) {
122+
webSocketService.sendMessage(
123+
"/events/manifestFile",
124+
ManifestFileUpdateDto(
125+
"owner/repo",
126+
ManifestFileAction.MODIFIED,
127+
"content",
128+
""
129+
)
130+
)
131+
}
132+
133+
verify(exactly = 1) {
134+
webSocketService.sendMessage(
135+
"/events/manifestFile",
136+
ManifestFileUpdateDto(
137+
"owner/repo",
138+
ManifestFileAction.MODIFIED,
139+
"content",
140+
"tree/main/a"
141+
)
142+
)
143+
}
144+
}
145+
146+
@Test
147+
fun `should accept manifest files with case ignore`() {
148+
val payload = """{
149+
"repository": {
150+
"name": "repo",
151+
"full_name": "owner/repo",
152+
"owner": {"name": "owner"},
153+
"default_branch": "main"
154+
},
155+
"head_commit": {
156+
"added": [],
157+
"modified": ["a/$MANIFEST_FILE_NAME", "b/leanIX.yaml", "LEanIX.yaml"],
158+
"removed": []
159+
},
160+
"installation": {"id": 1},
161+
"ref": "refs/heads/main"
162+
}"""
163+
164+
webhookEventService.consumeWebhookEvent("PUSH", payload)
165+
166+
verify(exactly = 1) {
167+
webSocketService.sendMessage(
168+
"/events/manifestFile",
169+
ManifestFileUpdateDto(
170+
"owner/repo",
171+
ManifestFileAction.MODIFIED,
172+
"content",
173+
"tree/main/b"
174+
)
175+
)
176+
}
177+
178+
verify(exactly = 1) {
179+
webSocketService.sendMessage(
180+
"/events/manifestFile",
181+
ManifestFileUpdateDto(
182+
"owner/repo",
183+
ManifestFileAction.MODIFIED,
184+
"content",
185+
"tree/main/a"
186+
)
187+
)
188+
}
189+
190+
verify(exactly = 1) {
191+
webSocketService.sendMessage(
192+
"/events/manifestFile",
193+
ManifestFileUpdateDto(
194+
"owner/repo",
195+
ManifestFileAction.MODIFIED,
196+
"content",
197+
""
198+
)
199+
)
200+
}
201+
}
202+
101203
@Test
102204
fun `should send all events of type other than push to backend without processing`() {
103205
val payload = """{

0 commit comments

Comments
 (0)