pipeline { agent none options { skipDefaultCheckout(true) } environment { APP_NAME = 'test_app' GITEA_URL = 'https://git.grigowashere.ru' GITEA_OWNER = 'Grigo' GITEA_REPO = 'Testing' 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 rm -rf dist/linux mkdir -p dist/linux cp build/linux/test_app dist/linux/test_app chmod +x dist/linux/test_app ''' archiveArtifacts artifacts: 'dist/linux/**', fingerprint: true stash name: 'linux-dist', includes: 'dist/linux/**' } } stage('Build Windows Qt') { agent { label 'windows' } steps { deleteDir() 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 stash name: 'windows-dist', includes: 'dist/windows/**' } } stage('Create Gitea Release') { agent { label 'windows' } steps { deleteDir() unstash 'linux-dist' unstash 'windows-dist' withCredentials([string(credentialsId: 'Gitea_Credentials', variable: 'GITEA_TOKEN')]) { writeFile file: 'gitea-release.ps1', text: ''' $ErrorActionPreference = "Stop" $tag = "v$env:BUILD_NUMBER" Compress-Archive -Path "dist\\windows\\*" -DestinationPath "test_app-windows-$tag.zip" -Force Compress-Archive -Path "dist\\linux\\*" -DestinationPath "test_app-linux-$tag.zip" -Force $headers = @{ Authorization = "token $env:GITEA_TOKEN" } $body = @{ tag_name = $tag target_commitish = "main" name = "Release $tag" body = "Jenkins build $env:BUILD_NUMBER`n$env:BUILD_URL" draft = $false prerelease = $false } | ConvertTo-Json $release = Invoke-RestMethod ` -Method Post ` -Uri "$env:GITEA_URL/api/v1/repos/$env:GITEA_OWNER/$env:GITEA_REPO/releases" ` -Headers $headers ` -ContentType "application/json" ` -Body $body function Upload-Asset($fileName) { $uploadUrl = "$env:GITEA_URL/api/v1/repos/$env:GITEA_OWNER/$env:GITEA_REPO/releases/$($release.id)/assets?name=$fileName" curl.exe -X POST ` $uploadUrl ` -H "Authorization: token $env:GITEA_TOKEN" ` -F "attachment=@$fileName;type=application/zip" if ($LASTEXITCODE -ne 0) { throw "Gitea asset upload failed: $fileName" } } Upload-Asset "test_app-windows-$tag.zip" Upload-Asset "test_app-linux-$tag.zip" ''' bat ''' powershell -NoProfile -ExecutionPolicy Bypass -File gitea-release.ps1 ''' } } } } post { always { node('linux') { cleanWs() checkout scm 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): req = urllib.request.Request(f"{taiga_url}{path}", 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") req = urllib.request.Request( f"{taiga_url}/api/v1/{endpoint}/{data['id']}", 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()) } } } } } }