CI: Run PVS-Studio analysis on Windows

This commit is contained in:
derrod
2024-05-23 01:04:16 +02:00
committed by Ryan Foster
parent b9de99a103
commit dff4dd9acf
6 changed files with 336 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
function Invoke-External {
<#
.SYNOPSIS
Invokes a non-PowerShell command.
.DESCRIPTION
Runs a non-PowerShell command, and captures its return code.
Throws an exception if the command returns non-zero.
.EXAMPLE
Invoke-External 7z x $MyArchive
#>
if ( $args.Count -eq 0 ) {
throw 'Invoke-External called without arguments.'
}
if ( ! ( Test-Path function:Log-Information ) ) {
. $PSScriptRoot/Logger.ps1
}
$Command = $args[0]
$CommandArgs = @()
if ( $args.Count -gt 1) {
$CommandArgs = $args[1..($args.Count - 1)]
}
$_EAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
Log-Debug "Invoke-External: ${Command} ${CommandArgs}"
& $command $commandArgs
$Result = $LASTEXITCODE
$ErrorActionPreference = $_EAP
if ( $Result -ne 0 ) {
throw "${Command} ${CommandArgs} exited with non-zero code ${Result}."
}
}

View File

@@ -0,0 +1,149 @@
function Log-Debug {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Debug $m
}
}
}
function Log-Verbose {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Verbose $m
}
}
}
function Log-Warning {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Warning $m
}
}
}
function Log-Error {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Error $m
}
}
}
function Log-Information {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $script:StageName -ne $null ) { $script:StageName } else { '' })
$Icon = ' =>'
foreach($m in $Message) {
Write-Host -NoNewLine -ForegroundColor Blue " ${StageName} $($Icon.PadRight(5)) "
Write-Host "${m}"
}
}
}
}
function Log-Group {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[string[]] $Message
)
Process {
if ( $Env:CI -ne $null ) {
if ( $script:LogGroup ) {
Write-Output '::endgroup::'
$script:LogGroup = $false
}
if ( $Message.count -ge 1 ) {
Write-Output "::group::$($Message -join ' ')"
$script:LogGroup = $true
}
} else {
if ( $Message.count -ge 1 ) {
Log-Information $Message
}
}
}
}
function Log-Status {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $StageName -ne $null ) { $StageName } else { '' })
$Icon = ' >'
foreach($m in $Message) {
Write-Host -NoNewLine -ForegroundColor Green " ${StageName} $($Icon.PadRight(5)) "
Write-Host "${m}"
}
}
}
}
function Log-Output {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $script:StageName -ne $null ) { $script:StageName } else { '' })
$Icon = ''
foreach($m in $Message) {
Write-Output " ${StageName} $($Icon.PadRight(5)) ${m}"
}
}
}
}
$Columns = (Get-Host).UI.RawUI.WindowSize.Width - 5

View File

@@ -0,0 +1,90 @@
name: Run PVS-Studio Analysis
inputs:
pvsUsername:
description: PVS-Studio License Username
required: true
pvsKey:
description: PVS-Studio License Key
required: true
target:
description: Build Target
required: true
config:
description: Build Configuration
required: true
runs:
using: composite
steps:
- name: Setup PVS-Studio
shell: pwsh
run: |
choco install pvs-studio --version=7.30.81185.980 -y --no-progress
- name: Activate PVS-Studio
shell: pwsh
run: |
. ${env:GITHUB_ACTION_PATH}\Invoke-External.ps1
Invoke-External "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials -u ${{ inputs.pvsUsername }} -n ${{ inputs.pvsKey }}
- name: Run PVS-Studio Analysis
shell: pwsh
run: |
[flags()] Enum PVSErrorCodes {
Success = 0
AnalyzerCrash = 1
GenericError = 2
InvalidCommandLine = 4
FileNotFound = 8
ConfigurationNotFound = 16
InvalidProject = 32
InvalidExtension = 64
LicenseInvalid = 128
CodeErrorsFound = 256
SuppressionFailed = 512
LicenseExpiringSoon = 1024
}
$pvsParams = @(
"--progress"
"--disableLicenseExpirationCheck"
"-p", "${{ inputs.target }}"
"-c", "${{ inputs.config }}"
"-t", "${{ github.workspace }}\build_x64\obs-studio.sln"
"-o", "${{ github.workspace }}\analysis.plog"
"-C", "${env:GITHUB_ACTION_PATH}\obs.pvsconfig"
)
& "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" @pvsParams
# Success and CodeErrorsFound are fine as error codes, we only care if it is anything but those
$pvs_result = $LASTEXITCODE -band (-bnot [PVSErrorCodes]::CodeErrorsFound)
if ($pvs_result -ne 0) {
Write-Output "PVS-Studio Errors: $([PVSErrorCodes]$pvs_result)"
}
exit $pvs_result
- name: Convert Analysis to SARIF
shell: pwsh
run: |
. ${env:GITHUB_ACTION_PATH}\Invoke-External.ps1
$conversionParams = @(
"-a", "GA:1,2",
"-d", "V1042,Renew"
"-t", "Sarif"
"${{ github.workspace }}\analysis.plog"
)
Invoke-External "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" @conversionParams
- name: Upload PVS-Studio Logs
uses: actions/upload-artifact@v4
with:
name: 'pvs-analysis-log'
path: |
${{ github.workspace }}/analysis.plog
${{ github.workspace }}/analysis.plog.sarif
- name: Upload PVS-Studio Report
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "${{ github.workspace }}/analysis.plog.sarif"
category: 'PVS-Studio (Windows)'

View File

@@ -0,0 +1,10 @@
//V_EXCLUDE_PATH */.deps/*
//V_EXCLUDE_PATH */blake2/*
//V_EXCLUDE_PATH */json11/*
//V_EXCLUDE_PATH */simde/*
//V_EXCLUDE_PATH */w32-pthreads/*
//V_EXCLUDE_PATH */plugins/obs-browser/*
//V_EXCLUDE_PATH */plugins/obs-outputs/ftl-sdk/*
//V_EXCLUDE_PATH */plugins/obs-websocket/*
//V_EXCLUDE_PATH */plugins/win-dshow/libdshowcapture/*
//V_EXCLUDE_PATH *_autogen/*

39
.github/workflows/analyze-project.yaml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Analyze Project
on:
workflow_call:
jobs:
windows:
name: Windows 🪟 (PVS-Studio)
runs-on: windows-2022
defaults:
run:
shell: pwsh
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Build OBS Studio 🧱
uses: ./.github/actions/build-obs
env:
TWITCH_CLIENTID: ${{ secrets.TWITCH_CLIENT_ID }}
TWITCH_HASH: ${{ secrets.TWITCH_HASH }}
RESTREAM_CLIENTID: ${{ secrets.RESTREAM_CLIENTID }}
RESTREAM_HASH: ${{ secrets.RESTREAM_HASH }}
YOUTUBE_CLIENTID: ${{ secrets.YOUTUBE_CLIENTID }}
YOUTUBE_CLIENTID_HASH: ${{ secrets.YOUTUBE_CLIENTID_HASH }}
YOUTUBE_SECRET: ${{ secrets.YOUTUBE_SECRET }}
YOUTUBE_SECRET_HASH: ${{ secrets.YOUTUBE_SECRET_HASH }}
GPU_PRIORITY_VAL: ${{ secrets.GPU_PRIORITY_VAL }}
with:
target: x64
config: Debug
- name: Run PVS-Studio Analysis
uses: ./.github/actions/windows-analysis
with:
pvsUsername: ${{ secrets.PVS_NAME }}
pvsKey: ${{ secrets.PVS_KEY }}
target: x64
config: Debug

View File

@@ -88,6 +88,14 @@ jobs:
needs: cache-cleanup
secrets: inherit
analyze-project:
name: Analyze 🔬
uses: ./.github/workflows/analyze-project.yaml
needs: cache-cleanup
secrets: inherit
permissions:
security-events: write
upload-language-files:
name: Upload Language Files 🌐
if: github.repository_owner == 'obsproject' && github.ref_name == 'master'