AS400_API_DOTNET/Jenkinsfile copy 3
2025-10-28 13:07:28 +07:00

198 lines
7.5 KiB
Plaintext

pipeline {
agent {
docker {
image 'mcr.microsoft.com/dotnet/sdk:9.0'
args '-u root:root'
// label "${params.AGENT_LABEL?.trim() ?: ''}"
}
}
options {
ansiColor('xterm')
timestamps()
buildDiscarder(logRotator(numToKeepStr: '15'))
disableConcurrentBuilds()
skipDefaultCheckout(true)
}
parameters {
string(name: 'GIT_URL', defaultValue: 'file:///repos/AS400API.git', description: 'Git repository URL to clone')
string(name: 'GIT_BRANCH', defaultValue: 'main', description: 'Branch or ref to build')
// string(name: 'AGENT_LABEL', defaultValue: '', description: 'Optional Jenkins agent label with Docker CLI access (leave blank for default node)')
}
environment {
DOTNET_CLI_TELEMETRY_OPTOUT = '1'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1'
DOTNET_NOLOGO = '1'
BUILD_CONFIGURATION = 'Release'
TEST_RESULTS_DIR = 'TestResults'
COVERAGE_DIR = 'TestResults/Coverage'
COVERAGE_FILE = 'TestResults/Coverage/coverage.opencover.xml'
PUBLISH_DIR = 'publish/Release'
SONAR_PROJECT_KEY = 'AS400API'
SONAR_PROJECT_NAME = 'AS400API'
}
stages {
stage('Checkout') {
steps {
// Fetch the requested branch from the configured Git URL.
script {
if (!params.GIT_URL?.trim()) {
error 'GIT_URL parameter must not be empty.'
}
String branchSpec = params.GIT_BRANCH?.trim() ?: 'main'
if (!branchSpec.startsWith('*/')) {
branchSpec = "*/${branchSpec}"
}
checkout([
$class : 'GitSCM',
branches : [[name: branchSpec]],
doGenerateSubmoduleConfigurations: false,
extensions : [[$class: 'CloneOption', depth: 0, noTags: false, shallow: false]],
userRemoteConfigs : [[url: params.GIT_URL.trim()]]
])
}
}
}
stage('.NET SDK Info') {
steps {
// Sanity check the SDK and install required global tools (Java for Sonar + dotnet-sonarscanner).
sh '''#!/bin/bash -e
apt-get update
apt-get install -y --no-install-recommends openjdk-17-jre
rm -rf /var/lib/apt/lists/*
echo '### dotnet --info'
dotnet --info
echo '### Install/Update dotnet-sonarscanner'
dotnet tool install --global dotnet-sonarscanner || dotnet tool update --global dotnet-sonarscanner
'''
script {
if (!env.PATH.contains('/root/.dotnet/tools')) {
env.PATH = "${env.PATH}:/root/.dotnet/tools"
}
}
}
}
stage('Restore') {
steps {
// Restore solution dependencies.
sh '''#!/bin/bash -e
dotnet restore AS400API.sln
'''
}
}
stage('Build') {
steps {
// Build the solution in Release mode without failing on warnings.
sh '''#!/bin/bash -e
dotnet build AS400API.sln --configuration "${BUILD_CONFIGURATION}" --no-restore
'''
}
}
stage('Test & Coverage') {
steps {
// Execute tests once for fast feedback and capture TRX + OpenCover reports.
sh '''#!/bin/bash -e
rm -rf "${TEST_RESULTS_DIR}"
mkdir -p "${COVERAGE_DIR}"
dotnet test AS400API.sln --configuration "${BUILD_CONFIGURATION}" --no-build \
/p:CollectCoverage=true \
/p:CoverletOutputFormat=opencover \
/p:CoverletOutput="${COVERAGE_DIR}/" \
--logger "trx;LogFileName=test-results.trx" \
--logger "junit;LogFileName=test-results.xml"
'''
junit testResults: "${TEST_RESULTS_DIR}/**/*.xml", allowEmptyResults: false
publishCoverage adapters: [opencoverAdapter("${COVERAGE_FILE}")], sourceFileResolver: sourceFiles('STORE_LAST_BUILD'), failNoReports: true
}
}
stage('SonarQube: Begin') {
steps {
// Kick off Sonar analysis with project metadata and coverage location.
script {
env.SONAR_PROJECT_VERSION = env.BUILD_NUMBER ?: '0.0.0'
}
withSonarQubeEnv('sonarqube') {
sh '''#!/bin/bash -e
dotnet sonarscanner begin \
/k:"${SONAR_PROJECT_KEY}" \
/n:"${SONAR_PROJECT_NAME}" \
/v:"${SONAR_PROJECT_VERSION}" \
/d:sonar.host.url="${SONAR_HOST_URL}" \
/d:sonar.login="${SONAR_AUTH_TOKEN}" \
/d:sonar.cs.opencover.reportsPaths="${COVERAGE_FILE}"
'''
}
}
}
stage('Rebuild for Sonar') {
steps {
// Run a rebuild under the Sonar scanner context so analysis picks up compilation data.
sh '''#!/bin/bash -e
dotnet build AS400API.sln --configuration "${BUILD_CONFIGURATION}" --no-restore --no-incremental
'''
}
}
stage('SonarQube: End') {
steps {
// Close the Sonar analysis and push data to the server.
withSonarQubeEnv('sonarqube') {
sh '''#!/bin/bash -e
dotnet sonarscanner end /d:sonar.login="${SONAR_AUTH_TOKEN}"
'''
}
}
}
stage('Quality Gate') {
steps {
// Wait for the Quality Gate result and fail fast on non-green outcomes.
timeout(time: 15, unit: 'MINUTES') {
script {
def qualityGate = waitForQualityGate()
if (qualityGate.status != 'OK') {
error "SonarQube Quality Gate failed: ${qualityGate.status}"
}
}
}
}
}
stage('Archive') {
steps {
// Publish Release-ready binaries and test artifacts for downstream consumption.
sh '''#!/bin/bash -e
rm -rf "${PUBLISH_DIR}"
dotnet publish AS400API.sln --configuration "${BUILD_CONFIGURATION}" --no-restore --output "${PUBLISH_DIR}"
'''
archiveArtifacts artifacts: "${PUBLISH_DIR}/**", fingerprint: true
archiveArtifacts artifacts: "${TEST_RESULTS_DIR}/**/*.trx", allowEmptyArchive: true
archiveArtifacts artifacts: "${COVERAGE_FILE}", allowEmptyArchive: true
}
}
}
post {
always {
script {
try {
deleteDir()
} catch (org.jenkinsci.plugins.workflow.steps.MissingContextVariableException ignore) {
echo 'Workspace cleanup skipped because no workspace was provisioned.'
}
}
}
}
}