diff --git a/android/app/build.gradle b/android/app/build.gradle
index eb3f3f1338..c5d63c01b1 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -116,6 +116,15 @@ def getVersionName = { ->
}
}
+def getBuildUrl = { ->
+ new ByteArrayOutputStream().withStream { stdOut ->
+ if (project.hasProperty("buildUrl")) {
+ return project.buildUrl
+ }
+ return 'Local Build'
+ }
+}
+
android {
compileSdkVersion 27
@@ -130,6 +139,13 @@ android {
abiFilters "armeabi-v7a", "arm64-v8a", "x86"
}
}
+ /**
+ * Arbitrary project metadata
+ * https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
+ **/
+ project.ext {
+ buildUrl = getBuildUrl()
+ }
/**
* Fix for: (https://github.com/ReactiveX/RxJava/issues/4445)
* Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
diff --git a/ci/Jenkinsfile.android b/ci/Jenkinsfile.android
index 6da3dfed61..714b14f9e9 100644
--- a/ci/Jenkinsfile.android
+++ b/ci/Jenkinsfile.android
@@ -3,9 +3,9 @@ pipeline {
options {
buildDiscarder(logRotator(
- numToKeepStr: '10',
+ numToKeepStr: '20',
daysToKeepStr: '30',
- artifactNumToKeepStr: '6',
+ artifactNumToKeepStr: '10',
))
}
diff --git a/ci/Jenkinsfile.combined b/ci/Jenkinsfile.combined
index 56ff8feee9..8c306debd2 100644
--- a/ci/Jenkinsfile.combined
+++ b/ci/Jenkinsfile.combined
@@ -13,48 +13,47 @@ pipeline {
stages {
stage('Tag') {
steps { script {
- common = load('ci/common.groovy')
+ cmn = load('ci/common.groovy')
/* to avoid missing build tag parallel builds */
- print "Build Number: ${common.tagBuild()}"
+ print "Build Number: ${cmn.tagBuild(true)}"
} }
}
stage('Build') {
parallel {
stage('MacOS') { steps { script {
- osx = common.buildBranch('status-react/combined/desktop-macos')
+ osx = cmn.buildBranch('status-react/combined/desktop-macos')
} } }
stage('Linux') { steps { script {
- nix = common.buildBranch('status-react/combined/desktop-linux')
+ nix = cmn.buildBranch('status-react/combined/desktop-linux')
} } }
stage('iOS') { steps { script {
- ios = common.buildBranch('status-react/combined/mobile-ios')
+ ios = cmn.buildBranch('status-react/combined/mobile-ios')
} } }
stage('Android') { steps { script {
- dro = common.buildBranch('status-react/combined/mobile-android')
+ dro = cmn.buildBranch('status-react/combined/mobile-android')
} } }
stage('Android e2e') { steps { script {
- e2e = common.buildBranch('status-react/combined/mobile-android', 'e2e')
+ e2e = cmn.buildBranch('status-react/combined/mobile-android', 'e2e')
} } }
}
}
stage('Archive') {
steps { script {
sh('rm -f pkg/*')
- common.copyArts('status-react/combined/desktop-macos', osx.number)
- common.copyArts('status-react/combined/desktop-linux', nix.number)
- common.copyArts('status-react/combined/mobile-android', dro.number)
- common.copyArts('status-react/combined/mobile-android', e2e.number)
+ cmn.copyArts('status-react/combined/desktop-macos', osx.number)
+ cmn.copyArts('status-react/combined/desktop-linux', nix.number)
+ cmn.copyArts('status-react/combined/mobile-android', dro.number)
+ cmn.copyArts('status-react/combined/mobile-android', e2e.number)
archiveArtifacts('pkg/*')
} }
}
stage('Upload') {
when { expression { params.BUILD_TYPE == 'nightly' } }
steps { script {
- def pkg = "StatusIm-${GIT_COMMIT.take(6)}"
- e2eUrl = common.uploadArtifact('pkg', "${pkg}-e2e.apk")
- apkUrl = common.uploadArtifact('pkg', "${pkg}.apk")
- dmgUrl = common.uploadArtifact('pkg', "${pkg}.dmg")
- appUrl = common.uploadArtifact('pkg', "${pkg}.AppImage")
+ e2eUrl = cmn.uploadArtifact(findFiles(glob: 'pkg/*.e2e.apk')[0].path)
+ apkUrl = cmn.uploadArtifact(findFiles(glob: "pkg/*.${params.BUILD_TYPE}.apk")[0].path)
+ dmgUrl = cmn.uploadArtifact(findFiles(glob: 'pkg/*.dmg')[0].path)
+ appUrl = cmn.uploadArtifact(findFiles(glob: 'pkg/*.AppImage')[0].path)
/* special case for iOS Diawi link */
ipaUrl = ios.getBuildVariables().get('DIAWI_URL')
} }
@@ -67,11 +66,12 @@ pipeline {
"<${currentBuild.absoluteUrl}|${currentBuild.displayName}> "+
"(${currentBuild.durationString})\n"+
(params.BUILD_TYPE == 'nightly' ?
- "E2E: ${e2eUrl}\n"+
- "APK: ${apkUrl}\n"+
- "IPA: ${ipaUrl}\n"+
- "DMG: ${dmgUrl}\n"+
- "APP: ${appUrl}\n"
+ "Packages: "+
+ "<${apkUrl}|Android>, "+
+ "(<${e2eUrl}|e2e>), "+
+ "<${ipaUrl}|iOS>, "+
+ "<${dmgUrl}|MacOS>, "+
+ "<${appUrl}|AppImage>"
: '')
),
color: 'good'
diff --git a/ci/Jenkinsfile.ios b/ci/Jenkinsfile.ios
index e4275603af..ece021d276 100644
--- a/ci/Jenkinsfile.ios
+++ b/ci/Jenkinsfile.ios
@@ -11,9 +11,9 @@ pipeline {
options {
buildDiscarder(logRotator(
- numToKeepStr: '10',
+ numToKeepStr: '20',
daysToKeepStr: '30',
- artifactNumToKeepStr: '1',
+ artifactNumToKeepStr: '10',
))
}
diff --git a/ci/Jenkinsfile.linux b/ci/Jenkinsfile.linux
index 1747d94be4..c0db1c9eda 100644
--- a/ci/Jenkinsfile.linux
+++ b/ci/Jenkinsfile.linux
@@ -3,9 +3,9 @@ pipeline {
options {
buildDiscarder(logRotator(
- numToKeepStr: '10',
+ numToKeepStr: '20',
daysToKeepStr: '30',
- artifactNumToKeepStr: '1',
+ artifactNumToKeepStr: '10',
))
}
@@ -37,7 +37,7 @@ pipeline {
}
stage('Bundle') {
steps {
- script { app = desktop.bundleLinux() }
+ script { app = desktop.bundleLinux(params.BUILD_TYPE) }
}
}
stage('Archive') {
diff --git a/ci/Jenkinsfile.macos b/ci/Jenkinsfile.macos
index b19f194228..28126e266c 100644
--- a/ci/Jenkinsfile.macos
+++ b/ci/Jenkinsfile.macos
@@ -3,9 +3,9 @@ pipeline {
options {
buildDiscarder(logRotator(
- numToKeepStr: '10',
+ numToKeepStr: '20',
daysToKeepStr: '30',
- artifactNumToKeepStr: '1',
+ artifactNumToKeepStr: '10',
))
}
@@ -37,7 +37,7 @@ pipeline {
}
stage('Bundle') {
steps {
- script { dmg = desktop.bundleMacOS() }
+ script { dmg = desktop.bundleMacOS(params.BUILD_TYPE) }
}
}
stage('Archive') {
diff --git a/ci/android.groovy b/ci/android.groovy
index 1de9e3bf6b..a044f8de9e 100644
--- a/ci/android.groovy
+++ b/ci/android.groovy
@@ -15,15 +15,15 @@ def uploadArtifact() {
def compile(type = 'nightly') {
common.tagBuild()
- def gradleOpt = ''
+ def gradleOpt = "-PbuildUrl='${currentBuild.absoluteUrl}' "
if (type == 'release') {
- gradleOpt = "-PreleaseVersion=${common.version()}"
+ gradleOpt += "-PreleaseVersion='${common.version()}'"
}
dir('android') {
sh './gradlew react-native-android:installArchives'
sh "./gradlew assembleRelease ${gradleOpt}"
}
- def pkg = "StatusIm-${GIT_COMMIT.take(6)}${(type == 'e2e' ? '-e2e' : '')}.apk"
+ def pkg = common.pkgFilename(type, 'apk')
sh "cp android/app/build/outputs/apk/release/app-release.apk ${pkg}"
return pkg
}
diff --git a/ci/common.groovy b/ci/common.groovy
index dc354fd6e4..27bdc7a532 100644
--- a/ci/common.groovy
+++ b/ci/common.groovy
@@ -44,7 +44,8 @@ def doGitRebase() {
}
}
-def tagBuild() {
+def tagBuild(increment = false) {
+ def opts = (increment ? '--increment' : '')
withCredentials([[
$class: 'UsernamePasswordMultiBinding',
credentialsId: 'status-im-auto',
@@ -53,14 +54,23 @@ def tagBuild() {
]]) {
return sh(
returnStdout: true,
- script: './scripts/build_no.sh --increment'
+ script: "./scripts/build_no.sh ${opts}"
).trim()
}
}
-def uploadArtifact(path, filename) {
+def getDirPath(path) {
+ return path.tokenize('/')[0..-2].join('/')
+}
+
+def getFilename(path) {
+ return path.tokenize('/')[-1]
+}
+
+def uploadArtifact(path) {
+ /* defaults for upload */
def domain = 'ams3.digitaloceanspaces.com'
- def bucket = 'status-im-desktop'
+ def bucket = 'status-im'
withCredentials([usernamePassword(
credentialsId: 'digital-ocean-access-keys',
usernameVariable: 'DO_ACCESS_KEY',
@@ -73,11 +83,23 @@ def uploadArtifact(path, filename) {
--host-bucket='%(bucket)s.${domain}' \\
--access_key=${DO_ACCESS_KEY} \\
--secret_key=${DO_SECRET_KEY} \\
- put ${path}/${filename} s3://${bucket}/
+ put ${path} s3://${bucket}/
"""
}
- def url = "https://${bucket}.${domain}/${filename}"
- return url
+ return "https://${bucket}.${domain}/${getFilename(path)}"
+}
+
+def timestamp() {
+ def now = new Date(currentBuild.timeInMillis)
+ return now.format('yyMMdd.HHmmss', TimeZone.getTimeZone('UTC'))
+}
+
+def gitCommit() {
+ return GIT_COMMIT.take(6)
+}
+
+def pkgFilename(type, ext) {
+ return "StatusIm.${timestamp()}.${gitCommit()}.${type}.${ext}"
}
return this
diff --git a/ci/desktop.groovy b/ci/desktop.groovy
index 4ee1ff3a45..f8d398a580 100644
--- a/ci/desktop.groovy
+++ b/ci/desktop.groovy
@@ -102,8 +102,8 @@ def compileLinux() {
}
}
-def bundleLinux() {
- def appFile
+def bundleLinux(type = 'nightly') {
+ def pkg
dir(packageFolder) {
sh 'rm -rf StatusImAppImage'
@@ -146,10 +146,10 @@ def bundleLinux() {
dir(packageFolder) {
sh 'ldd AppDir/usr/bin/StatusIm'
sh 'rm -rf StatusIm.AppImage'
- appFile = "StatusIm-${GIT_COMMIT.take(6)}.AppImage"
- sh "mv ../StatusIm-x86_64.AppImage ${appFile}"
+ pkg = common.pkgFilename(type, 'AppImage')
+ sh "mv ../StatusIm-x86_64.AppImage ${pkg}"
}
- return "${packageFolder}/${appFile}".drop(2)
+ return "${packageFolder}/${pkg}".drop(2)
}
def compileMacOS() {
@@ -169,8 +169,8 @@ def compileMacOS() {
}
}
-def bundleMacOS() {
- def dmgFile
+def bundleMacOS(type = 'nightly') {
+ def pkg = common.pkgFilename(type, 'dmg')
dir(packageFolder) {
sh 'git clone https://github.com/vkjr/StatusAppFiles.git'
sh 'unzip StatusAppFiles/StatusIm.app.zip'
@@ -182,10 +182,9 @@ def bundleMacOS() {
-qmldir='${workspace}/node_modules/react-native/ReactQt/runtime/src/qml/'
"""
sh 'rm -fr StatusAppFiles'
- dmgFile = "StatusIm-${GIT_COMMIT.take(6)}.dmg"
- sh "mv StatusIm.dmg ${dmgFile}"
+ sh "mv StatusIm.dmg ${pkg}"
}
- return "${packageFolder}/${dmgFile}".drop(2)
+ return "${packageFolder}/${pkg}".drop(2)
}
return this
diff --git a/ci/ios.groovy b/ci/ios.groovy
index 2a4254bf29..e24d937a59 100644
--- a/ci/ios.groovy
+++ b/ci/ios.groovy
@@ -1,5 +1,16 @@
+common = load('ci/common.groovy')
+
+def plutil(name, value) {
+ sh "plutil -replace ${name} -string ${value} ios/StatusIm/Info.plist"
+}
+
def compile(type = 'nightly') {
def target = (type == 'release' ? 'adhoc' : 'nightly')
+ /* configure build metadata */
+ plutil('CFBundleShortVersionString', common.version())
+ plutil('CFBundleVersion', common.tagBuild())
+ plutil('CFBundleBuildUrl', currentBuild.absoluteUrl)
+ /* build the actual app */
withCredentials([
string(credentialsId: 'SLACK_URL', variable: 'SLACK_URL'),
string(credentialsId: "slave-pass-${env.NODE_NAME}", variable: 'KEYCHAIN_PASSWORD'),
@@ -7,11 +18,9 @@ def compile(type = 'nightly') {
string(credentialsId: 'APPLE_ID', variable: 'APPLE_ID'),
string(credentialsId: 'fastlane-match-password', variable:'MATCH_PASSWORD')
]) {
- sh "plutil -replace CFBundleShortVersionString -string ${common.version()} ios/StatusIm/Info.plist"
- sh "plutil -replace CFBundleVersion -string ${common.tagBuild()} ios/StatusIm/Info.plist"
sh "fastlane ios ${target}"
}
- def pkg = "StatusIm-${GIT_COMMIT.take(6)}.ipa"
+ def pkg = common.pkgFilename(type, 'ipa')
sh "cp status-adhoc/StatusIm.ipa ${pkg}"
return pkg
}
diff --git a/ci/mobile.groovy b/ci/mobile.groovy
index 8be516bec5..37cb386f84 100644
--- a/ci/mobile.groovy
+++ b/ci/mobile.groovy
@@ -2,7 +2,7 @@ common = load 'ci/common.groovy'
ios = load 'ci/ios.groovy'
android = load 'ci/android.groovy'
-def prep(type = 'debug') {
+def prep(type = 'nightly') {
/* select type of build */
switch (type) {
case 'nightly':
diff --git a/ios/StatusIm/Info.plist b/ios/StatusIm/Info.plist
index 6ab44cfbb4..6c42a4d77c 100644
--- a/ios/StatusIm/Info.plist
+++ b/ios/StatusIm/Info.plist
@@ -31,6 +31,8 @@
1.0
CFBundleSignature
????
+ CFBundleBuildUrl
+ ????
CFBundleVersion
1
LSApplicationQueriesSchemes
diff --git a/scripts/build_no.sh b/scripts/build_no.sh
index f5e7cbcb8a..4ee0f83453 100755
--- a/scripts/build_no.sh
+++ b/scripts/build_no.sh
@@ -20,37 +20,61 @@ set -e
# * https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
#
-getNumber () {
- echo "$BUILD" | sed 's/[^0-9]*//g'
-}
-
REGEX='^build-[0-9]\+$'
-# make sure we have all the tags
-git fetch --tags --quiet >/dev/null || >&2 echo "Could not fetch tags from remote"
+getNumber () {
+ echo "$1" | sed 's/[^0-9]*//g'
+}
-# even if the current commit has a tag already, it is normal that the same commit
-# is built multiple times (with different build configurations, for instance),
-# so we increment the build number every time.
-
-# find the last used build number
-BUILD=$(git tag -l --sort=-v:refname | grep -e "$REGEX" | head -n 1)
-# extract the number
-BUILD_NO=$(getNumber "$BUILD")
-
-if [ "$1" = "--increment" ]; then
- # These need to be provided by Jenkins
- if [ -z "${GIT_USER}" ] || [ -z "${GIT_PASS}" ]; then
- echo "Git credentials not specified! (GIT_USER, GIT_PASS)" >&2
- exit 1
+findNumber () (
+ # check if current commit has a build tag
+ # since we are building in separate jobs we have to check for a tag
+ BUILD_TAG=$(git tag --points-at HEAD | grep -e "$REGEX" | tail -n1)
+
+ # use already existing build number if applicable
+ if [ -n "$BUILD_TAG" ]; then
+ echo "Current commit already tagged: $BUILD_TAG" >&2
+ getNumber $BUILD_TAG
fi
+)
+
+tagBuild () {
+ echo "Tagging HEAD: build-$1" >&2
+ git tag "build-$1" HEAD
+ if [ -n "$GIT_USER" ] && [ -n "$GIT_PASS" ]; then
+ git push --tags \
+ https://${GIT_USER}:${GIT_PASS}@github.com/status-im/status-react
+ else
+ git push --tags git@github.com:status-im/status-react
+ fi
+}
+
+increment () {
+ # find the last used build number
+ BUILD=$(git tag -l --sort=-v:refname | grep -e "$REGEX" | head -n 1)
+ # extract the number
+ BUILD_NO=$(getNumber "$BUILD")
+
# increment
BUILD_NO="$((BUILD_NO+1))"
+ # finally print build number
+ echo "$BUILD_NO"
+}
- echo "Tagging HEAD: build-$BUILD_NO" >&2
- git tag "build-$BUILD_NO" HEAD
- git push --tags https://${GIT_USER}:${GIT_PASS}@github.com/status-im/status-react
+#####################################################################
+
+# make sure we have all the tags
+git fetch --tags --quiet >/dev/null || \
+ >&2 echo "Could not fetch tags from remote"
+
+# check if this commit already has a build number
+NUMBER=$(findNumber)
+
+# if it doesn't, or we are forcing via cli option, increment
+if [ -z "$NUMBER" ] || [ "$1" = "--increment" ]; then
+ NUMBER=$(increment)
+ tagBuild $NUMBER
fi
-# finally print build number
-echo "$BUILD_NO"
+# print build number
+echo $NUMBER