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 = 'AndroidTemplate' } 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.sh', text: ''' #!/bin/bash apkPath="build/outputs/apk/debug/app-debug.apk" headers="Authorization: token $GITEA_TOKEN" # Create the release on Gitea release=$(curl -X POST "https://git.grigowashere.ru/api/v1/repos/$GITEA_OWNER/$GITEA_REPO/releases" \ -H "$headers" \ -H "Content-Type: application/json" \ -d '{ "tag_name": "v'$BUILD_NUMBER'", "target_commitish": "main", "name": "Release v'$BUILD_NUMBER'", "body": "Jenkins Android build '$BUILD_NUMBER'", "draft": false, "prerelease": false }') releaseId=$(echo $release | jq -r .id) # Form URL for uploading APK asset uploadUrl="https://git.grigowashere.ru/api/v1/repos/$GITEA_OWNER/$GITEA_REPO/releases/$releaseId/assets?name=app-debug.apk" # Upload APK file to Gitea curl -X POST "$uploadUrl" \ -H "$headers" \ -F "attachment=@$apkPath;type=application/vnd.android.package-archive" if [ $? -ne 0 ]; then echo "Gitea asset upload failed: $apkPath" exit 1 fi ''' sh ''' chmod +x gitea-release.sh ./gitea-release.sh ''' } } } } 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 import urllib.error 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 as e: print(f"Taiga lookup warning: {e}") return None targets = [ ("issues", "Issue"), ("userstories", "User Story"), ("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 as issue/userstory/task") 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()) } } } } }