Skip to content

Code Quality

Code Quality #506

Workflow file for this run

name: Code Quality
# Comprehensive code quality checks
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
schedule:
# Run quality checks daily at 2 AM UTC
- cron: '0 2 * * *'
permissions:
contents: read
security-events: write
actions: read
env:
DOTNET_VERSION: '9.0.x'
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
jobs:
code-analysis:
name: 🔍 Code Analysis
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🔧 Setup Complete Environment
uses: ./.github/actions/setup-environment
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
enable-nuget-cache: true
- name: 🔨 Build and Test with Coverage
uses: ./.github/actions/build-and-test
with:
configuration: 'Release'
enable-coverage: true
- name: 📊 Upload coverage to Codecov
if: always()
uses: codecov/codecov-action@v4
with:
directory: artifacts/coverage/
fail_ci_if_error: false
verbose: false
continue-on-error: true
- name: 📤 Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: code-analysis-results
path: |
artifacts/test-results/
artifacts/coverage/
if-no-files-found: warn
retention-days: 30
security-scan:
name: 🔒 Security Scan
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: 🔧 Setup Complete Environment
uses: ./.github/actions/setup-environment
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
enable-nuget-cache: true
- name: 🔍 Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: csharp
- name: 🔨 Build for Analysis
uses: ./.github/actions/build-and-test
with:
configuration: 'Release'
enable-coverage: false
skip-tests: true
- name: 🔬 Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: 🛡️ Run security audit
shell: pwsh
run: |
# Explicitly target the primary solution to avoid ambiguity when multiple .sln files exist
$sln = "AGI.Kapster.sln"
# Check for known vulnerabilities in NuGet packages
dotnet list $sln package --vulnerable --include-transitive 2>&1 | Tee-Object -FilePath "security-audit.log"
# Check for outdated packages
dotnet list $sln package --outdated 2>&1 | Tee-Object -FilePath "outdated-packages.log"
- name: 📄 Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: |
security-audit.log
outdated-packages.log
if-no-files-found: warn
retention-days: 30
# TODO: Re-enable performance tests when needed for complex performance-critical features
# performance-test:
# name: ⚡ Performance Test
# runs-on: ubuntu-latest
# if: github.event_name != 'schedule' # Skip on scheduled runs
#
# steps:
# - name: 📥 Checkout repository
# uses: actions/checkout@v4
# with:
# fetch-depth: 1
#
# - name: 🔧 Setup Complete Environment
# uses: ./.github/actions/setup-environment
# with:
# dotnet-version: ${{ env.DOTNET_VERSION }}
# enable-nuget-cache: true
#
# - name: 🔨 Build for Performance Testing
# uses: ./.github/actions/build-and-test
# with:
# configuration: 'Release'
# enable-coverage: false
# skip-tests: false
# cache-key-suffix: '-perf'
#
# - name: ⚡ Run performance tests
# shell: pwsh
# run: |
# if (Test-Path "tests/") {
# ./build.ps1 Test --configuration Release --test-filter "Category=Performance"
# } else {
# Write-Host "⚠️ No performance tests found, skipping..."
# }
#
# - name: 📊 Generate performance report
# shell: pwsh
# run: |
# # Basic performance metrics
# Write-Host "📊 Build Performance Metrics" | Tee-Object -FilePath "performance-report.md"
# Write-Host "=============================" | Tee-Object -Append -FilePath "performance-report.md"
# Write-Host "" | Tee-Object -Append -FilePath "performance-report.md"
#
# # Check assembly sizes
# Write-Host "## Assembly Sizes" | Tee-Object -Append -FilePath "performance-report.md"
# if (Test-Path "artifacts/publish") {
# Get-ChildItem "artifacts/publish" -Recurse -Filter "*.dll" |
# Sort-Object Length -Descending |
# Select-Object Name, @{Name="Size(MB)";Expression={[math]::Round($_.Length/1MB,2)}} |
# Format-Table | Out-String | Tee-Object -Append -FilePath "performance-report.md"
# } else {
# Write-Host "No publish artifacts found for analysis." | Tee-Object -Append -FilePath "performance-report.md"
# }
#
# # Build timing (if available)
# Write-Host "## Build Performance" | Tee-Object -Append -FilePath "performance-report.md"
# Write-Host "Build completed at: $(Get-Date)" | Tee-Object -Append -FilePath "performance-report.md"
#
# # Ensure file exists
# if (-not (Test-Path "performance-report.md")) {
# Write-Host "Creating fallback performance report..."
# "Performance report generated at $(Get-Date)" | Out-File -FilePath "performance-report.md"
# }
#
# - name: 📊 Upload performance report
# uses: actions/upload-artifact@v4
# if: always()
# with:
# name: performance-report
# path: performance-report.md
# if-no-files-found: warn
# retention-days: 30
quality-gate:
name: 🎯 Quality Gate
runs-on: ubuntu-latest
needs: [code-analysis, security-scan]
if: always()
steps:
- name: 📊 Evaluate quality metrics
shell: pwsh
run: |
Write-Host "🎯 Quality Gate Evaluation"
Write-Host "=========================="
$codeAnalysisResult = "${{ needs.code-analysis.result }}"
$securityScanResult = "${{ needs.security-scan.result }}"
Write-Host "Code Analysis: $codeAnalysisResult"
Write-Host "Security Scan: $securityScanResult"
Write-Host "Dependency Check: SKIPPED (requires GitHub Advanced Security)"
$allPassed = ($codeAnalysisResult -eq "success") -and
($securityScanResult -eq "success")
if ($allPassed) {
Write-Host "✅ Quality gate PASSED - All checks successful!"
} else {
Write-Host "❌ Quality gate FAILED - Some checks failed!"
if ($env:GITHUB_EVENT_NAME -eq "pull_request") {
Write-Host "::error::Quality gate failed. Please address the issues before merging."
exit 1
}
}