Skip to content

Commit 8660e99

Browse files
nnobelisoheger-bosch
authored andcommitted
feat(Fossid-webapp): Change the delta scan matching logic
The current implementation carries the wrong identifications when creating a delta scan for a given branch: when such a delta scan is created, the identifications reused are the ones for that latest successful scan of the repository. This leads to wrong pending files in the UI because these identifications can concern another branch with snippets that don't exist in the current one. Therefore, the logic needs to be adapted as follows: When a delta scan is created for a branch, one must first find the latest completed scan on this branch and carry its identification. If no such scan has been found, the latest scan on the default branch of the repository must be chosen and its identifications taken. If still no scan has been found, the current behavior must apply. Signed-off-by: Nicolas Nobelis <[email protected]>
1 parent 2750d99 commit 8660e99

File tree

2 files changed

+243
-39
lines changed

2 files changed

+243
-39
lines changed

scanner/src/main/kotlin/scanners/fossid/FossId.kt

+42-13
Original file line numberDiff line numberDiff line change
@@ -353,19 +353,39 @@ class FossId internal constructor(
353353
}
354354

355355
/**
356-
* Filter this list of [Scan]s for the repository defined by [url] and an optional [revision] and sort it by
357-
* scan ID, so that the most recent scan comes first and the oldest scan comes last.
356+
* Filter this list of [Scan]s for the repository defined by [url] and Git [reference<]. If no scan is found with
357+
* these criteria, search for scans of the default branch [defaultBranch]. If still no scan is found, all scans for
358+
* this repository are taken, filtered by an optional [revision].
359+
* Scans returned are sorted by scan ID, so that the most recent scan comes first and the oldest scan comes last.
358360
*/
359361
private fun List<Scan>.recentScansForRepository(
360362
url: String,
361-
revision: String? = null
362-
): List<Scan> = filter {
363-
val isArchived = it.isArchived ?: false
364-
// The scans in the server contain the url with the credentials, so we have to remove it for the
365-
// comparison. If we don't, the scans won't be matched if the password changes!
366-
val urlWithoutCredentials = it.gitRepoUrl?.replaceCredentialsInUri()
367-
!isArchived && urlWithoutCredentials == url && (revision == null || it.gitBranch == revision)
368-
}.sortedByDescending { scan -> scan.id }
363+
revision: String? = null,
364+
projectRevision: String? = null,
365+
defaultBranch: String? = null,
366+
): List<Scan> {
367+
val scans = filter {
368+
val isArchived = it.isArchived ?: false
369+
// The scans in the server contain the url with the credentials, so we have to remove it for the
370+
// comparison. If we don't, the scans won't be matched if the password changes!
371+
val urlWithoutCredentials = it.gitRepoUrl?.replaceCredentialsInUri()
372+
!isArchived && urlWithoutCredentials == url
373+
}.sortedByDescending { it.id }
374+
375+
return scans.filter { scan -> projectRevision == scan.comment }.ifEmpty {
376+
logger.warn {
377+
"No recent scan found for project revision $projectRevision. Falling back to default branch scans."
378+
}
379+
380+
scans.filter { scan ->
381+
defaultBranch?.let { scan.comment == defaultBranch } ?: false
382+
}.ifEmpty {
383+
logger.warn { "No recent default branch scan found. Falling back to old behavior." }
384+
385+
scans.filter { revision == null || it.gitBranch == revision }
386+
}
387+
}
388+
}
369389

370390
/**
371391
* Call FossID service, initiate a scan and return scan data: Scan Code and Scan Id
@@ -377,7 +397,7 @@ class FossId internal constructor(
377397
projectCode: String,
378398
projectName: String
379399
): Pair<String, String> {
380-
val existingScan = scans.recentScansForRepository(url, revision).findLatestPendingOrFinishedScan()
400+
val existingScan = scans.recentScansForRepository(url, revision = revision).findLatestPendingOrFinishedScan()
381401

382402
val scanCodeAndId = if (existingScan == null) {
383403
logger.info { "No scan found for $url and revision $revision. Creating scan..." }
@@ -444,7 +464,11 @@ class FossId internal constructor(
444464
}
445465

446466
// we ignore the revision because we want to do a delta scan
447-
val recentScans = scans.recentScansForRepository(urlWithoutCredentials)
467+
val recentScans = scans.recentScansForRepository(
468+
urlWithoutCredentials,
469+
projectRevision = projectRevision,
470+
defaultBranch = defaultBranch
471+
)
448472

449473
logger.info { "Found ${recentScans.size} scans." }
450474

@@ -454,7 +478,10 @@ class FossId internal constructor(
454478
logger.info { "No scan found for $urlWithoutCredentials and revision $revision. Creating origin scan..." }
455479
namingProvider.createScanCode(projectName, DeltaTag.ORIGIN, branchLabel)
456480
} else {
457-
logger.info { "Scan found for $urlWithoutCredentials and revision $revision. Creating delta scan..." }
481+
logger.info { "Scan '${existingScan.code}' found for $urlWithoutCredentials and revision $revision." }
482+
logger.info {
483+
"Existing scan has for reference(s): ${existingScan.comment.orEmpty()}. Creating delta scan..."
484+
}
458485
namingProvider.createScanCode(projectName, DeltaTag.DELTA, branchLabel)
459486
}
460487

@@ -511,6 +538,8 @@ class FossId internal constructor(
511538
/**
512539
* Make sure that only the configured number of delta scans exists for the current package. Based on the list of
513540
* [existingScans], delete older scans until the maximum number of delta scans is reached.
541+
* Please note that in the case of delta scans, the [existingScans] are filtered by Git references or, in a case of
542+
* a fallback, filtered to be only default branch scans. Therefore, the delta scan limit is enforced per branch.
514543
*/
515544
private suspend fun enforceDeltaScanLimit(existingScans: List<Scan>) {
516545
logger.info { "Will retain up to ${config.deltaScanLimit} delta scans." }

0 commit comments

Comments
 (0)