130 lines
4.3 KiB
Groovy
130 lines
4.3 KiB
Groovy
pipeline {
|
||
agent none
|
||
|
||
environment {
|
||
// Optional: tweak for speed
|
||
DOTNET_CLI_TELEMETRY_OPTOUT = '1'
|
||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1'
|
||
|
||
// Sonar: set host via withSonarQubeEnv; token via credentials below
|
||
SONAR_PROJECT_KEY = 'AS400-API'
|
||
SONAR_PROJECT_NAME = 'AS/400 API (.NET9)'
|
||
}
|
||
|
||
stages {
|
||
stage('Checkout') {
|
||
agent any
|
||
steps { checkout scm }
|
||
}
|
||
|
||
stage('SCA (Dependency Audit)') {
|
||
// Run inside official .NET 9 SDK image
|
||
agent {
|
||
docker { image 'mcr.microsoft.com/dotnet/sdk:9.0'; reuseNode true }
|
||
}
|
||
steps {
|
||
sh '''
|
||
dotnet --info
|
||
# 1) Built-in vulnerability audit (NuGet advisory DB)
|
||
dotnet restore
|
||
# dotnet list package --vulnerable exits 0 even when vulnerabilities found; use Jenkins Warnings NG to surface, or grep to fail on high
|
||
dotnet list package --vulnerable || true
|
||
|
||
# 2) (Optional) OWASP Dependency-Check via Docker
|
||
# Scans csproj/packages.lock.json for known CVEs
|
||
mkdir -p depcheck
|
||
docker run --rm \
|
||
-v "$PWD":/src \
|
||
-v "$PWD/depcheck":/report \
|
||
owasp/dependency-check:latest \
|
||
--scan /src \
|
||
--format "HTML" \
|
||
--out /report || true
|
||
echo "Dependency-Check report at depcheck/dependency-check-report.html"
|
||
'''
|
||
// You can archive the HTML report for viewing in Jenkins
|
||
archiveArtifacts artifacts: 'depcheck/**', allowEmptyArchive: true
|
||
}
|
||
}
|
||
|
||
stage('SAST + Coverage (SonarQube + Tests)') {
|
||
agent {
|
||
docker {
|
||
// Use SDK image; we’ll install scanner + reportgenerator inside
|
||
image 'mcr.microsoft.com/dotnet/sdk:9.0'
|
||
reuseNode true
|
||
}
|
||
}
|
||
environment {
|
||
SONAR_TOKEN = credentials('sonar-token')
|
||
}
|
||
steps {
|
||
withSonarQubeEnv('SonarQubeServer') {
|
||
sh '''
|
||
# Install dotnet tools we need
|
||
dotnet tool install --global dotnet-sonarscanner --version 7.*
|
||
dotnet tool install --global dotnet-reportgenerator-globaltool
|
||
export PATH="$PATH:/root/.dotnet/tools"
|
||
|
||
# Begin Sonar analysis (SAST + quality gates)
|
||
dotnet sonarscanner begin \
|
||
/k:"$SONAR_PROJECT_KEY" \
|
||
/n:"$SONAR_PROJECT_NAME" \
|
||
/d:sonar.host.url="$SONAR_HOST_URL" \
|
||
/d:sonar.login="$SONAR_TOKEN" \
|
||
/d:sonar.cs.opencover.reportsPaths="**/TestResults/**/coverage.opencover.xml" \
|
||
/d:sonar.coverage.exclusions="**/*.cshtml,**/Migrations/**"
|
||
|
||
# Build (needed for Sonar to analyze)
|
||
dotnet restore
|
||
dotnet build -c Release --no-restore
|
||
|
||
# Test + Coverage (OpenCover format for Sonar)
|
||
# This uses coverlet.msbuild (works without editing csproj)
|
||
# Generates: ./<testproject>/TestResults/<GUID>/coverage.opencover.xml
|
||
dotnet test -c Release --no-build \
|
||
/p:CollectCoverage=true \
|
||
/p:CoverletOutputFormat=opencover \
|
||
/p:CoverletOutput=./TestResults/coverage
|
||
|
||
# End Sonar (uploads results to server)
|
||
dotnet sonarscanner end /d:sonar.login="$SONAR_TOKEN"
|
||
|
||
# Optional: create a single Cobertura report for Jenkins UI
|
||
reportgenerator \
|
||
-reports:**/TestResults/**/coverage.opencover.xml \
|
||
-targetdir:coverage-report \
|
||
-reporttypes:Cobertura
|
||
'''
|
||
}
|
||
}
|
||
post {
|
||
always {
|
||
// Publish coverage into Jenkins (Cobertura)
|
||
publishCoverage adapters: [coberturaAdapter('coverage-report/Cobertura.xml')],
|
||
sourceFileResolver: sourceFiles('STORE_LAST_BUILD')
|
||
junit '**/TestResults/**/*.trx'
|
||
archiveArtifacts artifacts: 'coverage-report/**', allowEmptyArchive: true
|
||
}
|
||
}
|
||
}
|
||
|
||
stage('Build Artifact') {
|
||
agent {
|
||
docker { image 'mcr.microsoft.com/dotnet/sdk:9.0'; reuseNode true }
|
||
}
|
||
steps {
|
||
sh '''
|
||
dotnet publish -c Release -o out
|
||
ls -la out
|
||
'''
|
||
archiveArtifacts artifacts: 'out/**', fingerprint: true
|
||
}
|
||
}
|
||
}
|
||
|
||
options {
|
||
ansiColor('xterm')
|
||
timestamps()
|
||
}
|
||
} |