Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class GitHubScanningService(

fun fetchManifestFilesAndSend(installation: Installation, repository: RepositoryDto) {
if (repository.archived) return
val manifestFiles = fetchManifestFiles(installation, repository.name).getOrThrow().items
val manifestFiles = fetchManifestFiles(installation, repository.name).getOrThrow()
val manifestFilesContents = fetchManifestContents(
installation,
manifestFiles,
Expand All @@ -149,13 +149,14 @@ class GitHubScanningService(

private fun fetchManifestFiles(installation: Installation, repositoryName: String) = runCatching {
val installationToken = cachingService.get("installationToken:${installation.id}").toString()
rateLimitHandler.executeWithRateLimitHandler(RateLimitType.SEARCH) {
val manifestFiles = rateLimitHandler.executeWithRateLimitHandler(RateLimitType.SEARCH) {
gitHubClient.searchManifestFiles(
"Bearer $installationToken",
"" +
"repo:${installation.account.login}/$repositoryName filename:$MANIFEST_FILE_NAME"
)
}
manifestFiles.items.filter { it.name.lowercase() == MANIFEST_FILE_NAME }
}
private fun fetchManifestContents(
installation: Installation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ class WebhookEventService(
repositoryName: String,
installationToken: String
) {
val addedManifestFiles = headCommit.added.filter { it.contains(MANIFEST_FILE_NAME) }
val modifiedManifestFiles = headCommit.modified.filter { it.contains(MANIFEST_FILE_NAME) }
val removedManifestFiles = headCommit.removed.filter { it.contains(MANIFEST_FILE_NAME) }
val addedManifestFiles = headCommit.added.filter { isLeanixManifestFile(it.lowercase()) }
val modifiedManifestFiles = headCommit.modified.filter { isLeanixManifestFile(it.lowercase()) }
val removedManifestFiles = headCommit.removed.filter { isLeanixManifestFile(it.lowercase()) }

addedManifestFiles.forEach { filePath ->
handleAddedOrModifiedManifestFile(
Expand Down Expand Up @@ -143,6 +143,8 @@ class WebhookEventService(
}
}

private fun isLeanixManifestFile(it: String) = it == MANIFEST_FILE_NAME || it.endsWith("/$MANIFEST_FILE_NAME")

private fun getInstallationToken(installationId: Int): String {
var installationToken = cachingService.get("installationToken:$installationId")?.toString()
if (installationToken == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ val SUPPORTED_EVENT_TYPES = listOf(
"INSTALLATION",
)

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

const val GITHUB_APP_LABEL = "GitHub App"
const val INSTALLATION_LABEL = "Installation"
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,147 @@ class GitHubScanningServiceTest {
assertEquals(fileSlot.captured.manifestFiles[0].path, "")
}

@Test
fun `scanGitHubResources should not send manifest files over WebSocket for manifest files with wrong name`() {
// given
every { cachingService.get("runId") } returns runId
every { gitHubGraphQLService.getRepositories(any(), any()) } returns PagedRepositories(
repositories = listOf(
RepositoryDto(
id = "repo1",
name = "TestRepo",
organizationName = "testOrg",
description = "A test repository",
url = "https://github.com/testRepo",
defaultBranch = "main",
archived = false,
visibility = RepositoryVisibility.PUBLIC,
updatedAt = "2024-01-01T00:00:00Z",
languages = listOf("Kotlin", "Java"),
topics = listOf("test", "example"),
)
),
hasNextPage = false,
cursor = null
)
every { gitHubClient.searchManifestFiles(any(), any()) } returns GitHubSearchResponse(
1,
listOf(
ItemResponse(
name = MANIFEST_FILE_NAME,
path = MANIFEST_FILE_NAME,
repository = RepositoryItemResponse(
name = "TestRepo",
fullName = "testOrg/TestRepo"
),
url = "http://url"
),
ItemResponse(
name = MANIFEST_FILE_NAME,
path = "a/$MANIFEST_FILE_NAME",
repository = RepositoryItemResponse(
name = "TestRepo",
fullName = "testOrg/TestRepo"
),
url = "http://url"
),
ItemResponse(
name = "a-$MANIFEST_FILE_NAME",
path = "a/a-$MANIFEST_FILE_NAME",
repository = RepositoryItemResponse(
name = "TestRepo",
fullName = "testOrg/TestRepo"
),
url = "http://url"
)
)
)
every { gitHubGraphQLService.getManifestFileContent(any(), any(), MANIFEST_FILE_NAME, any()) } returns "content"
every {
gitHubGraphQLService.getManifestFileContent(any(), any(), "a/$MANIFEST_FILE_NAME", any())
} returns "content"

// when
gitHubScanningService.scanGitHubResources()

// then
verify(exactly = 1) { webSocketService.sendMessage(eq("$runId/manifestFiles"), any()) }
verify(exactly = 1) { syncLogService.sendInfoLog("Scanning repository TestRepo for manifest files.") }
verify(exactly = 1) { syncLogService.sendInfoLog("Found 2 manifest files in repository TestRepo.") }
}

@Test
fun `scanGitHubResources should accept manifest files with case ignored`() {
// given
every { cachingService.get("runId") } returns runId
every { gitHubGraphQLService.getRepositories(any(), any()) } returns PagedRepositories(
repositories = listOf(
RepositoryDto(
id = "repo1",
name = "TestRepo",
organizationName = "testOrg",
description = "A test repository",
url = "https://github.com/testRepo",
defaultBranch = "main",
archived = false,
visibility = RepositoryVisibility.PUBLIC,
updatedAt = "2024-01-01T00:00:00Z",
languages = listOf("Kotlin", "Java"),
topics = listOf("test", "example"),
)
),
hasNextPage = false,
cursor = null
)
every { gitHubClient.searchManifestFiles(any(), any()) } returns GitHubSearchResponse(
1,
listOf(
ItemResponse(
name = "leanIX.yaml",
path = "leanIX.yaml",
repository = RepositoryItemResponse(
name = "TestRepo",
fullName = "testOrg/TestRepo"
),
url = "http://url"
),
ItemResponse(
name = "lEAnIX.yaml",
path = "a/lEAnIX.yaml",
repository = RepositoryItemResponse(
name = "TestRepo",
fullName = "testOrg/TestRepo"
),
url = "http://url"
),
ItemResponse(
name = MANIFEST_FILE_NAME,
path = "b/$MANIFEST_FILE_NAME",
repository = RepositoryItemResponse(
name = "TestRepo",
fullName = "testOrg/TestRepo"
),
url = "http://url"
)
)
)
every {
gitHubGraphQLService.getManifestFileContent(any(), any(), "b/leanix.yaml", any())
} returns "content"
every {
gitHubGraphQLService.getManifestFileContent(any(), any(), "leanIX.yaml", any())
} returns "content"
every {
gitHubGraphQLService.getManifestFileContent(any(), any(), "a/lEAnIX.yaml", any())
} returns "content"

// when
gitHubScanningService.scanGitHubResources()

// then
verify(exactly = 1) { syncLogService.sendInfoLog("Found 3 manifest files in repository TestRepo.") }
}

@Test
fun `scanGitHubResources should skip organizations without correct permissions and events`() {
every { cachingService.get("runId") } returns runId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,108 @@ class WebhookEventServiceTest {
}
}

@Test
fun `should not process push event with wrong name`() {
val payload = """{
"repository": {
"name": "repo",
"full_name": "owner/repo",
"owner": {"name": "owner"},
"default_branch": "main"
},
"head_commit": {
"added": [],
"modified": ["$MANIFEST_FILE_NAME", "a-$MANIFEST_FILE_NAME", "a/$MANIFEST_FILE_NAME", "a/a-$MANIFEST_FILE_NAME"],
"removed": []
},
"installation": {"id": 1},
"ref": "refs/heads/main"
}"""

webhookEventService.consumeWebhookEvent("PUSH", payload)

verify(exactly = 1) {
webSocketService.sendMessage(
"/events/manifestFile",
ManifestFileUpdateDto(
"owner/repo",
ManifestFileAction.MODIFIED,
"content",
""
)
)
}

verify(exactly = 1) {
webSocketService.sendMessage(
"/events/manifestFile",
ManifestFileUpdateDto(
"owner/repo",
ManifestFileAction.MODIFIED,
"content",
"tree/main/a"
)
)
}
}

@Test
fun `should accept manifest files with case ignore`() {
val payload = """{
"repository": {
"name": "repo",
"full_name": "owner/repo",
"owner": {"name": "owner"},
"default_branch": "main"
},
"head_commit": {
"added": [],
"modified": ["a/$MANIFEST_FILE_NAME", "b/leanIX.yaml", "LEanIX.yaml"],
"removed": []
},
"installation": {"id": 1},
"ref": "refs/heads/main"
}"""

webhookEventService.consumeWebhookEvent("PUSH", payload)

verify(exactly = 1) {
webSocketService.sendMessage(
"/events/manifestFile",
ManifestFileUpdateDto(
"owner/repo",
ManifestFileAction.MODIFIED,
"content",
"tree/main/b"
)
)
}

verify(exactly = 1) {
webSocketService.sendMessage(
"/events/manifestFile",
ManifestFileUpdateDto(
"owner/repo",
ManifestFileAction.MODIFIED,
"content",
"tree/main/a"
)
)
}

verify(exactly = 1) {
webSocketService.sendMessage(
"/events/manifestFile",
ManifestFileUpdateDto(
"owner/repo",
ManifestFileAction.MODIFIED,
"content",
""
)
)
}
}

@Test
fun `should send all events of type other than push to backend without processing`() {
val payload = """{
Expand Down
Loading