tasks/analysis.tasks.ps1
$covenantVersion = "0.12.0" $CovenantIncludeSpdxReport = $true $CovenantIncludeCycloneDxReport = $true $CovenantMetadata = @{ git_repo = $(if (Get-Command "gh" -ErrorAction SilentlyContinue) { & gh repo view --json nameWithOwner | ConvertFrom-Json | Select-Object -expandproperty nameWithOwner }) git_branch = $(if (Get-Command "git" -ErrorAction SilentlyContinue) {git branch --show-current }) git_sha = $(if (Get-Command "git" -ErrorAction SilentlyContinue) { & git rev-parse HEAD }) } # Defaults for publishing-related variables $PublishCovenantOutputToStorage = $false $AnalysisOutputStorageAccountName = "" $AnalysisOutputStorageAccountResourceGroup = "" $AnalysisOutputStorageAccountSubscription = "" $AnalysisOutputContainerName = "" $AnalysisOutputBlobPath = "" task InstallCovenantTool { Install-DotNetTool -Name covenant -Version $covenantVersion } # Synopsis: Setup SBOM metadata for Covenant command-line task PrepareCovenantMetadata { $script:covenantMetadataArgs = @() foreach ($key in $CovenantMetadata.Keys) { # NOTE: No space after the '-m' switch otherwise the metadata key has a leading space in the report $script:covenantMetadataArgs += "-m$key=$($CovenantMetadata[$key])" } } task RunCovenantTool -If { $SolutionToBuild } Version, InstallCovenantTool, PrepareCovenantMetadata,{ $baseOutputName = [IO.Path]::GetFileNameWithoutExtension($SolutionToBuild) # Ensure we have a fully-qualified path, as this will be needed when uploading on build server $script:covenantJsonOutputFile = Join-Path $here ("/{0}.sbom.json" -f $baseOutputName) $script:covenantSpdxOutputFile = Join-Path $here ("/{0}.sbom.spdx.json" -f $baseOutputName) $script:covenantCycloneDxOutputFile = Join-Path $here ("/{0}.sbom.cyclonedx.xml" -f $baseOutputName) $script:covenantHtmlReportFile = Join-Path $here ("/{0}.sbom.html" -f $baseOutputName) Write-Verbose "covenantHtmlReportFile: $covenantHtmlReportFile" # Generate SBOM exec { & dotnet-covenant ` generate ` $SolutionToBuild ` -v $script:GitVersion.SemVer ` --output $covenantJsonOutputFile ` $covenantMetadataArgs } # Generate HTML report exec { & dotnet-covenant ` report ` $covenantJsonOutputFile ` --output $covenantHtmlReportFile } } # Synopsis: Generate SPDX-formatted report task GenerateCovenantSpdxReport -If { $CovenantIncludeSpdxReport } { exec { & dotnet-covenant ` convert ` spdx ` $covenantJsonOutputFile ` --output $covenantSpdxOutputFile } Write-Verbose "covenantSpdxOutputFile: $covenantSpdxOutputFile" } # Synopsis: Generate CycloneDX-formatted report task GenerateCovenantCycloneDxReport -If { $CovenantIncludeCycloneDxReport } { exec { & dotnet-covenant ` convert ` cyclonedx ` $covenantJsonOutputFile ` --output $covenantCycloneDxOutputFile } Write-Verbose "covenantCycloneDxOutputFile: $covenantCycloneDxOutputFile" } task PublishCovenantBuildArtefacts -If { $IsAzureDevops } { Write-Host "##vso[task.setvariable variable=SbomHtmlReportPath;isoutput=true]$covenantHtmlReportFile" Write-Host "##vso[artifact.upload artifactname=SBOM]$covenantHtmlReportFile" Write-Host "##vso[artifact.upload artifactname=SBOM]$covenantJsonOutputFile" if ($CovenantIncludeSpdxReport) { Write-Host "##vso[artifact.upload artifactname=SBOM]$covenantSpdxOutputFile" } if ($CovenantIncludeCycloneDxReport) { Write-Host "##vso[artifact.upload artifactname=SBOM]$covenantCycloneDxOutputFile" } } task PublishCovenantOutputToStorage -If { $SolutionToBuild -and $PublishCovenantOutputToStorage } { if ( (Test-Path $covenantJsonOutputFile) -and ` $AnalysisOutputStorageAccountName -and ` $AnalysisOutputStorageAccountResourceGroup -and ` $AnalysisOutputStorageAccountSubscription -and ` $AnalysisOutputContainerName -and ` $AnalysisOutputBlobPath) { $covenantJsonOutputFilename = (Split-Path -Leaf $covenantJsonOutputFile) $filename = "{0}-{1}.json" -f [IO.Path]::GetFileNameWithoutExtension($covenantJsonOutputFilename), ([DateTime]::Now).ToString('yyyyMMddHHmmssfff') Write-Information @" Publishing storage account: Source File: $covenantJsonOutputFile Account: $AnalysisOutputStorageAccountName ResourceGroup: $AnalysisOutputStorageAccountResourceGroup Subscription: $AnalysisOutputStorageAccountSubscription Blob Path: "$AnalysisOutputContainerName/$AnalysisOutputBlobPath/$filename" "@ Set-AzContext -Subscription $AnalysisOutputStorageAccountSubscription $storage = Get-AzStorageAccount ` -Name $AnalysisOutputStorageAccountName ` -ResourceGroupName $AnalysisOutputStorageAccountResourceGroup Set-AzStorageBlobContent ` -File $covenantJsonOutputFile ` -Container $AnalysisOutputContainerName ` -Blob "$AnalysisOutputBlobPath/$filename" ` -Context $storage.Context | Out-Null Write-Information "Covenant JSON output published to storage account" } else { Write-Information "Publishing of Covenant output skipped, due to absent configuration" } } task RunCovenant RunCovenantTool, GenerateCovenantSpdxReport, GenerateCovenantCycloneDxReport, PublishCovenantBuildArtefacts, PublishCovenantOutputToStorage |