pipeline { agent any environment { JAVA_HOME = '/usr/lib/jvm/java-21-openjdk-amd64' ANDROID_HOME = '/opt/android-sdk' ANDROID_SDK_ROOT = '/opt/android-sdk' PATH = "/usr/lib/jvm/java-21-openjdk-amd64/bin:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools:${env.PATH}" TAIGA_PROJECT_ID = '2' TAIGA_URL = 'https://taiga.grigowashere.ru' GITEA_OWNER = 'Grigo' GITEA_REPO = 'Testing' } stages { stage('Build Android APK') { steps { cleanWs() checkout scm sh ''' chmod +x ./gradlew ./gradlew clean assembleDebug ''' archiveArtifacts artifacts: '**/build/outputs/apk/**/*.apk', fingerprint: true stash name: 'apk', includes: '**/build/outputs/apk/**/*.apk' } } stage('Create Gitea Release and Upload APK') { steps { unstash 'apk' withCredentials([string(credentialsId: 'Gitea_Credentials', variable: 'GITEA_TOKEN')]) { writeFile file: 'gitea-release.ps1', text: ''' $ErrorActionPreference = "Stop" $apkPath = "build/outputs/apk/debug/app-debug.apk" $headers = @{ Authorization = "token $env:GITEA_TOKEN" } $body = @{ tag_name = "v$env:BUILD_NUMBER" target_commitish = "main" name = "Release v$env:BUILD_NUMBER" body = "Jenkins Android build $env:BUILD_NUMBER`n$env:BUILD_URL" draft = $false prerelease = $false } | ConvertTo-Json # Создаём релиз в Gitea $release = Invoke-RestMethod ` -Method Post ` -Uri "https://git.grigowashere.ru/api/v1/repos/$env:GITEA_OWNER/$env:GITEA_REPO/releases" ` -Headers $headers ` -ContentType "application/json" ` -Body $body # Формируем URL для загрузки артефакта $uploadUrl = "https://git.grigowashere.ru/api/v1/repos/$env:GITEA_OWNER/$env:GITEA_REPO/releases/$($release.id)/assets?name=app-debug.apk" # Используем curl для загрузки APK в Gitea curl.exe -X POST ` $uploadUrl ` -H "Authorization: token $env:GITEA_TOKEN" ` -F "attachment=@$apkPath;type=application/vnd.android.package-archive" if ($LASTEXITCODE -ne 0) { throw "Gitea asset upload failed: $apkPath" } ''' bat ''' powershell -NoProfile -ExecutionPolicy Bypass -File gitea-release.ps1 ''' } } } } post { always { 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 Android 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()) } } } } }