Update Jenkinsfile to local
This commit is contained in:
parent
e99d12b81d
commit
3e0eaa142b
269
Jenkinsfile
vendored
269
Jenkinsfile
vendored
@ -1,221 +1,192 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
agent none
|
agent any
|
||||||
options { ansiColor('xterm'); timestamps() }
|
|
||||||
|
options {
|
||||||
|
ansiColor('xterm')
|
||||||
|
timestamps()
|
||||||
|
}
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT = '1'
|
// ถ้าใช้ local bare repo
|
||||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1'
|
GIT_URL = 'file:///repos/AS400API.git'
|
||||||
SONAR_PROJECT_KEY = 'as400api-dotnet'
|
|
||||||
SONAR_PROJECT_NAME = 'AS400_API_DOTNET (.NET 9)'
|
// Path ติดตั้ง dotnet ชั่วคราวใน pipeline
|
||||||
|
DOTNET_ROOT = "${WORKSPACE}/.dotnet"
|
||||||
|
PATH = "${DOTNET_ROOT}:${PATH}"
|
||||||
|
|
||||||
|
// Dependency-Check cache (แมพกับ volume/โฟลเดอร์บน Jenkins)
|
||||||
|
DC_DATA = "${JENKINS_HOME}/.dc-cache"
|
||||||
|
|
||||||
|
// ถ้าจะใช้ SonarQube ให้ตั้งค่าตามระบบจริง
|
||||||
|
// SONAR_HOST_URL = 'http://sonarqube:9000'
|
||||||
|
// SONAR_TOKEN = credentials('SONAR_TOKEN')
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
|
|
||||||
stage('Checkout') {
|
stage('Checkout') {
|
||||||
agent any
|
steps {
|
||||||
steps { checkout scm }
|
checkout([$class: 'GitSCM',
|
||||||
|
branches: [[name: '*/main']],
|
||||||
|
userRemoteConfigs: [[url: "${GIT_URL}"]]
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Install prerequisites') {
|
stage('Install prerequisites') {
|
||||||
agent any
|
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
install_deps() {
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
if command -v apt-get >/dev/null 2>&1; then
|
apt-get update
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
apt-get install -y --no-install-recommends \
|
||||||
apt-get update
|
ca-certificates curl unzip jq git openjdk-21-jre-headless
|
||||||
# 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
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${DOTNET_ROOT}"
|
||||||
|
curl -fsSL https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh
|
||||||
|
bash dotnet-install.sh --channel 9.0 --install-dir "${DOTNET_ROOT}"
|
||||||
dotnet --info
|
dotnet --info
|
||||||
|
|
||||||
|
# เตรียม cache สำหรับ Dependency-Check
|
||||||
|
mkdir -p "${DC_DATA}"
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('SCA (NuGet vulnerabilities + OWASP)') {
|
stage('SCA (NuGet + OWASP)') {
|
||||||
agent any
|
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
export PATH="$HOME/.dotnet:$PATH"
|
|
||||||
|
|
||||||
echo "=== NuGet vulnerability audit ==="
|
echo "=== NuGet vulnerability audit ==="
|
||||||
dotnet restore
|
dotnet restore
|
||||||
dotnet list package --vulnerable || true
|
dotnet list package --vulnerable || true
|
||||||
|
|
||||||
echo "=== OWASP Dependency-Check (no Docker) ==="
|
echo "=== OWASP Dependency-Check ==="
|
||||||
rm -f depcheck.zip || true
|
rm -rf depcheck
|
||||||
rm -rf dependency-check || true
|
|
||||||
mkdir -p depcheck
|
mkdir -p depcheck
|
||||||
|
|
||||||
API="https://api.github.com/repos/jeremylong/DependencyCheck/releases/latest"
|
API="https://api.github.com/repos/jeremylong/DependencyCheck/releases/latest"
|
||||||
|
echo "Resolving latest Dependency-Check..."
|
||||||
# Resolve the correct asset URL (ends with -release.zip)
|
ASSET_URL=$(curl -fsSL "$API" | jq -r '.assets[]?.browser_download_url | select(test("release\\\\.zip$"))' | head -n1)
|
||||||
echo "Resolving Dependency-Check latest asset URL from GitHub API..."
|
|
||||||
ASSET_URL="$(curl -fsSL "$API" \
|
|
||||||
| jq -r '.assets[]?.browser_download_url | select(test("release\\\\.zip$"))' \
|
|
||||||
| head -n1 || true)"
|
|
||||||
|
|
||||||
# Fallback from tag_name if assets listing is throttled
|
|
||||||
if [ -z "${ASSET_URL:-}" ]; then
|
|
||||||
TAG="$(curl -fsSL "$API" | jq -r '.tag_name' || true)"
|
|
||||||
if [ -n "${TAG:-}" ]; then
|
|
||||||
VER="${TAG#v}"
|
|
||||||
ASSET_URL="https://github.com/jeremylong/DependencyCheck/releases/download/${TAG}/dependency-check-${VER}-release.zip"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${ASSET_URL:-}" ]; then
|
|
||||||
echo "ERROR: Could not resolve Dependency-Check release asset URL."
|
|
||||||
exit 9
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Downloading: $ASSET_URL"
|
echo "Downloading: $ASSET_URL"
|
||||||
curl -fL --retry 3 --retry-all-errors -o depcheck.zip "$ASSET_URL"
|
curl -fL --retry 3 --retry-all-errors -o depcheck.zip "$ASSET_URL"
|
||||||
|
|
||||||
# Validate and extract
|
|
||||||
unzip -tq depcheck.zip || { echo "Downloaded file is not a valid ZIP"; exit 9; }
|
|
||||||
mkdir -p dependency-check
|
|
||||||
unzip -q depcheck.zip -d dependency-check
|
unzip -q depcheck.zip -d dependency-check
|
||||||
|
|
||||||
DC_BIN="$(echo dependency-check/dependency-check*/bin/dependency-check.sh)"
|
DC_BIN="dependency-check/dependency-check/bin/dependency-check.sh"
|
||||||
if [ ! -x "$DC_BIN" ]; then
|
|
||||||
echo "ERROR: dependency-check.sh not found under extracted folder"
|
|
||||||
ls -la dependency-check || true
|
|
||||||
exit 9
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Generate HTML and XML reports (note: use multiple -f flags)
|
# อัปเดตฐานข้อมูลครั้งแรก (และทุกครั้งที่ cache ว่าง)
|
||||||
bash "$DC_BIN" \
|
bash "$DC_BIN" --data "${DC_DATA}" --updateonly || true
|
||||||
-f HTML -f XML \
|
|
||||||
--project "AS400_API_DOTNET" \
|
# สแกนจริง (เร็ว เพราะใช้ cache)
|
||||||
--scan "." \
|
bash "$DC_BIN" -f HTML -f XML \
|
||||||
--out "depcheck" \
|
--project "AS400API" \
|
||||||
|
--scan . \
|
||||||
|
--out depcheck \
|
||||||
|
--data "${DC_DATA}" \
|
||||||
--noupdate || true
|
--noupdate || true
|
||||||
|
|
||||||
echo "SCA reports generated in depcheck/"
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
always {
|
always {
|
||||||
archiveArtifacts artifacts: 'depcheck/**', allowEmptyArchive: true
|
archiveArtifacts artifacts: 'depcheck/**', allowEmptyArchive: true
|
||||||
|
// ถ้ามี HTML Publisher plugin จะโชว์รายงานสวยขึ้น
|
||||||
|
publishHTML(target: [
|
||||||
|
reportName: 'OWASP Dependency-Check',
|
||||||
|
reportDir: 'depcheck',
|
||||||
|
reportFiles: 'dependency-check-report.html',
|
||||||
|
keepAll: true,
|
||||||
|
alwaysLinkToLastBuild: true,
|
||||||
|
allowMissing: true
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('SAST + Coverage (SonarQube + Tests)') {
|
stage('SAST') {
|
||||||
agent any
|
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
set -e
|
set -euo pipefail
|
||||||
export PATH="$HOME/.dotnet:$PATH"
|
|
||||||
|
|
||||||
# run tests with coverage (cobertura) + produce TRX results for JUnit
|
if [ -n "${SONAR_HOST_URL:-}" ] && [ -n "${SONAR_TOKEN:-}" ]; then
|
||||||
|
echo "=== SAST with SonarQube ==="
|
||||||
|
# ถ้าใช้ sonarscanner for .NET (แนะนำ)
|
||||||
|
dotnet tool update --global dotnet-sonarscanner || dotnet tool install --global dotnet-sonarscanner
|
||||||
|
export PATH="$HOME/.dotnet/tools:${PATH}"
|
||||||
|
|
||||||
|
dotnet-sonarscanner begin \
|
||||||
|
/k:"AS400API" \
|
||||||
|
/d:sonar.host.url="${SONAR_HOST_URL}" \
|
||||||
|
/d:sonar.login="${SONAR_TOKEN}"
|
||||||
|
|
||||||
|
dotnet build -c Release
|
||||||
|
|
||||||
|
dotnet-sonarscanner end /d:sonar.login="${SONAR_TOKEN}"
|
||||||
|
else
|
||||||
|
echo "=== SAST with Roslyn analyzers (no Sonar) ==="
|
||||||
|
# เปิด .NET analyzers และ treat warnings เป็น error
|
||||||
|
dotnet build -c Release \
|
||||||
|
-p:EnableNETAnalyzers=true \
|
||||||
|
-p:TreatWarningsAsErrors=true \
|
||||||
|
-warnaserror
|
||||||
|
fi
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Test + Coverage') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# รันเทส + สร้างผลลัพธ์ JUnit XML + Coverage (Cobertura)
|
||||||
dotnet test \
|
dotnet test \
|
||||||
--logger "trx;LogFileName=test_results.trx" \
|
--logger "junit;LogFileName=test-results.xml" \
|
||||||
/p:CollectCoverage=true \
|
/p:CollectCoverage=true \
|
||||||
/p:CoverletOutput=coverage/ \
|
/p:CoverletOutput=coverage/ \
|
||||||
/p:CoverletOutputFormat=cobertura
|
/p:CoverletOutputFormat=cobertura
|
||||||
|
|
||||||
|
# รวม coverage ไว้ที่เดียวเพื่อ publish/เก็บ artifacts
|
||||||
mkdir -p coverage-report
|
mkdir -p coverage-report
|
||||||
# copy the cobertura file (adjust path if your solution layout differs)
|
COB=$(find . -type f -name "coverage.cobertura.xml" | head -n1 || true)
|
||||||
COBERTURA_FILE=$(find . -type f -name "coverage.cobertura.xml" | head -n1 || true)
|
if [ -n "$COB" ]; then
|
||||||
[ -n "$COBERTURA_FILE" ] && cp "$COBERTURA_FILE" coverage-report/Cobertura.xml || true
|
cp "$COB" coverage-report/Cobertura.xml
|
||||||
|
|
||||||
# If SonarQube is configured, run scanner; otherwise skip gracefully.
|
|
||||||
if [ -n "${SONARQUBE_ENV_NAME:-}" ]; then
|
|
||||||
echo "SonarQube env variable detected: $SONARQUBE_ENV_NAME"
|
|
||||||
else
|
|
||||||
echo "SonarQube not configured; skipping Sonar scan."
|
|
||||||
exit 0
|
|
||||||
fi
|
fi
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
always {
|
always {
|
||||||
// Publish TRX results (built-in)
|
// รายงานผลเทส (JUnit)
|
||||||
junit '**/TestResults/**/*.trx'
|
junit allowEmptyResults: false, testResults: '**/TestResults/**/*.xml'
|
||||||
// Archive coverage XML so you can inspect it
|
|
||||||
|
// เก็บไฟล์ coverage
|
||||||
archiveArtifacts artifacts: 'coverage-report/**', allowEmptyArchive: true
|
archiveArtifacts artifacts: 'coverage-report/**', allowEmptyArchive: true
|
||||||
|
|
||||||
|
// (ทางเลือก) ถ้าติดตั้ง Coverage plugin
|
||||||
|
// publishCoverage adapters: [coberturaAdapter('coverage-report/Cobertura.xml')], sourceFileResolver: sourceFiles('STORE_LAST_BUILD')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Build Artifact') {
|
stage('Build') {
|
||||||
agent any
|
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
set -e
|
set -euo pipefail
|
||||||
export PATH="$HOME/.dotnet:$PATH"
|
|
||||||
dotnet publish -c Release -o out
|
dotnet publish -c Release -o out
|
||||||
ls -la out
|
|
||||||
'''
|
'''
|
||||||
archiveArtifacts artifacts: 'out/**', fingerprint: true
|
}
|
||||||
|
post {
|
||||||
|
success {
|
||||||
|
archiveArtifacts artifacts: 'out/**', allowEmptyArchive: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
echo "Pipeline finished (status: ${currentBuild.currentResult})"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
221
Jenkinsfile copy
Normal file
221
Jenkinsfile copy
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
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 -euo pipefail
|
||||||
|
export PATH="$HOME/.dotnet:$PATH"
|
||||||
|
|
||||||
|
echo "=== NuGet vulnerability audit ==="
|
||||||
|
dotnet restore
|
||||||
|
dotnet list package --vulnerable || true
|
||||||
|
|
||||||
|
echo "=== OWASP Dependency-Check (no Docker) ==="
|
||||||
|
rm -f depcheck.zip || true
|
||||||
|
rm -rf dependency-check || true
|
||||||
|
mkdir -p depcheck
|
||||||
|
|
||||||
|
API="https://api.github.com/repos/jeremylong/DependencyCheck/releases/latest"
|
||||||
|
|
||||||
|
# Resolve the correct asset URL (ends with -release.zip)
|
||||||
|
echo "Resolving Dependency-Check latest asset URL from GitHub API..."
|
||||||
|
ASSET_URL="$(curl -fsSL "$API" \
|
||||||
|
| jq -r '.assets[]?.browser_download_url | select(test("release\\\\.zip$"))' \
|
||||||
|
| head -n1 || true)"
|
||||||
|
|
||||||
|
# Fallback from tag_name if assets listing is throttled
|
||||||
|
if [ -z "${ASSET_URL:-}" ]; then
|
||||||
|
TAG="$(curl -fsSL "$API" | jq -r '.tag_name' || true)"
|
||||||
|
if [ -n "${TAG:-}" ]; then
|
||||||
|
VER="${TAG#v}"
|
||||||
|
ASSET_URL="https://github.com/jeremylong/DependencyCheck/releases/download/${TAG}/dependency-check-${VER}-release.zip"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${ASSET_URL:-}" ]; then
|
||||||
|
echo "ERROR: Could not resolve Dependency-Check release asset URL."
|
||||||
|
exit 9
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Downloading: $ASSET_URL"
|
||||||
|
curl -fL --retry 3 --retry-all-errors -o depcheck.zip "$ASSET_URL"
|
||||||
|
|
||||||
|
# Validate and extract
|
||||||
|
unzip -tq depcheck.zip || { echo "Downloaded file is not a valid ZIP"; exit 9; }
|
||||||
|
mkdir -p dependency-check
|
||||||
|
unzip -q depcheck.zip -d dependency-check
|
||||||
|
|
||||||
|
DC_BIN="$(echo dependency-check/dependency-check*/bin/dependency-check.sh)"
|
||||||
|
if [ ! -x "$DC_BIN" ]; then
|
||||||
|
echo "ERROR: dependency-check.sh not found under extracted folder"
|
||||||
|
ls -la dependency-check || true
|
||||||
|
exit 9
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate HTML and XML reports (note: use multiple -f flags)
|
||||||
|
bash "$DC_BIN" \
|
||||||
|
-f HTML -f 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 {
|
||||||
|
sh '''
|
||||||
|
set -e
|
||||||
|
export PATH="$HOME/.dotnet:$PATH"
|
||||||
|
|
||||||
|
# run tests with coverage (cobertura) + produce TRX results for JUnit
|
||||||
|
dotnet test \
|
||||||
|
--logger "trx;LogFileName=test_results.trx" \
|
||||||
|
/p:CollectCoverage=true \
|
||||||
|
/p:CoverletOutput=coverage/ \
|
||||||
|
/p:CoverletOutputFormat=cobertura
|
||||||
|
|
||||||
|
mkdir -p coverage-report
|
||||||
|
# copy the cobertura file (adjust path if your solution layout differs)
|
||||||
|
COBERTURA_FILE=$(find . -type f -name "coverage.cobertura.xml" | head -n1 || true)
|
||||||
|
[ -n "$COBERTURA_FILE" ] && cp "$COBERTURA_FILE" coverage-report/Cobertura.xml || true
|
||||||
|
|
||||||
|
# If SonarQube is configured, run scanner; otherwise skip gracefully.
|
||||||
|
if [ -n "${SONARQUBE_ENV_NAME:-}" ]; then
|
||||||
|
echo "SonarQube env variable detected: $SONARQUBE_ENV_NAME"
|
||||||
|
else
|
||||||
|
echo "SonarQube not configured; skipping Sonar scan."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
// Publish TRX results (built-in)
|
||||||
|
junit '**/TestResults/**/*.trx'
|
||||||
|
// Archive coverage XML so you can inspect it
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
// var builder = WebApplication.CreateBuilder(args);
|
|
||||||
var builderArgs = args ?? Array.Empty<string>();
|
var builderArgs = args ?? Array.Empty<string>();
|
||||||
var builder = WebApplication.CreateBuilder(builderArgs);
|
var builder = WebApplication.CreateBuilder(builderArgs);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user