AS400_API_DOTNET/Jenkinsfile

194 lines
6.8 KiB
Groovy

pipeline {
agent none
options { ansiColor('xterm'); timestamps() }
environment {
DOTNET_CLI_TELEMETRY_OPTOUT = '1'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1'
SONAR_PROJECT_KEY = 'as400api-dotnet'
SONAR_PROJECT_NAME = 'AS400_API_DOTNET (.NET 9)'
}
stages {
stage('Checkout') {
agent any
steps { checkout scm }
}
stage('Install prerequisites') {
agent any
steps {
sh '''
set -euo pipefail
install_deps() {
if command -v apt-get >/dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
apt-get update
# Common native deps for .NET + tools
apt-get install -y --no-install-recommends \
libkrb5-3 zlib1g libstdc++6 ca-certificates curl unzip jq
# Java (for OWASP Dependency-Check)
# prefer 17 headless; fall back to default-jre-headless
(apt-get install -y --no-install-recommends openjdk-17-jre-headless) || \
(apt-get install -y --no-install-recommends default-jre-headless) || true
# ---- ICU on Debian/Ubuntu ----
# 1) try meta/dev names (older releases)
apt-get install -y --no-install-recommends libicu || true
apt-get install -y --no-install-recommends libicu-dev || true
# 2) if still missing, detect versioned package (e.g., libicu74 on trixie)
if ! ldconfig -p 2>/dev/null | grep -qi 'libicu'; then
PKG="$(apt-cache search -n '^libicu[0-9]+$' | awk '{print $1}' | sort -V | tail -n1 || true)"
if [ -n "${PKG:-}" ]; then
echo "Installing detected ICU package: $PKG"
apt-get install -y --no-install-recommends "$PKG"
fi
fi
# 3) final sanity
if ! ldconfig -p 2>/dev/null | grep -qi 'libicu'; then
echo "WARN: ICU not found after install attempts (will rely on invariant mode if needed)"
fi
elif command -v dnf >/dev/null 2>&1; then
dnf install -y libicu krb5-libs zlib libstdc++ ca-certificates curl unzip java-17-openjdk-headless jq || true
elif command -v yum >/dev/null 2>&1; then
yum install -y libicu krb5-libs zlib libstdc++ ca-certificates curl unzip java-17-openjdk-headless jq || true
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache icu-libs krb5-libs zlib libstdc++ ca-certificates curl unzip openjdk17-jre-headless jq || true
else
echo "Unsupported package manager. Please install ICU + Java manually."
exit 1
fi
}
install_deps
'''
}
}
// 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"
# If ICU still missing (e.g., no libicu*.so found), enable invariant mode as a fallback
if ! ldconfig -p 2>/dev/null | grep -qi 'libicu'; then
export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
echo "NOTE: Running .NET in globalization invariant mode (ICU not found)"
fi
dotnet --info
'''
}
}
stage('SCA (NuGet vulnerabilities + OWASP)') {
agent any
steps {
sh '''
set -e
export PATH="$HOME/.dotnet:$PATH"
echo "=== NuGet vulnerability audit ==="
dotnet restore
dotnet list package --vulnerable || true
echo "=== OWASP Dependency-Check (no Docker) ==="
mkdir -p depcheck
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/"
'''
}
post {
always {
archiveArtifacts artifacts: 'depcheck/**', allowEmptyArchive: true
}
}
}
stage('SAST + Coverage (SonarQube + Tests)') {
agent any
steps {
withSonarQubeEnv('SonarQube') {
sh '''
set -e
export PATH="$HOME/.dotnet:$PATH"
# 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
dotnet-sonarscanner end
'''
}
}
post {
always {
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 any
steps {
sh '''
set -e
export PATH="$HOME/.dotnet:$PATH"
dotnet publish -c Release -o out
ls -la out
'''
archiveArtifacts artifacts: 'out/**', fingerprint: true
}
}
}
}