From 56d3ae85586143f48c130f01b66792faa4a91a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Soko=C5=82owski?= Date: Wed, 8 Aug 2018 14:11:55 -0400 Subject: [PATCH] cleanup jenkinsfile and prepare for builds on new linux slaves --- ci/Jenkinsfile.nightly_desktop | 306 +++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 ci/Jenkinsfile.nightly_desktop diff --git a/ci/Jenkinsfile.nightly_desktop b/ci/Jenkinsfile.nightly_desktop new file mode 100644 index 0000000000..7022c9e186 --- /dev/null +++ b/ci/Jenkinsfile.nightly_desktop @@ -0,0 +1,306 @@ +properties([ + buildDiscarder(logRotator( + numToKeepStr: '2', + daysToKeepStr: '3', + artifactNumToKeepStr: '2', + artifactDaysToKeepStr: '3' + )) +]) + +env.LANG = 'en_US.UTF-8' +env.LANGUAGE = 'en_US.UTF-8' +env.LC_ALL = 'en_US.UTF-8' + +app_url = '' +dmg_url = '' +app_file = '' +dmg_file = '' +commit = '' +testPassed = true +packageFolder = './StatusImPackage' +external_modules_dir = [ + 'node_modules/react-native-i18n/desktop', + 'node_modules/react-native-config/desktop', + 'node_modules/react-native-fs/desktop', + 'node_modules/react-native-http-bridge/desktop', + 'node_modules/react-native-webview-bridge/desktop', + 'node_modules/react-native-keychain/desktop', + 'node_modules/react-native-securerandom/desktop', + 'modules/react-native-status/desktop', +] + +def installJSDeps() { + def attempt = 1 + def maxAttempts = 10 + def installed = false + sh 'node -v' + sh 'npm -v' + while (!installed && attempt <= maxAttempts) { + println "#${attempt} attempt to install npm deps" + sh 'scripts/prepare-for-platform.sh desktop' + sh 'npm install' + installed = fileExists('node_modules/web3/index.js') + attemp = attempt + 1 + } +} + +def doGitRebase() { + try { + sh 'git rebase origin/develop' + } catch (e) { + sh 'git rebase --abort' + throw e + } +} + +def cleanupBuild() { + sh 'rm -rf node_modules' + sh "rm -rf ${packageFolder}" + sh 'rm -rf desktop/modules' + sh 'rm -rf desktop/node_modules' +} + +def cleanupAndDeps() { + cleanupBuild() + sh 'cp .env.jenkins .env' + sh 'lein deps' + installJSDeps() +} + +def slackNotify(message, color = 'good') { + slackSend( + color: color, + channel: '#jenkins-desktop', + message: "develop (${env.CHANGE_BRANCH}) ${message} ${env.BUILD_URL}" + ) +} + +def buildClojureScript() { + sh 'rm -f index.desktop.js' + sh 'lein prod-build-desktop' + sh "mkdir ${packageFolder}" + sh """ + react-native bundle \\ + --entry-file index.desktop.js \\ + --dev false --platform desktop \\ + --bundle-output ${packageFolder}/StatusIm.jsbundle \\ + --assets-dest ${packageFolder}/assets + """ +} + +def uploadArtifact(filename) { + def domain = 'ams3.digitaloceanspaces.com' + def bucket = 'status-im-desktop' + withCredentials([usernamePassword( + credentialsId: 'digital-ocean-access-keys', + usernameVariable: 'DO_ACCESS_KEY', + passwordVariable: 'DO_SECRET_KEY' + )]) { + sh """ + s3cmd \\ + --acl-public \\ + --host='${domain}' \\ + --host-bucket='%(bucket)s.${domain}' \\ + --access_key=${DO_ACCESS_KEY} \\ + --secret_key=${DO_SECRET_KEY} \\ + put ${filename} s3://${bucket}/ + """ + + } + def url = "https://${bucket}.${domain}/${filename}" + return url +} + +parallel( + 'MacOS build': { + timeout(90) { + node('macos') { + load "$HOME/env.groovy" + + try { + stage('Git & Deps') { + slackNotify('MacOS build started.') + checkout scm + doGitRebase() + cleanupAndDeps() + commit = sh( + returnStdout: true, + script: 'git rev-parse HEAD' + ).trim().take(6) + } + + stage('Build ClojureScript') { + buildClojureScript() + } + + stage('Build MacOS binaries') { + /* add path for QT installation binaries */ + env.PATH = "/Users/administrator/qt/5.9.1/clang_64/bin:${env.PATH}" + dir('desktop') { + sh 'rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile' + sh """ + cmake -Wno-dev \\ + -DCMAKE_BUILD_TYPE=Release \\ + -DEXTERNAL_MODULES_DIR='${external_modules_dir.join(";")}' \\ + -DJS_BUNDLE_PATH='${workspace}/${packageFolder}/StatusIm.jsbundle' \\ + -DCMAKE_CXX_FLAGS:='-DBUILD_FOR_BUNDLE=1' + """ + sh 'make' + } + } + + stage('Create MacOS Bundle') { + dir(packageFolder) { + sh 'git clone https://github.com/vkjr/StatusAppFiles.git' + sh 'unzip StatusAppFiles/StatusIm.app.zip' + sh 'cp -r assets/share/assets StatusIm.app/Contents/MacOs' + sh 'chmod +x StatusIm.app/Contents/MacOs/ubuntu-server' + sh 'cp ../desktop/bin/StatusIm StatusIm.app/Contents/MacOs' + sh """ + macdeployqt StatusIm.app -verbose=1 -dmg \\ + -qmldir='${workspace}/node_modules/react-native/ReactQt/runtime/src/qml/' + """ + sh 'rm -fr StatusAppFiles' + dmg_file = "StatusIm-${commit}.dmg" + sh "mv StatusIm.dmg ${dmg_file}" + } + } + + stage('Archive Artifact') { + archiveArtifacts "StatusImPackage/${dmg_file}" + } + + stage('Upload Artifacts') { + dir(packageFolder) { + dmg_url = uploadArtifact(dmg_file) + } + } + + slackNotify('MacOS build finished successfully.') + } catch (e) { + slackNotify('Failed to build on MacOS.', color: 'bad') + throw e + } finally { + cleanupBuild() + } + } + } + }, + 'Linux build': { + timeout(90) { + node ('linux-new') { + def qt_bin = '/opt/qt59/bin' + + try { + stage('Git & Deps') { + slackNotify('Linux build started.') + checkout scm + doGitRebase() + cleanupAndDeps() + commit = sh( + returnStdout: true, + script: 'git rev-parse HEAD' + ).trim().take(6) + } + + stage('Build ClojureScript') { + buildClojureScript() + } + + stage('Build Linux binaries') { + /* add path for QT installation binaries */ + env.PATH = "${qt_bin}:${env.PATH}" + dir('desktop') { + sh 'rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile' + sh """ + cmake -Wno-dev \\ + -DCMAKE_BUILD_TYPE=Release \\ + -DEXTERNAL_MODULES_DIR='${external_modules_dir.join(";")}' \\ + -DJS_BUNDLE_PATH='${workspace}/${packageFolder}/StatusIm.jsbundle' \\ + -DCMAKE_CXX_FLAGS:='-DBUILD_FOR_BUNDLE=1' + """ + sh 'make' + } + } + + stage('Create Linux AppImage') { + dir(packageFolder) { + sh 'rm -rf StatusImAppImage' + /* TODO this needs to be fixed: status-react/issues/5378 */ + sh 'cp /opt/StatusImAppImage.zip ./' + sh 'unzip ./StatusImAppImage.zip' + sh 'rm -rf AppDir' + sh 'mkdir AppDir' + } + sh "cp -r ./deployment/linux/usr ${packageFolder}/AppDir" + sh "cp ./deployment/linux/.env ${packageFolder}/AppDir" + sh "cp ./desktop/bin/StatusIm ${packageFolder}/AppDir/usr/bin" + sh 'wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage' + sh 'chmod a+x ./linuxdeployqt-continuous-x86_64.AppImage' + + sh 'rm -f Application-x86_64.AppImage' + sh 'rm -f StatusIm-x86_64.AppImage' + + sh "ldd ${packageFolder}/AppDir/usr/bin/StatusIm" + sh """ + ./linuxdeployqt-continuous-x86_64.AppImage \\ + ${packageFolder}/AppDir/usr/share/applications/StatusIm.desktop \\ + -verbose=3 -always-overwrite -no-strip \\ + -no-translations -bundle-non-qt-libs \\ + -qmake=${qt_bin}/qmake \\ + -extra-plugins=imageformats/libqsvg.so \\ + -qmldir='${workspace}/node_modules/react-native' + """ + dir(packageFolder) { + sh 'ldd AppDir/usr/bin/StatusIm' + sh 'cp -r assets/share/assets AppDir/usr/bin' + sh 'cp -rf StatusImAppImage/* AppDir/usr/bin' + sh 'rm -f AppDir/usr/bin/StatusIm.AppImage' + } + sh """ + ./linuxdeployqt-continuous-x86_64.AppImage \\ + ${packageFolder}/AppDir/usr/share/applications/StatusIm.desktop \\ + -verbose=3 -appimage -qmake=${qt_bin}/qmake + """ + dir(packageFolder) { + sh 'ldd AppDir/usr/bin/StatusIm' + sh 'rm -rf StatusIm.AppImage' + app_file = "StatusIm-${commit}.AppImage" + sh "mv ../StatusIm-x86_64.AppImage ${app_file}" + } + } + + stage('Archive Artifacts') { + archiveArtifacts "StatusImPackage/${app_file}" + } + + stage('Upload Artifacts') { + dir(packageFolder) { + app_url = uploadArtifact(app_file) + } + } + + slackNotify('Linux build finished successfully.') + } catch (e) { + slackNotify('Failed to build on Linux.', color: 'bad') + throw e + } finally { + cleanupBuild() + } + } + } + } +) + +stage('Update nightly links') { + println "Publishing URLs:" + println dmg_url + println app_url + build( + job: 'misc/status-im.github.io-update_env', + parameters: [ + [$class: 'StringParameterValue', name: 'DMG_URL', value: dmg_url], + [$class: 'StringParameterValue', name: 'IOS_URL', value: app_url] + ] + ) +}