pipeline { agent { label 'cicd-builder' } environment { // Provided by user //OLLAMA_API_URI = "https://agent:12tf56so@ollama-api.a.ucnit.eu/v1" //OLLAMA_API_KEY = credentials("b8d5c306-99e5-42a6-9825-4da275e9df89") //GITEA_TOKEN = credentials('48bf7c4c-b4c8-4652-bc90-17440e959bf4') //GITEA_API_URL = "https://gitea.a.ucnit.eu/api/v1" // Internal paths/artifacts CHANGED_FILES_FILE = "changed_files.txt" TEXT_FILES_FILE = "text_files.txt" SCAN_JSON_FILE = "scan_results.json" REPORT_FILE = "report.md" // Optional: Extend/override allowed text extensions (comma-separated, lowercase) // TEXT_FILE_EXTS = "py,js,ts,java,cs,go,rb,php,rs,kt,scala,sh,bash,zsh,ps1,tf,tfvars,yaml,yml,json,ini,conf,properties,toml,xml,gradle,m,mm,sql,md,rst,txt" } options { timeout(time: 30, unit: 'MINUTES') timestamps() disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr: '20')) } parameters { string(name: 'OLLAMA_MODEL', defaultValue: 'llama3.1:8b', description: 'Ollama model to use (e.g., llama3.1, codellama, qwen2.5-coder)') booleanParam(name: 'FAIL_ON_MEDIUM_OR_HIGH', defaultValue: true, description: 'Fail the build if any Medium or higher finding is present') string(name: 'MAX_FILE_BYTES', defaultValue: '200000', description: 'Limit of bytes per file passed to model (to avoid context overflows)') string(name: 'REQUEST_TIMEOUT_SEC', defaultValue: '180', description: 'Per-file analysis timeout (seconds)') } stages { stage('List folder content') { steps { echo "List folder content" sh "ls -l" sh "export" } } stage('Change to unix files') { steps { echo "Change to unix files" sh "/bin/dos2unix .workflow/* .workflow/*" sh "/bin/chmod +x .workflow/* .workflow/*" } } stage('Prepare & Verify') { steps { sh 'chmod +x .workflow/*.sh || true' sh '.workflow/verify_environment.sh' } } stage('Build all projects') { steps { echo "Build all projects" sh ".workflow/01_dotnet_build.sh" } } stage('Detect Changes') { when { branch 'Security' } steps { sh ".workflow/get_changed_files.sh \"$CHANGED_FILES_FILE\"" archiveArtifacts artifacts: "$CHANGED_FILES_FILE", allowEmptyArchive: true } } stage('Filter Text Files') { when { branch 'Security' } steps { sh ".workflow/filter_text_files.sh \"$CHANGED_FILES_FILE\" \"$TEXT_FILES_FILE\"" archiveArtifacts artifacts: "$TEXT_FILES_FILE", allowEmptyArchive: true } } stage('Scan with Ollama') { when { expression { fileExists('text_files.txt') && sh(script: "test -s text_files.txt", returnStatus: true) == 0 } } steps { sh ".workflow/scan_with_ollama.sh \"$TEXT_FILES_FILE\" \"$SCAN_JSON_FILE\" \"$OLLAMA_MODEL\" \"$MAX_FILE_BYTES\" \"$REQUEST_TIMEOUT_SEC\"" archiveArtifacts artifacts: "$SCAN_JSON_FILE", allowEmptyArchive: true } } stage('Build Markdown Report') { when { expression { fileExists('text_files.txt') && sh(script: "test -s text_files.txt", returnStatus: true) == 0 } } steps { sh ".workflow/build_markdown_report.sh \"$SCAN_JSON_FILE\" \"$REPORT_FILE\"" archiveArtifacts artifacts: "$REPORT_FILE", allowEmptyArchive: true } } stage('Report to Gitea (Issue)') { when { expression { fileExists('text_files.txt') && sh(script: "test -s text_files.txt", returnStatus: true) == 0 } } steps { sh ".workflow/create_gitea_issue.sh \"$REPORT_FILE\"" } } stage('Quality Gate') { when { expression { fileExists('text_files.txt') && sh(script: "test -s text_files.txt", returnStatus: true) == 0 } } steps { sh ".workflow/evaluate_threshold.sh \"$SCAN_JSON_FILE\" \"$FAIL_ON_MEDIUM_OR_HIGH\"" } } stage('Docker container release') { when { branch 'Docker' } steps { echo "Build container(s)" sh ".workflow/01_container_build.sh" } } } post { always { archiveArtifacts allowEmptyArchive: true, artifacts: "${CHANGED_FILES_FILE}, ${TEXT_FILES_FILE}, ${SCAN_JSON_FILE}, ${REPORT_FILE}" } } }