mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-05-25 00:42:22 -04:00
CI: Run PVS-Studio analysis on Windows
This commit is contained in:
40
.github/actions/windows-analysis/Invoke-External.ps1
vendored
Normal file
40
.github/actions/windows-analysis/Invoke-External.ps1
vendored
Normal 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}."
|
||||
}
|
||||
}
|
||||
149
.github/actions/windows-analysis/Logger.ps1
vendored
Normal file
149
.github/actions/windows-analysis/Logger.ps1
vendored
Normal 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
|
||||
90
.github/actions/windows-analysis/action.yaml
vendored
Normal file
90
.github/actions/windows-analysis/action.yaml
vendored
Normal 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)'
|
||||
10
.github/actions/windows-analysis/obs.pvsconfig
vendored
Normal file
10
.github/actions/windows-analysis/obs.pvsconfig
vendored
Normal 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
39
.github/workflows/analyze-project.yaml
vendored
Normal 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
|
||||
8
.github/workflows/scheduled.yaml
vendored
8
.github/workflows/scheduled.yaml
vendored
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user