Skip to content

Commit 4399b9d

Browse files
committed
ci: job to build QT6 Image and android APK
1 parent 892e0b1 commit 4399b9d

File tree

6 files changed

+960
-53
lines changed

6 files changed

+960
-53
lines changed

ci/Jenkinsfile.android

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env groovy
2+
3+
4+
/* Options section can't access functions in objects. */
5+
def isPRBuild = utils.isPRBuild()
6+
def isNightlyBuild = utils.isNightlyBuild()
7+
8+
pipeline {
9+
agent {
10+
/* Image with Ubuntu 22.04, QT 6.9.0, Android SDK/NDK, Go, and Nim */
11+
docker {
12+
label 'linux'
13+
image 'statusteam/nim-status-client-build:1.0.2-qt6.9.0-android'
14+
alwaysPull true
15+
}
16+
}
17+
18+
parameters {
19+
booleanParam(
20+
name: 'RELEASE',
21+
description: 'Decides whether release credentials are used.',
22+
defaultValue: params.RELEASE ?: false
23+
)
24+
}
25+
26+
options {
27+
timestamps()
28+
/* Prevent Jenkins jobs from running forever */
29+
timeout(time: 45, unit: 'MINUTES')
30+
/* manage how many builds we keep */
31+
buildDiscarder(logRotator(
32+
numToKeepStr: '10',
33+
daysToKeepStr: '30',
34+
artifactNumToKeepStr: '3',
35+
))
36+
/* Allows combined build to copy */
37+
copyArtifactPermission('/status-desktop/*')
38+
/* Abort old PR builds. */
39+
disableConcurrentBuilds(abortPrevious: isPRBuild)
40+
disableRestartFromStage()
41+
}
42+
43+
environment {
44+
USE_SYSTEM_NIM = "1"
45+
GOCACHE = "/tmp/go-cache"
46+
GOMODCACHE = "/tmp/go-mod-cache"
47+
GOTMPDIR = "/tmp"
48+
STATUS_APK_ARTIFACT = "pkg/Status-tablet-${BUILD_NUMBER}.apk"
49+
PLATFORM = "android/arm64"
50+
QT_ANDROID_PATH = "/opt/qt/6.9.0/android_arm64_v8a"
51+
STATUS_APK = "${WORKSPACE}/mobile/bin/android/qt6/default/Status-tablet.apk"
52+
}
53+
54+
stages {
55+
stage('Prepare') {
56+
steps {
57+
sh 'git submodule update --init --recursive'
58+
}
59+
}
60+
61+
stage('Build Android APK') {
62+
steps {
63+
sh """
64+
make mobile-clean
65+
make -j${utils.getProcCount()} mobile-build V=3 USE_SYSTEM_NIM=1
66+
"""
67+
}
68+
}
69+
70+
stage('Package APK') {
71+
steps {
72+
sh """
73+
mkdir -p pkg
74+
cp '${env.STATUS_APK}' '${env.STATUS_APK_ARTIFACT}'
75+
ls -la '${env.STATUS_APK_ARTIFACT}'
76+
"""
77+
}
78+
}
79+
80+
stage('Parallel Upload') {
81+
parallel {
82+
stage('Upload') {
83+
steps {
84+
script {
85+
env.PKG_URL = s5cmd.upload(env.STATUS_APK_ARTIFACT)
86+
jenkins.setBuildDesc(APK: env.PKG_URL)
87+
}
88+
}
89+
}
90+
stage('Archive') {
91+
steps {
92+
archiveArtifacts env.STATUS_APK_ARTIFACT
93+
}
94+
}
95+
}
96+
}
97+
}
98+
99+
post {
100+
success { script { github.notifyPR(true) } }
101+
failure { script { github.notifyPR(false) } }
102+
cleanup { sh './scripts/clean-git.sh' }
103+
}
104+
}
105+

ci/Jenkinsfile.qt-build

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/env groovy
2+
3+
4+
pipeline {
5+
agent {
6+
label 'linux && x86_64 && qt-builder'
7+
}
8+
9+
options {
10+
buildDiscarder(logRotator(numToKeepStr: '20'))
11+
timestamps()
12+
timeout(time: 12, unit: 'HOURS')
13+
}
14+
15+
parameters {
16+
string(
17+
name: 'QT_VERSION',
18+
defaultValue: '6.9.0',
19+
description: 'Qt version to build'
20+
)
21+
string(
22+
name: 'DOCKER_TAG',
23+
defaultValue: '1.0.2-qt6.9.0-android',
24+
description: 'Docker image tag for the final image'
25+
)
26+
booleanParam(
27+
name: 'PUSH_TO_DOCKERHUB',
28+
defaultValue: true,
29+
description: 'Push the final image to DockerHub'
30+
)
31+
booleanParam(
32+
name: 'BUILD_QT_FROM_SOURCE',
33+
defaultValue: true,
34+
description: 'Build Qt from source (takes several hours)'
35+
)
36+
}
37+
38+
environment {
39+
DOCKER_REGISTRY = 'statusteam'
40+
DOCKER_IMAGE_BASE = 'nim-status-client-build'
41+
MOBILE_BUILD_DIR = "${WORKSPACE}/mobile/docker"
42+
}
43+
44+
stages {
45+
46+
stage('Build Qt from Source') {
47+
when {
48+
expression { params.BUILD_QT_FROM_SOURCE == true }
49+
}
50+
steps {
51+
script {
52+
// Build qt-dev-base stage for Qt source compilation
53+
dir("${MOBILE_BUILD_DIR}") {
54+
def qtDevImage = "${DOCKER_REGISTRY}/qt-dev-base-temp:${BUILD_ID}"
55+
sh """
56+
docker build \
57+
--target qt-dev-base \
58+
--build-arg TARGETARCH=amd64 \
59+
--build-arg JAVA_VERSION=17 \
60+
--build-arg ANDROID_API_LEVEL=35 \
61+
--build-arg ANDROID_NDK_VERSION=27.2.12479018 \
62+
-t ${qtDevImage} .
63+
"""
64+
65+
// Run Qt build in the container
66+
docker.image(qtDevImage).inside("-u root -v ${WORKSPACE}/qt_export:/root/export -v ${WORKSPACE}/scripts:/root/scripts") {
67+
dir('/root') {
68+
sh "/root/scripts/build_qt_android.sh"
69+
}
70+
}
71+
72+
// Clean up temp image
73+
sh "docker rmi ${qtDevImage} || true"
74+
}
75+
}
76+
}
77+
}
78+
79+
stage('Build Docker Images') {
80+
steps {
81+
script {
82+
dir("${MOBILE_BUILD_DIR}") {
83+
// Copy Qt exports if they exist
84+
sh """
85+
if [ -d ${WORKSPACE}/qt_export ]; then
86+
cp -r ${WORKSPACE}/qt_export .
87+
fi
88+
"""
89+
90+
// Build final mobile-build stage
91+
sh """
92+
docker build \
93+
--build-arg QTVER=${params.QT_VERSION} \
94+
--build-arg TARGETARCH=amd64 \
95+
--build-arg JAVA_VERSION=17 \
96+
--build-arg ANDROID_API_LEVEL=35 \
97+
--build-arg ANDROID_NDK_VERSION=27.2.12479018 \
98+
--build-arg GOLANG_VERSION=1.23.10 \
99+
--build-arg NIM_VERSION=2.0.12 \
100+
--build-arg NIX_VERSION=2.24.11 \
101+
--target mobile-build \
102+
-t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BASE}:${params.DOCKER_TAG} .
103+
"""
104+
105+
// Clean up qt_export copy
106+
sh "rm -rf qt_export || true"
107+
}
108+
}
109+
}
110+
}
111+
112+
stage('Test Images') {
113+
parallel {
114+
stage('Test Mobile Build Image') {
115+
steps {
116+
script {
117+
def testImage = "${DOCKER_REGISTRY}/${DOCKER_IMAGE_BASE}:${params.DOCKER_TAG}"
118+
docker.image(testImage).inside('--entrypoint=""') {
119+
sh "qmake --version || echo 'qmake not found'"
120+
sh "nim --version"
121+
sh "go version"
122+
sh "protoc --version"
123+
sh "java -version"
124+
sh "ls -la /opt/qt/${params.QT_VERSION}/ || echo 'Qt directory not found'"
125+
}
126+
}
127+
}
128+
}
129+
130+
}
131+
}
132+
133+
stage('Push to DockerHub') {
134+
when {
135+
expression { params.PUSH_TO_DOCKERHUB == true }
136+
}
137+
steps {
138+
script {
139+
withCredentials([
140+
usernamePassword(
141+
credentialsId: 'dockerhub-statusteam-bot',
142+
usernameVariable: 'DOCKER_USER',
143+
passwordVariable: 'DOCKER_PASS'
144+
)
145+
]) {
146+
sh """
147+
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BASE}:${params.DOCKER_TAG}
148+
docker logout
149+
"""
150+
}
151+
}
152+
}
153+
}
154+
}
155+
156+
post {
157+
always { cleanWs() }
158+
success { script { github.notifyPR(true) } }
159+
failure { script { github.notifyPR(false) } }
160+
}
161+
}

0 commit comments

Comments
 (0)