pipeline { agent none environment { TAIGA_PROJECT_ID = '1' TAIGA_URL = 'https://taiga.grigowashere.ru' } stages { stage('Build Linux') { agent { label 'linux' } steps { cleanWs() checkout scm sh ''' cmake -S . -B build/linux -G Ninja \ -DCMAKE_BUILD_TYPE=Release cmake --build build/linux mkdir -p dist/linux cp build/linux/test_app dist/linux/test_app ''' archiveArtifacts artifacts: 'dist/linux/**', fingerprint: true } } stage('Build Windows Qt') { agent { label 'windows' } steps { cleanWs() checkout scm bat ''' call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat" cmake -S . -B build\\windows -G Ninja ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_TOOLCHAIN_FILE=C:\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake ^ -DVCPKG_TARGET_TRIPLET=x64-windows cmake --build build\\windows if exist dist\\windows rmdir /s /q dist\\windows mkdir dist\\windows copy build\\windows\\test_app.exe dist\\windows\\test_app.exe for /f "delims=" %%i in ('dir /b /s C:\\vcpkg\\installed\\x64-windows\\tools\\Qt6\\windeployqt.exe') do set WINDEPLOYQT=%%i "%WINDEPLOYQT%" --release --no-translations dist\\windows\\test_app.exe xcopy /Y /I C:\\vcpkg\\installed\\x64-windows\\bin\\*.dll dist\\windows\\ ''' archiveArtifacts artifacts: 'dist/windows/**', fingerprint: true } } } post { always { node('linux') { script { def result = currentBuild.currentResult ?: 'UNKNOWN' withCredentials([string(credentialsId: 'TAIGA_TOKEN', variable: 'TAIGA_TOKEN')]) { sh(returnStatus: true, script: """ set +e REF=\$(git log -1 --pretty=%B | grep -oE 'TG-[0-9]+' | head -1 | cut -d- -f2 || true) if [ -z "\$REF" ]; then echo "No TG-* reference found" exit 0 fi export REF export BUILD_RESULT="${result}" python3 - <<'PY' import json import os import urllib.request taiga_url = os.environ["TAIGA_URL"] project_id = os.environ["TAIGA_PROJECT_ID"] token = os.environ["TAIGA_TOKEN"] ref = os.environ["REF"] headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", } def get_json(path): url = f"{taiga_url}{path}" req = urllib.request.Request(url, headers=headers) try: with urllib.request.urlopen(req) as r: return json.loads(r.read().decode("utf-8")) except Exception: return None targets = [ ("userstories", "User Story"), ("issues", "Issue"), ("tasks", "Task"), ] found = None for endpoint, label in targets: data = get_json(f"/api/v1/{endpoint}/by_ref?project={project_id}&ref={ref}") if data and "id" in data: found = (endpoint, label, data) break if not found: print(f"Taiga TG-{ref} not found") raise SystemExit(0) endpoint, label, data = found comment = ( f"Jenkins build #{os.environ['BUILD_NUMBER']}: {os.environ['BUILD_RESULT']}\\n" f"{os.environ['BUILD_URL']}" ) payload = json.dumps({ "comment": comment, "version": data["version"], }).encode("utf-8") url = f"{taiga_url}/api/v1/{endpoint}/{data['id']}" req = urllib.request.Request( url, data=payload, headers=headers, method="PATCH", ) try: with urllib.request.urlopen(req) as r: print(f"Commented Taiga TG-{ref} ({label}), HTTP {r.status}") except Exception as e: print(f"Taiga comment warning: {e}") raise SystemExit(0) PY """.stripIndent()) } } } } } }