This commit is contained in:
Anupong Hompan 2025-10-21 12:12:52 +07:00
parent 7ade39e07f
commit 23eb4b7b4a

91
Jenkinsfile vendored
View File

@ -14,12 +14,12 @@ pipeline {
DOTNET_ROOT = "${WORKSPACE}/.dotnet"
PATH = "${DOTNET_ROOT}:${PATH}"
// Dependency-Check cache (แมพกับ volume/โฟลเดอร์บน Jenkins)
// Dependency-Check cache
DC_DATA = "${JENKINS_HOME}/.dc-cache"
// ถ้าจะใช้ SonarQube ให้ตั้งค่าตามระบบจริง
// SonarQube
SONARQUBE_INSTANCE = 'SonarQube'
SONAR_PROJECT_KEY = 'AS400API'
SONAR_PROJECT_KEY = 'AS400API'
}
stages {
@ -50,7 +50,6 @@ pipeline {
echo "Installing ICU package: ${PKG}"
apt-get install -y --no-install-recommends "${PKG}"
else
# Fallback: dev package also provides the libs (heavier)
echo "Falling back to libicu-dev..."
apt-get install -y --no-install-recommends libicu-dev
fi
@ -88,11 +87,7 @@ pipeline {
unzip -oq depcheck.zip -d dependency-check
DC_BIN="dependency-check/dependency-check/bin/dependency-check.sh"
# อัปเดตฐานข้อมูลครั้งแรก (และทุกครั้งที่ cache ว่าง)
bash "$DC_BIN" --data "${DC_DATA}" --updateonly || true
# สแกนจริง (เร็ว เพราะใช้ cache)
bash "$DC_BIN" -f HTML -f XML \
--project "AS400API" \
--scan . \
@ -104,7 +99,6 @@ pipeline {
post {
always {
archiveArtifacts artifacts: 'depcheck/**', allowEmptyArchive: true
// ถ้ามี HTML Publisher plugin จะโชว์รายงานสวยขึ้น
script {
try {
publishHTML(target: [
@ -116,50 +110,39 @@ pipeline {
allowMissing: true
])
} catch (Throwable e) {
echo "Skipping HTML report publish (plugin unavailable?): ${e.getClass().getSimpleName()}"
echo "Skipping HTML report publish: ${e.getClass().getSimpleName()}"
}
}
}
}
}
stage('SAST') {
stage('SAST with SonarQube') {
steps {
script {
if (env.SONARQUBE_INSTANCE?.trim()) {
withSonarQubeEnv(env.SONARQUBE_INSTANCE) {
sh """
set -euo pipefail
withSonarQubeEnv("${SONARQUBE_INSTANCE}") {
sh '''
set -euo pipefail
echo "=== SAST with SonarQube ==="
echo "=== SAST with SonarQube (${env.SONARQUBE_INSTANCE}) ==="
dotnet tool update --global dotnet-sonarscanner || dotnet tool install --global dotnet-sonarscanner
export PATH="$HOME/.dotnet/tools:${PATH}"
dotnet tool update --global dotnet-sonarscanner
export PATH="$PATH:/root/.dotnet/tools"
dotnet clean -c Release
dotnet sonarscanner begin \
/k:"'"${SONAR_PROJECT_KEY}"'" \
/d:sonar.host.url="$SONAR_HOST_URL" \
/d:sonar.login="$SONAR_AUTH_TOKEN" \
/d:sonar.exclusions="**/bin/**,**/obj/**" \
/d:sonar.test.exclusions="**/*.Tests/**"
dotnet sonarscanner begin \
/k:"${env.SONAR_PROJECT_KEY}" \
/d:sonar.host.url="\$SONAR_HOST_URL" \
/d:sonar.login="\$SONAR_AUTH_TOKEN"
dotnet build -c Release \
-p:TreatWarningsAsErrors=false \
-warnaserror
dotnet sonarscanner end /d:sonar.login="\$SONAR_AUTH_TOKEN"
"""
}
} else {
sh '''
set -euo pipefail
echo "=== SAST with Roslyn analyzers (no Sonar) ==="
dotnet clean -c Release
dotnet build -c Release \
-p:EnableNETAnalyzers=true \
-p:TreatWarningsAsErrors=true \
-warnaserror
'''
}
dotnet clean -c Release
# สำคัญ: ปิด warnings-as-errors
dotnet build -c Release /warnaserror- -p:TreatWarningsAsErrors=false
'''
}
}
post {
always {
sh 'dotnet sonarscanner end /d:sonar.login="$SONAR_AUTH_TOKEN" || true'
}
}
}
@ -168,10 +151,7 @@ pipeline {
steps {
sh '''
set -euo pipefail
# รันเทส + สร้างผลลัพธ์ JUnit XML + Coverage (Cobertura)
dotnet build -c Debug
dotnet test \
--logger "junit;LogFileName=test-results.xml" \
--results-directory "TestResults" \
@ -179,7 +159,6 @@ pipeline {
/p:CoverletOutput=coverage/ \
/p:CoverletOutputFormat=cobertura
# รวม coverage ไว้ที่เดียวเพื่อ publish/เก็บ artifacts
mkdir -p coverage-report
COB=$(find . -type f -name "coverage.cobertura.xml" | head -n1 || true)
if [ -n "$COB" ]; then
@ -189,14 +168,8 @@ pipeline {
}
post {
always {
// รายงานผลเทส (JUnit)
junit allowEmptyResults: false, testResults: '**/TestResults/**/*.xml'
// เก็บไฟล์ coverage
archiveArtifacts artifacts: 'coverage-report/**', allowEmptyArchive: true
// (ทางเลือก) ถ้าติดตั้ง Coverage plugin
// publishCoverage adapters: [coberturaAdapter('coverage-report/Cobertura.xml')], sourceFileResolver: sourceFiles('STORE_LAST_BUILD')
}
}
}
@ -214,11 +187,19 @@ pipeline {
}
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 30, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
} // end stages
post {
always {
echo "Pipeline finished (status: ${currentBuild.currentResult})"
}
}
}
} // end pipeline