-
Notifications
You must be signed in to change notification settings - Fork 4
/
Jenkinsfile
326 lines (303 loc) · 13 KB
/
Jenkinsfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
void resetSourceTree() {
echo 'Reseting source tree...'
dir(env.SOURCE_DIR) {
sh '''#!/usr/bin/env bash
repo forall -c "git reset --hard"'''
}
}
int cleanUp() {
echo 'Cleaning up environment...'
dir(env.SOURCE_DIR) {
ansiColor('xterm') {
return sh (returnStatus: true, script: '''#!/usr/bin/env bash
# Load build environment
. build/envsetup.sh
lunch $LUNCH
# Clean up PRODUCT directory keeping the common stuff
# mkdir -p $OUT
# rm -rf $(cd $OUT/../;pwd)
# make clean
# Clean up temporary incoming directory
rm -rf $INCOMING_TMP_DIR
''')
}
}
}
void repoPickGerritChanges() {
echo 'Applying gerrit changes...'
dir(env.SOURCE_DIR) {
return sh (returnStatus: true, script: '''#!/usr/bin/env bash
function check_gerrit_picks_result {
if [ "0" -ne "$?" ]
then
echo "Gerrit picks failed."
exit 1
fi
}
if [ ! -z "$GERRIT_CHANGES" ]
then
IS_HTTP=$(echo $GERRIT_CHANGES | grep http)
if [ -z "$IS_HTTP" ]
then
python ./vendor/unlegacy/build/tools/repopick.py $GERRIT_CHANGES
check_gerrit_picks_result
else
python ./vendor/unlegacy/build/tools/repopick.py $(curl $GERRIT_CHANGES)
check_gerrit_picks_result
fi
fi''')
}
}
int build(String buildTargets) {
echo 'Building android...'
env.BUILD_TARGETS = buildTargets
dir(env.SOURCE_DIR) {
ansiColor('xterm') {
return sh (returnStatus: true, script: '''#!/usr/bin/env bash
# Make sure ccache is in PATH
export PATH="$PATH:/opt/local/bin/:$PWD/prebuilts/misc/$(uname|awk '{print tolower($0)}')-x86/ccache"
# Load build environment
. build/envsetup.sh
# Try to lunch
lunch $LUNCH
if [ "0" -ne "$?" ]
then
echo "Lunch failed."
exit 1
fi
# Setup ccache size
#if [ ! "$(ccache -s|grep -E 'max cache size'|awk '{print $4}')" = "100.0" ]
#then
# ccache -M 100G
#fi
# Check if we need to cleanup the OUT directory
LAST_CLEAN=0
if [ -f .clean ]
then
LAST_CLEAN=$(date -r .clean +%s)
fi
TIME_SINCE_LAST_CLEAN=$(expr $(date +%s) - $LAST_CLEAN)
# Convert this to hours
TIME_SINCE_LAST_CLEAN=$(expr $TIME_SINCE_LAST_CLEAN / 60 / 60)
if [ $TIME_SINCE_LAST_CLEAN -gt "168" -o $CLEAN = "true" ]
then
echo "Cleaning!"
touch .clean
make clean
else
echo -e "Skipping full clean: $TIME_SINCE_LAST_CLEAN hours since last clean.\nCleaning PRODUCT directory..."
mkdir -p $OUT
rm -rf $(cd $OUT/../;pwd)
fi
OTATOOLS_TARGET=otatools
time make -j$JOBS $BUILD_TARGETS $OTATOOLS_TARGET
if [ "0" -ne "$?" ]
then
echo "Build failed."
exit 2
fi
''')
}
}
}
int createOtaPackage(String otaType) {
echo 'Creating OTA Package...'
env.OTA_TYPE = otaType
dir(env.SOURCE_DIR) {
ansiColor('xterm') {
return sh (returnStatus: true, script: '''#!/usr/bin/env bash
export OTA_EXIT_CODE=0
# Load build environment
. build/envsetup.sh
lunch $LUNCH
cp -f $OUT/boot.img ${ARCHIVE_DIR}/. || export OTA_EXIT_CODE=3
cp -f $OUT/recovery.img ${ARCHIVE_DIR}/. || export OTA_EXIT_CODE=4
if [ "${BOOT_AND_RECOVERY_IMAGES_ONLY}" == "true" ]
then
# Clean up PRODUCT directory keeping the common stuff
mkdir -p $OUT
rm -rf $(cd $OUT/../;pwd)
exit $OTA_EXIT_CODE
fi
export DEVICE_TARGET_FILES_PATH=$DEVICE_TARGET_FILES_DIR/$(date -u +%Y%m%d-%H%M).zip
mkdir -p $DEVICE_TARGET_FILES_DIR
cp ${OUT}/obj/PACKAGING/target_files_intermediates/*target_files*.zip $DEVICE_TARGET_FILES_PATH
rm -f $(readlink ${DEVICE_TARGET_FILES_DIR}/last.zip) 2>/dev/null
rm -f ${DEVICE_TARGET_FILES_DIR}/last.zip 2>/dev/null
rm -f ${DEVICE_TARGET_FILES_DIR}/last.prop 2>/dev/null
mv ${DEVICE_TARGET_FILES_DIR}/latest.zip ${DEVICE_TARGET_FILES_DIR}/last.zip 2>/dev/null
mv ${DEVICE_TARGET_FILES_DIR}/latest.prop ${DEVICE_TARGET_FILES_DIR}/last.prop 2>/dev/null
ln -sf $DEVICE_TARGET_FILES_PATH ${DEVICE_TARGET_FILES_DIR}/latest.zip
cp -f $OUT/system/build.prop ${DEVICE_TARGET_FILES_DIR}/latest.prop
cp -f $OUT/system/build.prop ${ARCHIVE_DIR}/build.prop
export PLATFORM_VERSION=`grep ro.build.version.release $DEVICE_TARGET_FILES_DIR/latest.prop | cut -d '=' -f2`
export OUTPUT_FILE_NAME=${BUILD_PRODUCT}_${DEVICE}-${PLATFORM_VERSION}
export LATEST_DATE=$(date -r $DEVICE_TARGET_FILES_DIR/latest.prop +%Y%m%d-%H%M)
export OTA_OPTIONS="-v -p $ANDROID_HOST_OUT $OTA_COMMON_OPTIONS"
export OTA_INC_OPTIONS="$OTA_OPTIONS $OTA_INC_EXTRA_OPTIONS"
export OTA_FULL_OPTIONS="$OTA_OPTIONS $OTA_FULL_EXTRA_OPTIONS"
export OTA_INC_FAILED="false"
if [ "${MARK_AS_EXPERIMENTAL}" == "true" ] || [ ! -z "$GERRIT_CHANGES" ]
then
if [ ! -z "$EXPERIMENTAL_TAG" ]
then
export OUTPUT_FILE_NAME=${OUTPUT_FILE_NAME}-${EXPERIMENTAL_TAG}
else
export OUTPUT_FILE_NAME=${OUTPUT_FILE_NAME}-EXPERIMENTAL
fi
fi
if [ -f ${DEVICE_TARGET_FILES_DIR}/last.zip ] && [ "${OTA_TYPE}" == "incremental" ]
then
export LAST_DATE=$(date -r $DEVICE_TARGET_FILES_DIR/last.prop +%Y%m%d-%H%M)
export FILE_NAME=${OUTPUT_FILE_NAME}-${LAST_DATE}-TO-${LATEST_DATE}
./build/tools/releasetools/ota_from_target_files \
$OTA_INC_OPTIONS \
--incremental_from $DEVICE_TARGET_FILES_DIR/last.zip \
$DEVICE_TARGET_FILES_DIR/latest.zip $ARCHIVE_DIR/$FILE_NAME.zip || export OTA_INC_FAILED="true" && export OTA_EXIT_CODE=2
if [ -s $ARCHIVE_DIR/$FILE_NAME.zip ] || [ "${OTA_INC_FAILED}" == "true" ]
then
export FILE_NAME=${OUTPUT_FILE_NAME}-${LATEST_DATE}
./build/tools/releasetools/ota_from_target_files \
$OTA_FULL_OPTIONS \
$DEVICE_TARGET_FILES_DIR/latest.zip $ARCHIVE_DIR/$FILE_NAME.zip || export OTA_EXIT_CODE=1
else
rm -f $ARCHIVE_DIR/$FILE_NAME.*
fi
else
export FILE_NAME=${OUTPUT_FILE_NAME}-${LATEST_DATE}
./build/tools/releasetools/ota_from_target_files \
$OTA_FULL_OPTIONS \
$DEVICE_TARGET_FILES_DIR/latest.zip $ARCHIVE_DIR/$FILE_NAME.zip || export OTA_EXIT_CODE=1
fi
for f in $(ls $ARCHIVE_DIR/*.zip*)
do
md5sum $f | cut -d ' ' -f1 > $ARCHIVE_DIR/$(basename $f).md5sum
done
# Clean up PRODUCT directory keeping the common stuff
mkdir -p $OUT
rm -rf $(cd $OUT/../;pwd)
exit $OTA_EXIT_CODE
''')
}
}
}
int publishToPortal(String path) {
echo 'Publishing OTA Package to builds portal...'
env.OTA_URL_PATH = path
dir(env.SOURCE_DIR) {
ansiColor('xterm') {
return sh (returnStatus: true, script: '''#!/usr/bin/env bash
export PLATFORM_VERSION=`grep ro.build.version.release ${ARCHIVE_DIR}/build.prop | cut -d '=' -f2`
export FILENAME=$(basename $(ls ${ARCHIVE_DIR}/${BUILD_PRODUCT}_${DEVICE}-${PLATFORM_VERSION}*.zip))
export MD5SUM=$(cat ${ARCHIVE_DIR}/${BUILD_PRODUCT}_${DEVICE}-${PLATFORM_VERSION}*.zip.md5sum)
export OTA_URL="${OTA_URL_PATH}/${FILENAME}"
export TYPE=release
if [ "${MARK_AS_EXPERIMENTAL}" == "true" ] || [ ! -z "$GERRIT_CHANGES" ]
then
export TYPE=test
fi
export POST_DATA="{ \\"device\\": \\"${DEVICE}\\", \\"filename\\": \\"${FILENAME}\\", \\"md5sum\\": \\"${MD5SUM}\\", \\"romtype\\": \\"${TYPE}\\", \\"url\\": \\"${OTA_URL}\\", \\"version\\": \\"${PLATFORM_VERSION}\\" }"
echo "${POST_DATA}" > /tmp/postdata
curl -X POST ${BUILDS_PORTAL_URL}/api/v1/add_build -H "apiKey:$API_KEY" -H "Content-Type:application/json" --data-binary "@/tmp/postdata" 2>/dev/null
curl -X POST ${BUILDS_PORTAL_URL}/api/v1/purgecache -H "apiKey:$API_KEY" 2>/dev/null
rm -f /tmp/postdata
''')
}
}
}
node('builder') {
try {
currentBuild.description = env.BUILD_PRODUCT+'_'+env.DEVICE+'-'+env.BRANCH
stage('Preparation') {
echo 'Setting up environment...'
env.WORKSPACE = '/unlegacy'
env.SOURCE_DIR = env.WORKSPACE + '/' + env.BRANCH
env.ARCHIVE_DIR = env.WORKSPACE + '/archive'
env.INCOMING_TMP_DIR = '/tmp/incoming/'
env.INCOMING_DIR = ((env.PUBLISH_BUILD == 'true') ? '/incoming/' : env.INCOMING_TMP_DIR ) + env.BRANCH
env.DEVICE_TARGET_FILES_DIR = env.INCOMING_DIR + '/' + env.DEVICE
env.LUNCH = env.BUILD_PRODUCT + '_' + env.DEVICE + '-' + env.BUILD_TYPE
env.CCACHE_DIR = env.WORKSPACE + '/.ccache/' + env.BRANCH
env.USE_CCACHE = 1
env.CCACHE_NLEVELS = 4
env.PYTHONDONTWRITEBYTECODE = 1
// Number of available cores to build
echo 'Getting the number of available cores...'
env.JOBS = sh (returnStdout: true, script: '''#!/usr/bin/env bash
expr 0 + $(grep -c ^processor /proc/cpuinfo)
''').trim()
echo 'Cores available: ' + env.JOBS
echo 'Defining branch based prerequisites...'
if (env.BRANCH == 'aosp-4.4') {
sh script: '''#!/usr/bin/env bash
update-java-alternatives -s java-1.7.0-openjdk-amd64 2>/dev/null'''
env.OTA_COMMON_OPTIONS = ''
env.OTA_INC_EXTRA_OPTIONS = ''
env.OTA_FULL_EXTRA_OPTIONS = ''
echo 'BRANCH=aosp-4.4->[JDK=openjdk-7,OTA_COMMON_OPTIONS="'+env.OTA_COMMON_OPTIONS+'",OTA_INC_OPTIONS="'+env.OTA_INC_OPTIONS+'",OTA_FULL_OPTIONS="'+env.OTA_FULL_OPTIONS+'"]'
} else {
sh script: '''#!/usr/bin/env bash
update-java-alternatives -s java-1.8.0-openjdk-amd64 2>/dev/null'''
env.OTA_COMMON_OPTIONS = '-t ' + env.JOBS
env.OTA_INC_EXTRA_OPTIONS = ''
env.OTA_FULL_EXTRA_OPTIONS = '--block'
echo 'BRANCH='+env.BRANCH+'->[JDK=openjdk-8,OTA_COMMON_OPTIONS="'+env.OTA_COMMON_OPTIONS+'",OTA_INC_OPTIONS="'+env.OTA_INC_OPTIONS+'",OTA_FULL_OPTIONS="'+env.OTA_FULL_OPTIONS+'"]'
}
echo 'Creating build directory structure...'
sh script: '''#!/usr/bin/env bash
mkdir -p /unlegacy/$BRANCH
mkdir -p /unlegacy/repo-mirror
ln -sf /unlegacy/repo-mirror /unlegacy/$BRANCH/.repo'''
echo 'Preparing archive directory...'
sh '''#!/usr/bin/env bash
mkdir -p $ARCHIVE_DIR
rm -rf $ARCHIVE_DIR/**'''
}
stage('Code syncing') {
checkout poll: false, changelog: false, scm: [$class: 'RepoScm', currentBranch: true, depth: 1, destinationDir: '/unlegacy/'+env.BRANCH, forceSync: true, jobs: 8, manifestBranch: env.BRANCH, manifestRepositoryUrl: 'https://github.com/Unlegacy-Android/android.git', noTags: true, quiet: true, showAllChanges: true, resetFirst: false, trace: false]
// TODO: Create a saveManifest()
ret = repoPickGerritChanges()
if ( ret != 0 )
error('Gerrit picks failed.')
}
stage('Build process') {
buildTargets = 'target-files-package'
if ( env.BOOT_AND_RECOVERY_IMAGES_ONLY == 'true' )
buildTargets = 'bootimage recoveryimage'
ret = build(buildTargets)
switch (ret) {
case 1: error('Lunch failed!'); break;
case 2: error('Build failed!'); break;
default: echo "Build successful."
}
}
stage('OTA Package') {
ret = createOtaPackage('full')
if ( ret != 0 )
error('Failed to create full OTA Package!')
}
stage('Archiving') {
dir(env.ARCHIVE_DIR) {
archiveArtifacts allowEmptyArchive: true, artifacts: '**', excludes: '*-ota-*', fingerprint: true, onlyIfSuccessful: true
}
}
stage('Publishing') {
dir(env.ARCHIVE_DIR) {
if (env.PUBLISH_BUILD == 'true') {
echo 'Publishing...'
sh returnStdout: false, script: 'rsync -a -e ssh --include "*.zip*" --exclude="*.img" --exclude="*.prop" . builds@mirror:./$BRANCH/$DEVICE/'
publishToPortal("https://builds.unlegacy-android.org/"+env.BRANCH+"/"+env.DEVICE)
} else
echo 'Will not publish anything because PUBLISH_BUILD=false'
}
}
cleanUp()
currentBuild.result = 'SUCCESS'
slackSend (color: 'good', message: "Jenkins Builder - Job SUCCESS: '${env.JOB_NAME} [${env.BUILD_NUMBER} - ${currentBuild.description}]' (${env.BUILD_URL})")
} catch (Exception e) {
try { cleanUp() } catch (Exception ex) { }
currentBuild.result = 'FAILURE'
slackSend (color: 'danger', message: "Jenkins Builder - Job FAILED: '${env.JOB_NAME} [${env.BUILD_NUMBER} - ${currentBuild.description}]' (${env.BUILD_URL})")
}
echo "RESULT: ${currentBuild.result}"
}