Skip to content

Commit

Permalink
Merge pull request #32 from leanix/feature/-CID-3105/React-to-manifes…
Browse files Browse the repository at this point in the history
…t-file-creation-via-Webhook

CID-3105: React to manifest file creation via Webhook
  • Loading branch information
mohamedlajmileanix authored Nov 4, 2024
2 parents be85526 + 79fbb02 commit 59ffd77
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 105 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ The SAP LeanIX agent discovers self-built software in self-hosted GitHub Enterpr
- `GITHUB_ENTERPRISE_BASE_URL`: The base URL of your GitHub Enterprise Server instance.
- `GITHUB_APP_ID`: The ID of your GitHub App.
- `PEM_FILE`: The path to your GitHub App's PEM file inside the Docker container.
- `MANIFEST_FILE_DIRECTORY`: The directory path where the manifest files are stored in each repository. Manifest files are crucial for microservice discovery as they provide essential information about the service. For more information, see [Microservice Discovery Through a Manifest File](https://docs-eam.leanix.net/reference/microservice-discovery-manifest-file) in our documentation. **If both .yaml and .yml files exist in a repository, only the .yaml file will be used.**
- `WEBHOOK_SECRET`: The secret used to validate incoming webhook events from GitHub. (Optional, but recommended. [Needs to be set in the GitHub App settings first](https://docs.github.com/en/enterprise-server@3.8/webhooks/using-webhooks/validating-webhook-deliveries).)

5. **Start the agent**: To start the agent, run the following Docker command. Replace the variables in angle brackets with your actual values.
Expand All @@ -38,7 +37,6 @@ The SAP LeanIX agent discovers self-built software in self-hosted GitHub Enterpr
-e GITHUB_ENTERPRISE_BASE_URL=<github_enterprise_base_url> \
-e GITHUB_APP_ID=<github_app_id> \
-e PEM_FILE=/privateKey.pem \
-e MANIFEST_FILE_DIRECTORY=<manifest_file_directory> \
-e WEBHOOK_SECRET=<webhook_secret> \
leanix-github-agent
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ data class GitHubEnterpriseProperties(
val baseUrl: String,
val gitHubAppId: String,
val pemFile: String,
val manifestFileDirectory: String,
val webhookSecret: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package net.leanix.githubagent.dto
data class ManifestFileUpdateDto(
val repositoryFullName: String,
val action: ManifestFileAction,
val manifestFileContent: String?
val manifestFileContent: String?,
val manifestFilePath: String?
)

enum class ManifestFileAction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import net.leanix.githubagent.dto.RepositoryDto
import net.leanix.githubagent.dto.Trigger
import net.leanix.githubagent.exceptions.JwtTokenNotFound
import net.leanix.githubagent.exceptions.ManifestFileNotFoundException
import net.leanix.githubagent.shared.ManifestFileName
import net.leanix.githubagent.shared.MANIFEST_FILE_NAME
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.util.UUID
Expand Down Expand Up @@ -141,7 +141,7 @@ class GitHubScanningService(
gitHubClient.searchManifestFiles(
"Bearer $installationToken",
"" +
"repo:${installation.account.login}/$repositoryName filename:${ManifestFileName.YAML.fileName}"
"repo:${installation.account.login}/$repositoryName filename:$MANIFEST_FILE_NAME"
)
}
private fun fetchManifestContents(
Expand All @@ -163,7 +163,7 @@ class GitHubScanningService(
numOfManifestFilesFound++
syncLogService.sendInfoLog("Fetched manifest file ${manifestFile.path} from repository $repositoryName")
ManifestFileDTO(
path = manifestFile.path.replace("/${ManifestFileName.YAML.fileName}", ""),
path = manifestFile.path.replace("/$MANIFEST_FILE_NAME", ""),
content = content
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ 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.PushEventCommit
import net.leanix.githubagent.dto.PushEventPayload
import net.leanix.githubagent.shared.ManifestFileName
import net.leanix.githubagent.shared.MANIFEST_FILE_NAME
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service

@Service
class WebhookEventService(
private val webSocketService: WebSocketService,
private val gitHubGraphQLService: GitHubGraphQLService,
private val gitHubEnterpriseProperties: GitHubEnterpriseProperties,
private val cachingService: CachingService,
private val gitHubAuthenticationService: GitHubAuthenticationService
) {
Expand Down Expand Up @@ -53,47 +51,41 @@ class WebhookEventService(
}
}

@SuppressWarnings("LongParameterList")
private fun handleManifestFileChanges(
headCommit: PushEventCommit,
repositoryFullName: String,
owner: String,
repositoryName: String,
installationToken: String
) {
val yamlFileName = "${gitHubEnterpriseProperties.manifestFileDirectory}${ManifestFileName.YAML.fileName}"
val ymlFileName = "${gitHubEnterpriseProperties.manifestFileDirectory}${ManifestFileName.YML.fileName}"
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 isYAMLFileUpdated = isManifestFileUpdated(headCommit, yamlFileName)
val isYMLFileUpdated = isManifestFileUpdated(headCommit, ymlFileName)
addedManifestFiles.forEach { filePath ->
handleAddedOrModifiedManifestFile(
repositoryFullName,
owner,
repositoryName,
installationToken,
filePath,
ManifestFileAction.ADDED
)
}

if (!isYAMLFileUpdated && isYMLFileUpdated) {
val yamlFileContent = gitHubGraphQLService.getManifestFileContent(
modifiedManifestFiles.forEach { filePath ->
handleAddedOrModifiedManifestFile(
repositoryFullName,
owner,
repositoryName,
yamlFileName,
installationToken
installationToken,
filePath,
ManifestFileAction.MODIFIED
)
if (yamlFileContent != null) return
}

val manifestFilePath = determineManifestFilePath(isYAMLFileUpdated, isYMLFileUpdated, yamlFileName, ymlFileName)
manifestFilePath?.let {
when (it) {
in headCommit.added, in headCommit.modified -> {
handleAddedOrModifiedManifestFile(
headCommit,
repositoryFullName,
owner,
repositoryName,
installationToken,
it
)
}
in headCommit.removed -> {
handleRemovedManifestFile(repositoryFullName)
}
}
removedManifestFiles.forEach { filePath ->
handleRemovedManifestFile(repositoryFullName)
}
}

Expand All @@ -107,36 +99,23 @@ class WebhookEventService(
return installationToken
}

private fun isManifestFileUpdated(headCommit: PushEventCommit, fileName: String): Boolean {
return headCommit.added.any { it == fileName } ||
headCommit.modified.any { it == fileName } ||
headCommit.removed.any { it == fileName }
}

private fun determineManifestFilePath(
isYAMLFileUpdated: Boolean,
isYMLFileUpdated: Boolean,
yamlFileName: String,
ymlFileName: String
): String? {
return when {
isYAMLFileUpdated -> yamlFileName
isYMLFileUpdated -> ymlFileName
else -> null
}
}

@SuppressWarnings("LongParameterList")
private fun handleAddedOrModifiedManifestFile(
headCommit: PushEventCommit,
repositoryFullName: String,
owner: String,
repositoryName: String,
installationToken: String,
manifestFilePath: String
manifestFilePath: String,
action: ManifestFileAction
) {
val action = if (manifestFilePath in headCommit.added) ManifestFileAction.ADDED else ManifestFileAction.MODIFIED
logger.info("Manifest file $action in repository $repositoryFullName")
val location = if ('/' in manifestFilePath) {
"directory '/${manifestFilePath.substringBeforeLast('/')}'"
} else {
"root folder"
}

logger.info("Manifest file {} in repository {} under {}", action, repositoryFullName, location)

val fileContent = gitHubGraphQLService.getManifestFileContent(
owner,
repositoryName,
Expand All @@ -148,7 +127,8 @@ class WebhookEventService(
ManifestFileUpdateDto(
repositoryFullName,
action,
fileContent
fileContent,
manifestFilePath
)
)
}
Expand All @@ -160,6 +140,7 @@ class WebhookEventService(
ManifestFileUpdateDto(
repositoryFullName,
ManifestFileAction.REMOVED,
null,
null
)
)
Expand Down
6 changes: 1 addition & 5 deletions src/main/kotlin/net/leanix/githubagent/shared/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ package net.leanix.githubagent.shared
const val TOPIC_PREFIX = "/app/ghe/"
const val APP_NAME_TOPIC = "appName"
const val LOGS_TOPIC = "logs"

enum class ManifestFileName(val fileName: String) {
YAML("leanix.yaml"),
YML("leanix.yml")
}
const val MANIFEST_FILE_NAME = "leanix.yml"

val SUPPORTED_EVENT_TYPES = listOf(
"REPOSITORY",
Expand Down
Loading

0 comments on commit 59ffd77

Please sign in to comment.