From e86f92c9e472ccf567c3dddbfe2cef61fe066cfc Mon Sep 17 00:00:00 2001 From: PoohMac <> Date: Mon, 20 Oct 2025 12:01:53 +0700 Subject: [PATCH] Update Jenkinsfile --- Jenkinsfile | 111 +++++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4749a74..92cb6a2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,7 +5,7 @@ pipeline { environment { DOTNET_CLI_TELEMETRY_OPTOUT = '1' DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1' - SONAR_PROJECT_KEY = 'as400api-dotnet' // <-- change if you like + SONAR_PROJECT_KEY = 'as400api-dotnet' SONAR_PROJECT_NAME = 'AS400_API_DOTNET (.NET 9)' } @@ -15,35 +15,51 @@ pipeline { steps { checkout scm } } - stage('SCA (NuGet vulnerabilities + OWASP)') { - agent { docker { image 'mcr.microsoft.com/dotnet/sdk:9.0'; reuseNode true } } + // Bootstrap .NET SDK if dotnet is missing + stage('Bootstrap .NET SDK') { + agent any steps { sh ''' set -e + if ! command -v dotnet >/dev/null 2>&1; then + echo "Installing .NET SDK locally for this build..." + curl -fsSL https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh + bash dotnet-install.sh --channel 9.0 --install-dir "$HOME/.dotnet" + fi + export PATH="$HOME/.dotnet:$PATH" dotnet --info - dotnet restore + ''' + } + } + + stage('SCA (NuGet vulnerabilities + OWASP)') { + agent any + steps { + sh ''' + set -e + export PATH="$HOME/.dotnet:$PATH" echo "=== NuGet vulnerability audit ===" - # Prints known vulnerable packages (won't fail the build by default) + dotnet restore dotnet list package --vulnerable || true - echo "=== OWASP Dependency-Check (try Docker first) ===" + echo "=== OWASP Dependency-Check (no Docker) ===" mkdir -p depcheck - if command -v docker >/dev/null 2>&1; then - docker run --rm \ - -v "$PWD":/src \ - -v "$PWD/depcheck":/report \ - owasp/dependency-check:latest \ - --scan /src --format "HTML" --out /report || true - else - echo "Docker not found; falling back to CLI zip…" - curl -sSL -o depcheck.zip https://github.com/jeremylong/DependencyCheck/releases/latest/download/dependency-check.zip || true - if [ -f depcheck.zip ]; then - unzip -q depcheck.zip -d depcheckcli || true - java -jar depcheckcli/dependency-check/bin/dependency-check.jar \ - --scan . --format HTML --out depcheck || true - fi - fi + DC_VER=latest + # Grab the release (platform-independent zip) + curl -Ls -o depcheck.zip \ + https://github.com/jeremylong/DependencyCheck/releases/${DC_VER}/download/dependency-check-${DC_VER}-release.zip || \ + curl -Ls -o depcheck.zip \ + https://github.com/jeremylong/DependencyCheck/releases/latest/download/dependency-check-release.zip + rm -rf dependency-check && mkdir dependency-check + unzip -q depcheck.zip -d dependency-check + DC_BIN=$(echo dependency-check/dependency-check*/bin/dependency-check.sh) + bash "$DC_BIN" \ + --format "HTML,XML" \ + --project "AS400_API_DOTNET" \ + --scan "." \ + --out "depcheck" \ + --noupdate || true echo "SCA reports generated in depcheck/" ''' @@ -56,39 +72,35 @@ pipeline { } stage('SAST + Coverage (SonarQube + Tests)') { - agent { docker { image 'mcr.microsoft.com/dotnet/sdk:9.0'; reuseNode true } } - environment { SONAR_TOKEN = credentials('sonar-token') } + agent any steps { - withSonarQubeEnv('SonarQubeServer') { + withSonarQubeEnv('SonarQube') { sh ''' set -e - dotnet tool install --global dotnet-sonarscanner --version 7.* - dotnet tool install --global dotnet-reportgenerator-globaltool - export PATH="$PATH:/root/.dotnet/tools" + export PATH="$HOME/.dotnet:$PATH" - 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/**" + # run tests with coverage (coverlet integrated) + dotnet test /p:CollectCoverage=true /p:CoverletOutput=coverage/ \ + /p:CoverletOutputFormat=cobertura + + # prepare coverage report location + mkdir -p coverage-report + # many test templates already emit Cobertura; adjust path if needed + cp **/coverage.cobertura.xml coverage-report/Cobertura.xml || true + + # Sonar scan (assuming global dotnet-sonarscanner or use local tool) + if ! command -v dotnet-sonarscanner >/dev/null 2>&1; then + dotnet tool install --global dotnet-sonarscanner + export PATH="$PATH:$HOME/.dotnet/tools" + fi + + dotnet-sonarscanner begin \ + /k:"${SONAR_PROJECT_KEY}" \ + /n:"${SONAR_PROJECT_NAME}" \ + /d:sonar.cs.opencover.reportsPaths="coverage-report/Cobertura.xml" dotnet build -c Release - # run tests; produce OpenCover coverage for Sonar - # If your test project path differs, specify it explicitly or run at solution level: - dotnet test -c Release \ - /p:CollectCoverage=true \ - /p:CoverletOutputFormat=opencover \ - /p:CoverletOutput=./TestResults/coverage - - dotnet sonarscanner end /d:sonar.login="$SONAR_TOKEN" - - # Generate a Cobertura report for Jenkins Coverage UI - reportgenerator \ - -reports:**/TestResults/**/coverage.opencover.xml \ - -targetdir:coverage-report \ - -reporttypes:Cobertura + dotnet-sonarscanner end ''' } } @@ -103,10 +115,11 @@ pipeline { } stage('Build Artifact') { - agent { docker { image 'mcr.microsoft.com/dotnet/sdk:9.0'; reuseNode true } } + agent any steps { sh ''' set -e + export PATH="$HOME/.dotnet:$PATH" dotnet publish -c Release -o out ls -la out '''