diff --git a/ci/Jenkinsfile.android b/ci/Jenkinsfile.android
index bc4b4e2859..39ff57ba57 100644
--- a/ci/Jenkinsfile.android
+++ b/ci/Jenkinsfile.android
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'linux' }
@@ -40,14 +42,11 @@ pipeline {
stage('Prep') {
steps {
script {
- /* Necessary to load methods */
- android = load 'ci/android.groovy'
- cmn = load 'ci/common.groovy'
- btype = cmn.utils.getBuildType()
+ btype = utils.getBuildType()
print "Running ${btype} build!"
- cmn.ci.abortPreviousRunningBuilds()
+ jenkins.abortPreviousRunningBuilds()
/* Cleanup and Prep */
- cmn.prep(btype)
+ commonPrep(btype)
}
}
}
@@ -56,7 +55,7 @@ pipeline {
/* Build implicit dependencies if needed (we run `lein deps :tree` but it's not really required, for this purpose)
Implicit dependencies include building a patched node_modules, fetching maven dependencies, and anything else required.
We do this before the parallel steps so we have a known starting situation. */
- script { cmn.nix.shell('lein deps :tree', attr: 'shells.lein') }
+ script { nix.shell('lein deps :tree', attr: 'shells.lein') }
}
}
stage('Parallel Assemble') {
@@ -64,12 +63,12 @@ pipeline {
stage('Checks') { stages {
stage('Lint') {
steps {
- script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
+ script { nix.shell('lein cljfmt check', attr: 'shells.lein') }
}
}
stage('Tests') {
steps {
- script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
+ script { nix.shell('lein test-cljs', attr: 'shells.lein') }
}
}
} }
@@ -77,7 +76,7 @@ pipeline {
stage('JSBundle') {
steps {
script {
- cmn.nix.shell('make jsbundle-android', pure: false)
+ nix.shell('make jsbundle-android', pure: false)
}
}
}
@@ -99,7 +98,7 @@ pipeline {
stage('Upload') {
steps {
script {
- def urls = apks.collect { cmn.uploadArtifact(it) }
+ def urls = apks.collect { s3.uploadArtifact(it) }
/* return only the universal APK */
if (urls.size() > 1) {
env.PKG_URL = urls.find { it.contains('universal') }
@@ -125,8 +124,8 @@ pipeline {
}
}
post {
- success { script { load('ci/github.groovy').notifyPR(true) } }
- failure { script { load('ci/github.groovy').notifyPR(false) } }
+ success { script { github.notifyPR(true) } }
+ failure { script { github.notifyPR(false) } }
always { sh 'make _fix-node-perms' }
}
}
diff --git a/ci/Jenkinsfile.combined b/ci/Jenkinsfile.combined
index 0deb1e87e2..c6bb49b0a7 100644
--- a/ci/Jenkinsfile.combined
+++ b/ci/Jenkinsfile.combined
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'linux' }
@@ -18,36 +20,33 @@ pipeline {
stage('Prep') {
steps { script {
println "Current JOB: ${env.JOB_NAME}"
- /* load common lib */
- cmn = load('ci/common.groovy')
- gh = load('ci/github.groovy')
/* just for a shorter access */
- btype = cmn.utils.getBuildType()
+ btype = utils.getBuildType()
} }
}
stage('Build') {
parallel {
stage('iOS') { steps { script {
- ios = cmn.ci.Build('status-react/combined/mobile-ios')
+ ios = jenkins.Build('status-react/combined/mobile-ios')
} } }
stage('Android') { steps { script {
- apk = cmn.ci.Build('status-react/combined/mobile-android')
+ apk = jenkins.Build('status-react/combined/mobile-android')
} } }
stage('Android e2e') { steps { script {
- apke2e = cmn.ci.Build('status-react/combined/mobile-android-e2e')
+ apke2e = jenkins.Build('status-react/combined/mobile-android-e2e')
} } }
}
}
stage('Archive') {
steps { script {
sh('rm -f pkg/*')
- cmn.ci.copyArts(ios)
- //cmn.ci.copyArts(iose2e)
- cmn.ci.copyArts(apk)
- cmn.ci.copyArts(apke2e)
+ jenkins.copyArts(ios)
+ //jenkins.copyArts(iose2e)
+ jenkins.copyArts(apk)
+ jenkins.copyArts(apke2e)
dir('pkg') {
/* generate sha256 checksums for upload */
- sh "sha256sum * | tee ${cmn.utils.pkgFilename(btype, 'sha256')}"
+ sh "sha256sum * | tee ${utils.pkgFilename(btype, 'sha256')}"
archiveArtifacts('*')
}
} }
@@ -57,18 +56,18 @@ pipeline {
/* object for easier URLs handling */
urls = [
/* mobile */
- Apk: cmn.pkgUrl(apk), Apke2e: cmn.pkgUrl(apke2e),
- iOS: cmn.pkgUrl(ios), /*iOSe2e: cmn.pkgUrl(iose2e),*/
- Diawi: cmn.utils.getEnv(ios, 'DIAWI_URL'),
+ Apk: utils.pkgUrl(apk), Apke2e: utils.pkgUrl(apke2e),
+ iOS: utils.pkgUrl(ios), /*iOSe2e: utils.pkgUrl(iose2e),*/
+ Diawi: utils.utils.getEnv(ios, 'DIAWI_URL'),
/* upload the sha256 checksums file too */
- SHA: cmn.uploadArtifact(cmn.utils.pkgFind('sha256')),
+ SHA: s3.uploadArtifact(utils.pkgFind('sha256')),
]
/* add URLs to the build description */
- cmn.ci.setBuildDesc(urls)
+ jenkins.setBuildDesc(urls)
/* Create JSON file with newest build URLs */
switch (btype) {
/* legacy naming, should have named it nightly.json */
- case 'nightly': cmn.updateBucketJSON(urls, 'latest.json'); break
+ case 'nightly': s3.updateBucketJSON(urls, 'latest.json'); break
}
} }
}
@@ -83,10 +82,11 @@ pipeline {
stage('Run e2e') {
when { expression { btype == 'nightly' } }
steps { script {
- e2eApk = cmn.utils.getEnv(apke2e, 'SAUCE_URL')
+ e2eApk = utils.getEnv(apke2e, 'SAUCE_URL')
build(
- job: 'end-to-end-tests/status-app-nightly', wait: false,
- parameters: [string(name: 'APK_NAME', value: e2eApk)]
+ job: 'end-to-end-tests/status-app-nightly',
+ parameters: [string(name: 'APK_NAME', value: e2eApk)],
+ wait: false
)
} }
}
diff --git a/ci/Jenkinsfile.fastlane.clean b/ci/Jenkinsfile.fastlane.clean
index a8cf277f68..6435dec75e 100644
--- a/ci/Jenkinsfile.fastlane.clean
+++ b/ci/Jenkinsfile.fastlane.clean
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'macos' }
@@ -26,7 +28,6 @@ pipeline {
stages {
stage('Prep') {
steps { script {
- nix = load('ci/nix.groovy')
nix.shell(
'bundle install --gemfile=fastlane/Gemfile',
attr: 'shells.fastlane',
diff --git a/ci/Jenkinsfile.ios b/ci/Jenkinsfile.ios
index 4eb99098fe..3c8211138c 100644
--- a/ci/Jenkinsfile.ios
+++ b/ci/Jenkinsfile.ios
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'macos-xcode-11.3.1' }
@@ -39,14 +41,11 @@ pipeline {
stage('Prep') {
steps {
script {
- /* Necessary to load methods */
- ios = load 'ci/ios.groovy'
- cmn = load 'ci/common.groovy'
- btype = cmn.utils.getBuildType()
+ btype = utils.getBuildType()
print "Running ${btype} build!"
- cmn.ci.abortPreviousRunningBuilds()
+ jenkins.abortPreviousRunningBuilds()
/* Cleanup and Prep */
- cmn.prep(btype)
+ commonPrep(btype)
}
}
}
@@ -55,19 +54,19 @@ pipeline {
stage('Checks') { stages {
stage('Lint') {
steps {
- script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
+ script { nix.shell('lein cljfmt check', attr: 'shells.lein') }
}
}
stage('Tests') {
steps {
- script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
+ script { nix.shell('lein test-cljs', attr: 'shells.lein') }
}
}
} }
stage('Build') { stages {
stage('JSBundle') {
steps {
- script { cmn.nix.shell('make jsbundle-ios') }
+ script { nix.shell('make jsbundle-ios') }
}
}
stage('Bundle') {
@@ -88,7 +87,7 @@ pipeline {
stage('Upload') {
steps {
script {
- env.PKG_URL = cmn.uploadArtifact(api)
+ env.PKG_URL = s3.uploadArtifact(api)
/* e2e builds get tested in SauceLabs */
if (btype == 'e2e') {
env.SAUCE_URL = ios.uploadToSauceLabs()
@@ -108,8 +107,8 @@ pipeline {
}
}
post {
- success { script { load('ci/github.groovy').notifyPR(true) } }
- failure { script { load('ci/github.groovy').notifyPR(false) } }
+ success { script { github.notifyPR(true) } }
+ failure { script { github.notifyPR(false) } }
always { sh 'make _fix-node-perms' }
}
}
diff --git a/ci/Jenkinsfile.linux b/ci/Jenkinsfile.linux
index 4854a7853b..39e41c39bf 100644
--- a/ci/Jenkinsfile.linux
+++ b/ci/Jenkinsfile.linux
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'linux' }
@@ -42,14 +44,11 @@ pipeline {
stage('Prep') {
steps {
script {
- /* Necessary to load methods */
- desktop = load 'ci/desktop.groovy'
- cmn = load 'ci/common.groovy'
- btype = cmn.utils.getBuildType()
+ btype = utils.getBuildType()
print "Running ${btype} build!"
- cmn.ci.abortPreviousRunningBuilds()
+ jenkins.abortPreviousRunningBuilds()
/* Cleanup and Prep */
- cmn.prep(btype)
+ commonPrep(btype)
}
}
}
@@ -58,12 +57,12 @@ pipeline {
stage('Checks') { stages {
stage('Lint') {
steps {
- script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
+ script { nix.shell('lein cljfmt check', attr: 'shells.lein') }
}
}
stage('Tests') {
steps {
- script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
+ script { nix.shell('lein test-cljs', attr: 'shells.lein') }
}
}
} }
@@ -95,7 +94,7 @@ pipeline {
}
stage('Upload') {
steps {
- script { env.PKG_URL = cmn.uploadArtifact(app) }
+ script { env.PKG_URL = s3.uploadArtifact(app) }
}
}
}
@@ -108,7 +107,7 @@ pipeline {
}
}
post {
- success { script { load('ci/github.groovy').notifyPR(true) } }
- failure { script { load('ci/github.groovy').notifyPR(false) } }
+ success { script { github.notifyPR(true) } }
+ failure { script { github.notifyPR(false) } }
}
}
diff --git a/ci/Jenkinsfile.macos b/ci/Jenkinsfile.macos
index c52921bafd..f0461d9d9b 100644
--- a/ci/Jenkinsfile.macos
+++ b/ci/Jenkinsfile.macos
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'macos-xcode-11.3.1' }
@@ -40,14 +42,11 @@ pipeline {
stage('Prep') {
steps {
script {
- /* Necessary to load methods */
- desktop = load 'ci/desktop.groovy'
- cmn = load 'ci/common.groovy'
- btype = cmn.utils.getBuildType()
+ btype = utils.getBuildType()
print "Running ${btype} build!"
- cmn.ci.abortPreviousRunningBuilds()
+ jenkins.abortPreviousRunningBuilds()
/* Cleanup and Prep */
- cmn.prep(btype)
+ commonPrep(btype)
}
}
}
@@ -56,12 +55,12 @@ pipeline {
stage('Checks') { stages {
stage('Lint') {
steps {
- script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
+ script { nix.shell('lein cljfmt check', attr: 'shells.lein') }
}
}
stage('Tests') {
steps {
- script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
+ script { nix.shell('lein test-cljs', attr: 'shells.lein') }
}
}
} }
@@ -93,7 +92,7 @@ pipeline {
}
stage('Upload') {
steps {
- script { env.PKG_URL = cmn.uploadArtifact(dmg) }
+ script { env.PKG_URL = s3.uploadArtifact(dmg) }
}
}
}
@@ -106,7 +105,7 @@ pipeline {
}
}
post {
- success { script { load('ci/github.groovy').notifyPR(true) } }
- failure { script { load('ci/github.groovy').notifyPR(false) } }
+ success { script { github.notifyPR(true) } }
+ failure { script { github.notifyPR(false) } }
}
}
diff --git a/ci/Jenkinsfile.nix-cache b/ci/Jenkinsfile.nix-cache
index c92af3c4b1..4e496a792f 100644
--- a/ci/Jenkinsfile.nix-cache
+++ b/ci/Jenkinsfile.nix-cache
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label params.AGENT_LABEL }
@@ -25,11 +27,6 @@ pipeline {
}
stages {
- stage('Prep') {
- steps { script {
- nix = load('ci/nix.groovy')
- } }
- }
stage('Setup') {
steps { script {
nix.shell('nix-env -i openssh', pure: false)
diff --git a/ci/Jenkinsfile.windows b/ci/Jenkinsfile.windows
index 3db1a5403b..cdc84b94b2 100644
--- a/ci/Jenkinsfile.windows
+++ b/ci/Jenkinsfile.windows
@@ -1,3 +1,5 @@
+library 'status-react-jenkins@master'
+
pipeline {
agent { label 'linux' }
@@ -45,14 +47,11 @@ pipeline {
stage('Prep') {
steps {
script {
- /* Necessary to load methods */
- desktop = load 'ci/desktop.groovy'
- cmn = load 'ci/common.groovy'
- btype = cmn.utils.getBuildType()
+ btype = utils.getBuildType()
print "Running ${btype} build!"
- cmn.ci.abortPreviousRunningBuilds()
+ jenkins.abortPreviousRunningBuilds()
/* Cleanup and Prep */
- cmn.prep(btype)
+ commonPrep(btype)
}
}
}
@@ -61,12 +60,12 @@ pipeline {
stage('Checks') { stages {
stage('Lint') {
steps {
- script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
+ script { nix.shell('lein cljfmt check', attr: 'shells.lein') }
}
}
stage('Tests') {
steps {
- script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
+ script { nix.shell('lein test-cljs', attr: 'shells.lein') }
}
}
} }
@@ -98,7 +97,7 @@ pipeline {
}
stage('Upload') {
steps {
- script { env.PKG_URL = cmn.uploadArtifact(app) }
+ script { env.PKG_URL = s3.uploadArtifact(app) }
}
}
}
@@ -111,7 +110,7 @@ pipeline {
}
}
post {
- success { script { load('ci/github.groovy').notifyPR(true) } }
- failure { script { load('ci/github.groovy').notifyPR(false) } }
+ success { script { github.notifyPR(true) } }
+ failure { script { github.notifyPR(false) } }
}
}
diff --git a/ci/README.md b/ci/README.md
new file mode 100644
index 0000000000..5b4b63812a
--- /dev/null
+++ b/ci/README.md
@@ -0,0 +1,16 @@
+# Description
+
+This folder contains files defininf [Jenkins pipelines](https://jenkins.io/doc/book/pipeline/) that run on https://ci.status.im/.
+
+# Libraries
+
+All `Jenkinsfile`s contain the following line:
+```groovy
+library 'status-react-jenkins@master'
+```
+
+Which loads the used methods - like `nix.shell()` - from a separate private repo:
+
+https://github.com/status-im/status-react-jenkins
+
+This is done to improve security of our CI setup.
diff --git a/ci/android.groovy b/ci/android.groovy
deleted file mode 100644
index b13640e8b2..0000000000
--- a/ci/android.groovy
+++ /dev/null
@@ -1,178 +0,0 @@
-nix = load 'ci/nix.groovy'
-utils = load 'ci/utils.groovy'
-
-def bundle() {
- /* we use the method because parameter build type does not take e2e into account */
- def btype = utils.getBuildType()
- /* Disable Gradle Daemon https://stackoverflow.com/questions/38710327/jenkins-builds-fail-using-the-gradle-daemon */
- def gradleOpt = "-PbuildUrl='${currentBuild.absoluteUrl}' --console plain "
- /* Can't take more digits than unsigned int */
- def buildNumber = utils.readBuildNumber().substring(0, 10)
- /* we don't need x86 for any builds except e2e */
- env.ANDROID_ABI_INCLUDE="armeabi-v7a;arm64-v8a"
- env.ANDROID_ABI_SPLIT="false"
-
- /* some builds tyes require different architectures */
- switch (btype) {
- case 'e2e':
- env.ANDROID_ABI_INCLUDE="x86" /* e2e builds are used with simulators */
- break
- case 'release':
- env.ANDROID_ABI_SPLIT="true"
- gradleOpt += "-PreleaseVersion='${utils.getVersion()}'"
- break
- }
-
- /* credentials necessary to open the keystore and sign the APK */
- withCredentials([
- file(
- credentialsId: 'status-im.keystore',
- variable: 'KEYSTORE_PATH'
- ),
- string(
- credentialsId: 'android-keystore-pass',
- variable: 'KEYSTORE_PASSWORD'
- ),
- usernamePassword(
- credentialsId: 'android-keystore-key-pass',
- usernameVariable: 'KEYSTORE_ALIAS',
- passwordVariable: 'KEYSTORE_KEY_PASSWORD'
- )
- ]) {
- /* Nix target which produces the final APKs */
- nix.build(
- attr: 'targets.mobile.android.release',
- conf: [
- 'status-im.ci': '1',
- 'status-im.build-type': btype,
- 'status-im.status-react.gradle-opts': gradleOpt,
- 'status-im.status-react.build-number': buildNumber,
- ],
- safeEnv: [
- 'KEYSTORE_ALIAS',
- 'KEYSTORE_PASSWORD',
- 'KEYSTORE_KEY_PASSWORD',
- ],
- keepEnv: [
- 'ANDROID_ABI_SPLIT',
- 'ANDROID_ABI_INCLUDE',
- 'KEYSTORE_PATH',
- ],
- sandboxPaths: [
- env.KEYSTORE_PATH,
- ],
- link: false
- )
- }
- /* necessary for Fastlane */
- def apks = renameAPKs()
- /* for use with Fastlane */
- env.APK_PATHS = apks.join(";")
- return apks
-}
-
-def extractArchFromAPK(name) {
- def pattern = /app-(.+)-[^-]+.apk/
- /* extract architecture from filename */
- def matches = (name =~ pattern)
- if (matches.size() > 0) {
- return matches[0][1]
- }
- if (utils.isE2EBuild()) {
- return 'x86'
- }
- /* non-release builds make universal APKs */
- return 'universal'
-}
-
-/**
- * We need more informative filenames for all builds.
- * For more details on the format see utils.pkgFilename().
- **/
-def renameAPKs() {
- /* find all APK files */
- def apkGlob = 'result/*.apk'
- def found = findFiles(glob: apkGlob)
- if (found.size() == 0) {
- throw "APKs not found via glob: ${apkGlob}"
- }
- def renamed = []
- /* rename each for upload & archiving */
- for (apk in found) {
- def arch = extractArchFromAPK(apk)
- def pkg = utils.pkgFilename(env.BUILD_TYPE, 'apk', arch)
- def newApk = "result/${pkg}"
- renamed += newApk
- sh "cp ${apk.path} ${newApk}"
- }
- return renamed
-}
-
-def uploadToPlayStore(type = 'nightly') {
- withCredentials([
- string(credentialsId: "SUPPLY_JSON_KEY_DATA", variable: 'GOOGLE_PLAY_JSON_KEY'),
- ]) {
- nix.shell(
- "fastlane android ${type}",
- keepEnv: ['FASTLANE_DISABLE_COLORS', 'APK_PATHS', 'GOOGLE_PLAY_JSON_KEY'],
- attr: 'shells.fastlane',
- pure: false
- )
- }
-}
-
-def uploadToSauceLabs() {
- def changeId = utils.changeId()
- if (changeId != null) {
- env.SAUCE_LABS_NAME = "${changeId}.apk"
- } else {
- def pkg = utils.pkgFilename(env.BUILD_TYPE, 'apk', 'x86')
- env.SAUCE_LABS_NAME = "${pkg}"
- }
- withCredentials([
- usernamePassword(
- credentialsId: 'sauce-labs-api',
- usernameVariable: 'SAUCE_USERNAME',
- passwordVariable: 'SAUCE_ACCESS_KEY'
- ),
- ]) {
- nix.shell(
- 'fastlane android saucelabs',
- keepEnv: [
- 'FASTLANE_DISABLE_COLORS', 'APK_PATHS',
- 'SAUCE_ACCESS_KEY', 'SAUCE_USERNAME', 'SAUCE_LABS_NAME'
- ],
- attr: 'shells.fastlane',
- pure: false
- )
- }
- return env.SAUCE_LABS_NAME
-}
-
-def uploadToDiawi() {
- withCredentials([
- string(credentialsId: 'diawi-token', variable: 'DIAWI_TOKEN'),
- ]) {
- nix.shell(
- 'fastlane android upload_diawi',
- keepEnv: ['FASTLANE_DISABLE_COLORS', 'APK_PATHS', 'DIAWI_TOKEN'],
- attr: 'shells.fastlane',
- pure: false
- )
- }
- diawiUrl = readFile "${env.WORKSPACE}/fastlane/diawi.out"
- return diawiUrl
-}
-
-def coverage() {
- withCredentials([
- string(credentialsId: 'coveralls-status-react-token', variable: 'COVERALLS_REPO_TOKEN'),
- ]) {
- nix.shell(
- 'make coverage',
- keepEnv: ['COVERALLS_REPO_TOKEN', 'COVERALLS_SERVICE_NAME', 'COVERALLS_SERVICE_JOB_ID']
- )
- }
-}
-
-return this
diff --git a/ci/common.groovy b/ci/common.groovy
deleted file mode 100644
index b89009cd6c..0000000000
--- a/ci/common.groovy
+++ /dev/null
@@ -1,106 +0,0 @@
-import groovy.json.JsonBuilder
-
-/* Libraries -----------------------------------------------------------------*/
-
-ci = load 'ci/jenkins.groovy'
-nix = load 'ci/nix.groovy'
-utils = load 'ci/utils.groovy'
-
-/* Small Helpers -------------------------------------------------------------*/
-
-def pkgUrl(build) {
- return utils.getEnv(build, 'PKG_URL')
-}
-
-def updateBucketJSON(urls, fileName) {
- /* latest.json has slightly different key names */
- def content = [
- DIAWI: urls.Diawi,
- APK: urls.Apk, IOS: urls.iOS,
- APP: urls.App, MAC: urls.Mac,
- WIN: urls.Win, SHA: urls.SHA
- ]
- def filePath = "${pwd()}/pkg/${fileName}"
- /* it might not exist */
- sh "mkdir -p ${pwd()}/pkg"
- def contentJson = new JsonBuilder(content).toPrettyString()
- println "${filePath}:\n${contentJson}"
- writeFile(file: filePath, text: contentJson)
- return uploadArtifact(filePath)
-}
-
-def prep(type = 'nightly') {
- /* build/downloads all nix deps in advance */
- nix.prepEnv()
- /* rebase unless this is a release build */
- utils.doGitRebase()
- /* ensure that we start from a known state */
- sh 'make clean'
- /* Disable git hooks in CI, it's not useful, takes time and creates weird errors at times
- (e.g. bin/sh: 2: /etc/ssl/certs/ca-certificates.crt: Permission denied) */
- sh 'make disable-githooks'
-
- /* pick right .env and update from params */
- utils.updateEnv(type)
-
- if (['android', 'ios'].contains(env.TARGET)) {
- /* Run at start to void mismatched numbers */
- utils.genBuildNumber()
- }
-
- nix.shell('watchman watch-del-all', attr: 'shells.watchman')
-
- if (env.TARGET == 'ios') {
- /* install ruby dependencies */
- nix.shell(
- 'bundle install --gemfile=fastlane/Gemfile --quiet',
- attr: 'shells.fastlane',
- sandbox: false
- )
- }
-
- if (['macos', 'linux', 'windows'].contains(env.TARGET)) {
- /* node deps, pods, and status-go download */
- nix.shell('scripts/prepare-for-desktop-platform.sh', pure: false)
- }
- /* run script in the nix shell so that node_modules gets instantiated before attempting the copies */
- nix.shell(
- 'scripts/copy-translations.sh chmod',
- attr: "shells.${env.TARGET}",
- sandbox: false
- )
-}
-
-def uploadArtifact(path) {
- /* defaults for upload */
- def domain = 'ams3.digitaloceanspaces.com'
- def bucket = 'status-im'
- /* There's so many PR builds we need a separate bucket */
- if (utils.isPRBuild()) {
- bucket = 'status-im-prs'
- }
- /* WARNING: s3cmd can't guess APK MIME content-type */
- def customOpts = ''
- if (path.endsWith('apk')) {
- customOpts += "--mime-type='application/vnd.android.package-archive'"
- }
- /* We also need credentials for the upload */
- withCredentials([usernamePassword(
- credentialsId: 'digital-ocean-access-keys',
- usernameVariable: 'DO_ACCESS_KEY',
- passwordVariable: 'DO_SECRET_KEY'
- )]) {
- sh("""
- s3cmd ${customOpts} \\
- --acl-public \\
- --host="${domain}" \\
- --host-bucket="%(bucket)s.${domain}" \\
- --access_key=${DO_ACCESS_KEY} \\
- --secret_key=${DO_SECRET_KEY} \\
- put ${path} s3://${bucket}/
- """)
- }
- return "https://${bucket}.${domain}/${utils.getFilename(path)}"
-}
-
-return this
diff --git a/ci/desktop.groovy b/ci/desktop.groovy
deleted file mode 100644
index 70b96a6c20..0000000000
--- a/ci/desktop.groovy
+++ /dev/null
@@ -1,109 +0,0 @@
-nix = load 'ci/nix.groovy'
-utils = load 'ci/utils.groovy'
-
-packageFolder = './StatusImPackage'
-
-def buildJSBundle() {
- nix.shell(
- '''
- make jsbundle-desktop && \
- ./scripts/build-desktop.sh buildJSBundle
- ''',
- keepEnv: ['VERBOSE_LEVEL']
- )
-}
-
-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
-}
-
-/* MAIN --------------------------------------------------*/
-
-def compile() {
- /* disable logs for desktop builds when releasing */
- if (params.BUILD_TYPE == 'release') {
- env.STATUS_NO_LOGGING = 1
- }
- /* since QT is in a custom path we need to add it to PATH */
- if (env.QT_PATH) {
- env.PATH = "${env.QT_PATH}:${env.PATH}"
- }
- nix.shell(
- './scripts/build-desktop.sh compile',
- keepEnv: ['VERBOSE_LEVEL']
- )
-}
-
-def bundleWindows(type = 'nightly') {
- def pkg
-
- nix.shell(
- './scripts/build-desktop.sh bundle',
- keepEnv: ['VERBOSE_LEVEL']
- )
- dir(packageFolder) {
- pkg = utils.pkgFilename(type, 'exe')
- sh "mv ../Status-x86_64-setup.exe ${pkg}"
- }
- return "${packageFolder}/${pkg}".drop(2)
-}
-
-def bundleLinux(type = 'nightly') {
- def pkg
- nix.shell(
- './scripts/build-desktop.sh bundle',
- keepEnv: ['VERBOSE_LEVEL']
- )
- dir(packageFolder) {
- pkg = utils.pkgFilename(type, 'AppImage')
- sh "mv ../Status-x86_64.AppImage ${pkg}"
- }
- return "${packageFolder}/${pkg}".drop(2)
-}
-
-def bundleMacOS(type = 'nightly') {
- def pkg = utils.pkgFilename(type, 'dmg')
- nix.shell(
- './scripts/build-desktop.sh bundle',
- keepEnv: ['VERBOSE_LEVEL']
- )
- dir(packageFolder) {
- withCredentials([
- string(credentialsId: 'desktop-gpg-outer-pass', variable: 'GPG_PASS_OUTER'),
- string(credentialsId: 'desktop-gpg-inner-pass', variable: 'GPG_PASS_INNER'),
- string(credentialsId: 'desktop-keychain-pass', variable: 'KEYCHAIN_PASS')
- ]) {
- nix.shell(
- """
- ../scripts/sign-macos-pkg.sh Status.app ../deployment/macos/macos-developer-id.keychain-db.gpg && \
- ../node_modules/appdmg/bin/appdmg.js ../deployment/macos/status-dmg.json ${pkg} && \
- ../scripts/sign-macos-pkg.sh ${pkg} ../deployment/macos/macos-developer-id.keychain-db.gpg
- """,
- pure: false,
- keepEnv: ['GPG_PASS_OUTER', 'GPG_PASS_INNER', 'KEYCHAIN_PASS']
- )
- }
- }
- return "${packageFolder}/${pkg}".drop(2)
-}
-
-return this
diff --git a/ci/ghcmgr.groovy b/ci/ghcmgr.groovy
deleted file mode 100644
index 96f4e5c7a1..0000000000
--- a/ci/ghcmgr.groovy
+++ /dev/null
@@ -1,62 +0,0 @@
-import groovy.json.JsonBuilder
-
-utils = load 'ci/utils.groovy'
-
-/**
- * Methods for interacting with ghcmgr API.
- * For more details see:
- * https://github.com/status-im/github-comment-manager
- **/
-
-def buildObj(success) {
- def pkg_url = env.PKG_URL
- /* a bare ipa file is not installable on iOS */
- if (env.TARGET == 'ios' && env.DIAWI_URL != "") {
- pkg_url = env.DIAWI_URL
- }
- /* assemble build object valid for ghcmgr */
- return [
- id: env.BUILD_DISPLAY_NAME,
- commit: GIT_COMMIT.take(8),
- success: success != null ? success : true,
- platform: env.TARGET + (utils.isE2EBuild() ? '-e2e' : ''),
- duration: utils.buildDuration(),
- url: currentBuild.absoluteUrl,
- pkg_url: pkg_url,
- ]
-}
-
-def postBuild(success) {
- /**
- * This is our own service for avoiding comment spam.
- * https://github.com/status-im/github-comment-manager
- **/
- def ghcmgrurl = 'https://ghcmgr.status.im'
- def body = buildObj(success)
- def json = new JsonBuilder(body).toPrettyString()
- def stdout = null
- withCredentials([usernamePassword(
- credentialsId: 'ghcmgr-auth',
- usernameVariable: 'GHCMGR_USER',
- passwordVariable: 'GHCMGR_PASS'
- )]) {
- stdout = sh(
- returnStdout: true,
- script: """
- curl --silent \
- -XPOST --data '${json}' \
- -u '${GHCMGR_USER}:${GHCMGR_PASS}' \
- -w '\nHTTP_CODE:%{http_code}' \
- -H "content-type: application/json" \
- '${ghcmgrurl}/builds/status-react/${utils.changeId()}'
- """
- )
- }
- /* We're not using --fail because it suppresses server response */
- if (!stdout.contains('HTTP_CODE:201')) {
- println("STDOUT:\n${stdout}")
- error("Notifying GHCMGR failed")
- }
-}
-
-return this
diff --git a/ci/github.groovy b/ci/github.groovy
deleted file mode 100644
index fdee24c460..0000000000
--- a/ci/github.groovy
+++ /dev/null
@@ -1,205 +0,0 @@
-import groovy.json.JsonBuilder
-
-/* I'm using utils from ghcmgr to avoid another load */
-ghcmgr = load 'ci/ghcmgr.groovy'
-
-/**
- * Methods for interacting with GitHub API and related tools.
- **/
-
-/* Comments -------------------------------------------------------*/
-
-def notify(message) {
- def githubIssuesUrl = 'https://api.github.com/repos/status-im/status-react/issues'
- def changeId = ghcmgr.utils.changeId()
- if (changeId == null) { return }
- def msgObj = [body: message]
- def msgJson = new JsonBuilder(msgObj).toPrettyString()
- withCredentials([usernamePassword(
- credentialsId: 'status-im-auto',
- usernameVariable: 'GH_USER',
- passwordVariable: 'GH_PASS'
- )]) {
- sh """
- curl --silent \
- -u '${GH_USER}:${GH_PASS}' \
- --data '${msgJson}' \
- -H "Content-Type: application/json" \
- "${githubIssuesUrl}/${changeId}/comments"
- """.trim()
- }
-}
-
-def notifyFull(urls) {
- def msg = "#### :white_check_mark: "
- msg += "[${env.JOB_NAME}${currentBuild.displayName}](${currentBuild.absoluteUrl}) "
- msg += "CI BUILD SUCCESSFUL in ${ghcmgr.utils.buildDuration()} (${GIT_COMMIT.take(8)})\n"
- msg += '| | | | | |\n'
- msg += '|-|-|-|-|-|\n'
- msg += "| [Android](${urls.Apk}) ([e2e](${urls.Apke2e})) "
- msg += "| [iOS](${urls.iOS}) ([e2e](${urls.iOSe2e})) |"
- if (urls.Mac != null) {
- msg += " [MacOS](${urls.Mac}) | [AppImage](${urls.App}) | [Windows](${urls.Win}) |"
- } else {
- msg += " ~~MacOS~~ | ~~AppImage~~ | ~~Windows~~~ |"
- }
- notify(msg)
-}
-
-def notifyPRFailure() {
- def d = ":small_orange_diamond:"
- def msg = "#### :x: "
- msg += "[${env.JOB_NAME}${currentBuild.displayName}](${currentBuild.absoluteUrl}) ${d} "
- msg += "${ghcmgr.utils.buildDuration()} ${d} ${GIT_COMMIT.take(8)} ${d} "
- msg += "[:page_facing_up: build log](${currentBuild.absoluteUrl}/consoleText)"
- //msg += "Failed in stage: ${env.STAGE_NAME}\n"
- //msg += "```${currentBuild.rawBuild.getLog(5)}```"
- notify(msg)
-}
-
-def notifyPRSuccess() {
- def d = ":small_blue_diamond:"
- def msg = "#### :heavy_check_mark: "
- def type = ghcmgr.utils.isE2EBuild() ? ' e2e' : ''
- msg += "[${env.JOB_NAME}${currentBuild.displayName}](${currentBuild.absoluteUrl}) ${d} "
- msg += "${ghcmgr.utils.buildDuration()} ${d} ${GIT_COMMIT.take(8)} ${d} "
- msg += "[:package: ${env.TARGET}${type} package](${env.PKG_URL})"
- notify(msg)
-}
-
-/* Releases -------------------------------------------------------*/
-
-def getPrevRelease() {
- return sh(returnStdout: true,
- script: "git for-each-ref --format '%(refname)' --sort=committerdate refs/remotes/origin/release"
- ).trim().split('\\r?\\n').last()
-}
-
-def getDiffUrl(prev, current) {
- prev = prev.replaceAll(/.*origin\//, '')
- return "https://github.com/status-im/status-react/compare/${prev}...${current}"
-}
-
-def getReleaseChanges() {
- def prevRelease = getPrevRelease()
- def curRelease = ghcmgr.utils.branchName()
- def changes = ''
- try {
- changes = sh(returnStdout: true,
- script: """
- git log \
- --cherry-pick \
- --right-only \
- --no-merges \
- --format='%h %s' \
- ${prevRelease}..HEAD
- """
- ).trim()
- } catch (Exception ex) {
- println 'ERROR: Failed to retrieve changes.'
- println ex.message
- return ':warning: __Please fill me in!__'
- }
- /* remove single quotes to not confuse formatting */
- changes = changes.replace('\'', '')
- return changes + '\nDiff:' + getDiffUrl(prevRelease, curRelease)
-}
-
-def releaseExists(Map args) {
- def output = sh(
- returnStdout: true,
- script: """
- github-release info --json \
- -u '${args.user}' \
- -r '${args.repo}' \
- | jq '.Releases[].tag_name'
- """
- )
- return output.contains(args.version)
-}
-
-def releaseDelete(Map args) {
- if (!releaseExists(args)) {
- return
- }
- sh """
- github-release delete \
- -u '${args.user}' \
- -r '${args.repo}' \
- -t '${args.version}' \
- """
-}
-
-def releaseUpload(Map args) {
- args.files.each {
- sh """
- github-release upload \
- -u '${args.user}' \
- -r '${args.repo}' \
- -t '${args.version}' \
- -n ${it} \
- -f ${it}
- """
- }
-}
-
-def releasePublish(Map args) {
- sh """
- github-release release \
- -u '${args.user}' \
- -r '${args.repo}' \
- -n '${args.version}' \
- -t '${args.version}' \
- -c '${args.branch}' \
- -d '${args.desc}' \
- ${args.draft ? '--draft' : ''}
- """
-}
-
-def publishRelease(Map args) {
- def config = [
- draft: true,
- user: 'status-im',
- repo: 'status-react',
- files: args.files,
- version: args.version,
- branch: ghcmgr.utils.branchName(),
- desc: getReleaseChanges(),
- ]
- /* we release only for mobile right now */
- withCredentials([usernamePassword(
- credentialsId: 'status-im-auto',
- usernameVariable: 'GITHUB_USER',
- passwordVariable: 'GITHUB_TOKEN'
- )]) {
- releaseDelete(config) /* so we can re-release it */
- releasePublish(config)
- releaseUpload(config)
- }
-}
-
-def publishReleaseMobile(path='pkg') {
- def found = findFiles(glob: "${path}/*")
- if (found.size() == 0) {
- sh "ls ${path}"
- error("No file to release in ${path}")
- }
- publishRelease(
- version: ghcmgr.utils.getVersion(),
- files: found.collect { it.path },
- )
-}
-
-def notifyPR(success) {
- if (ghcmgr.utils.changeId() == null) { return }
- try {
- ghcmgr.postBuild(success)
- } catch (ex) { /* fallback to posting directly to GitHub */
- println "Failed to use GHCMGR: ${ex}"
- switch (success) {
- case true: notifyPRSuccess(); break
- }
- }
-}
-
-return this
diff --git a/ci/ios.groovy b/ci/ios.groovy
deleted file mode 100644
index 9580ed1db4..0000000000
--- a/ci/ios.groovy
+++ /dev/null
@@ -1,102 +0,0 @@
-nix = load('ci/nix.groovy')
-utils = load('ci/utils.groovy')
-
-def plutil(name, value) {
- return """
- plutil -replace ${name} -string ${value} ios/StatusIm/Info.plist;
-"""
-}
-
-def bundle() {
- def btype = utils.getBuildType()
- def target
- switch (btype) {
- case 'release': target = 'release'; break;
- case 'testflight': target = 'release'; break;
- case 'e2e': target = 'e2e'; break;
- default: target = 'nightly';
- }
- /* configure build metadata */
- nix.shell(plutil('CFBundleShortVersionString', utils.getVersion()), attr: 'shells.ios')
- nix.shell(plutil('CFBundleVersion', utils.genBuildNumber()), attr: 'shells.ios')
- nix.shell(plutil('CFBundleBuildUrl', currentBuild.absoluteUrl), attr: 'shells.ios')
- /* the dir might not exist */
- sh 'mkdir -p status-e2e'
- /* build the actual app */
- withCredentials([
- string(credentialsId: "slave-pass-${env.NODE_NAME}", variable: 'KEYCHAIN_PASSWORD'),
- string(credentialsId: 'fastlane-match-password', variable: 'MATCH_PASSWORD'),
- usernamePassword(
- credentialsId: 'fastlane-match-apple-id',
- usernameVariable: 'FASTLANE_APPLE_ID',
- passwordVariable: 'FASTLANE_PASSWORD'
- ),
- ]) {
- nix.shell(
- "bundle exec --gemfile=fastlane/Gemfile fastlane ios ${target}",
- keepEnv: [
- 'FASTLANE_DISABLE_COLORS',
- 'FASTLANE_PASSWORD', 'KEYCHAIN_PASSWORD',
- 'MATCH_PASSWORD', 'FASTLANE_APPLE_ID',
- ],
- attr: 'shells.ios'
- )
- }
- /* rename built file for uploads and archivization */
- def pkg = ''
- if (btype == 'release') {
- pkg = utils.pkgFilename('release', 'ipa')
- sh "cp status_appstore/StatusIm.ipa ${pkg}"
- } else if (btype == 'e2e') {
- pkg = utils.pkgFilename('e2e', 'app.zip')
- sh "cp status-e2e/StatusIm.app.zip ${pkg}"
- } else if (btype != 'testflight') {
- pkg = utils.pkgFilename(btype, 'ipa')
- sh "cp status-adhoc/StatusIm.ipa ${pkg}"
- }
- /* necessary for Diawi upload */
- env.DIAWI_IPA = pkg
- return pkg
-}
-
-def uploadToDiawi() {
- withCredentials([
- string(credentialsId: 'diawi-token', variable: 'DIAWI_TOKEN'),
- ]) {
- /* This can silently fail with 'File is not processed.' */
- nix.shell(
- 'bundle exec --verbose --gemfile=fastlane/Gemfile fastlane ios upload_diawi',
- keepEnv: ['FASTLANE_DISABLE_COLORS', 'DIAWI_TOKEN'],
- attr: 'shells.fastlane'
- )
- }
- diawiUrl = readFile "${env.WORKSPACE}/fastlane/diawi.out"
- /* Save the URL in the build description */
- currentBuild.description = "Diawi Link"
- return diawiUrl
-}
-
-def uploadToSauceLabs() {
- def changeId = utils.getParentRunEnv('CHANGE_ID')
- if (changeId != null) {
- env.SAUCE_LABS_NAME = "${changeId}.app.zip"
- } else {
- env.SAUCE_LABS_NAME = "im.status.ethereum-e2e-${utils.gitCommit()}.app.zip"
- }
- withCredentials([
- usernamePassword(
- credentialsId: 'sauce-labs-api',
- usernameVariable: 'SAUCE_USERNAME',
- passwordVariable: 'SAUCE_ACCESS_KEY'
- ),
- ]) {
- nix.shell(
- 'bundle exec --gemfile=fastlane/Gemfile fastlane ios saucelabs',
- keepEnv: ['FASTLANE_DISABLE_COLORS', 'SAUCE_ACCESS_KEY', 'SAUCE_USERNAME'],
- attr: 'shells.fastlane'
- )
- }
- return env.SAUCE_LABS_NAME
-}
-
-return this
diff --git a/ci/jenkins.groovy b/ci/jenkins.groovy
deleted file mode 100644
index 2d97a6fee1..0000000000
--- a/ci/jenkins.groovy
+++ /dev/null
@@ -1,92 +0,0 @@
-import jenkins.model.CauseOfInterruption.UserInterruption
-import hudson.model.Result
-import hudson.model.Run
-
-utils = load 'ci/utils.groovy'
-
-@NonCPS
-def abortPreviousRunningBuilds() {
- /* Aborting makes sense only for PR builds, since devs start so many of them */
- if (!env.JOB_NAME.contains('status-react/prs')) {
- println ">> Not aborting any previous jobs. Not a PR build."
- return
- }
- Run previousBuild = currentBuild.rawBuild.getPreviousBuildInProgress()
-
- while (previousBuild != null) {
- if (previousBuild.isInProgress()) {
- def executor = previousBuild.getExecutor()
- if (executor != null) {
- println ">> Aborting older build #${previousBuild.number}"
- executor.interrupt(Result.ABORTED, new UserInterruption(
- "newer build #${currentBuild.number}"
- ))
- }
- }
-
- previousBuild = previousBuild.getPreviousBuildInProgress()
- }
-}
-
-def strParam(key, value) {
- /* just a helper for making string params */
- return [
- name: key,
- value: value,
- $class: 'StringParameterValue',
- ]
-}
-
-def Build(name = null) {
- /**
- * Generate parameters to pass from current params
- * This allows utils.updateEnv() to work in sub-jobs
- **/
- parameters = params.keySet().collectEntries { key ->
- [(key): strParam(key, params.get(key))]
- }
- /* default to current build type */
- parameters['BUILD_TYPE'] = strParam('BUILD_TYPE', utils.getBuildType())
- /* need to drop origin/ to match definitions of child jobs */
- parameters['BRANCH'] = strParam('BRANCH', utils.branchName())
- /* necessary for updating GitHub PRs */
- parameters['CHANGE_ID'] = strParam('CHANGE_ID', env.CHANGE_ID)
- /* always pass the BRANCH and BUILD_TYPE params with current branch */
- def b = build(
- job: name,
- /* this allows us to analize the job even after failure */
- propagate: false,
- parameters: parameters.values()
- )
- /* BlueOcean seems to not show child-build links */
- println "Build: ${b.getAbsoluteUrl()} (${b.result})"
- if (b.result != 'SUCCESS') {
- error("Build Failed")
- }
- return b
-}
-
-def copyArts(build) {
- /**
- * The build argument is of class RunWrapper.
- * https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
- **/
- copyArtifacts(
- projectName: build.fullProjectName,
- target: 'pkg',
- flatten: true,
- selector: specific("${build.number}")
- )
-}
-
-def setBuildDesc(Map links) {
- def desc = 'Links: \n'
- links.each { type, url ->
- if (url != null) {
- desc += "${type} \n"
- }
- }
- currentBuild.description = desc
-}
-
-return this
diff --git a/ci/nix.groovy b/ci/nix.groovy
deleted file mode 100644
index caefd2fa6c..0000000000
--- a/ci/nix.groovy
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * Arguments:
- * - pure - Use --pure mode with Nix for more deterministic behaviour
- * - args - Map of arguments to provide to --argstr
- * - keepEnv - List of env variables to keep even in pure mode
- **/
-def shell(Map opts = [:], String cmd) {
- def defaults = [
- pure: true,
- args: ['target': env.TARGET ? env.TARGET : 'default'],
- keepEnv: ['LOCALE_ARCHIVE_2_27'],
- sandbox: true,
- ]
- /* merge defaults with received opts */
- opts = defaults + opts
- /* previous merge overwrites the array */
- opts.keepEnv = (opts.keepEnv + defaults.keepEnv).unique()
- /* not all targets can use a pure build */
- if (env.TARGET in ['windows', 'ios']) {
- opts.pure = false
- }
- sh("""
- set +x
- . ~/.nix-profile/etc/profile.d/nix.sh
- set -x
- nix-shell --run \'${cmd}\' ${_getNixCommandArgs(opts, true)}
- """)
-}
-
-/**
- * Arguments:
- * - pure - Use --pure mode with Nix for more deterministic behaviour
- * - link - Bu default build creates a `result` directory, you can turn that off
- * - conf - Map of config values to provide to --arg config
- * - args - Map of arguments to provide to --argstr
- * - attr - Name of attribute to use with --attr flag
- * - keepEnv - List of env variables to pass through to Nix build
- * - safeEnv - Name of env variables to pass securely through to Nix build (they won't get captured in Nix derivation file)
- * - sandbox - If build process should run inside of a sandbox
- * - sandboxPaths - List of file paths to make available in Nix sandbox
- **/
-def build(Map opts = [:]) {
- def defaults = [
- pure: true,
- link: true,
- args: ['target': env.TARGET],
- conf: [:],
- attr: null,
- keepEnv: [],
- safeEnv: [],
- sandbox: true,
- sandboxPaths: [],
- ]
- /* merge defaults with received opts */
- opts = defaults + opts
- /* Previous merge overwrites the array */
- opts.args = defaults.args + opts.args
- opts.keepEnv = (opts.keepEnv + defaults.keepEnv).unique()
-
- def nixPath = sh(
- returnStdout: true,
- script: """
- set +x
- . ~/.nix-profile/etc/profile.d/nix.sh
- set -x
- nix-build ${_getNixCommandArgs(opts, false)}
- """
- ).trim()
- /* if not linking, copy results, but only if there's just one path */
- if (!opts.link && nixPath && !nixPath.contains('\n')) {
- copyResults(nixPath)
- }
- return nixPath
-}
-
-private def copyResults(path) {
- def resultsPath = "${env.WORKSPACE}/result"
- sh "rm -fr ${resultsPath}"
- sh "mkdir -p ${resultsPath}"
- sh "cp -fr ${path}/* ${resultsPath}/"
- sh "chmod -R 755 ${resultsPath}"
-}
-
-private makeNixBuildEnvFile(Map opts = [:]) {
- File envFile = File.createTempFile("nix-env", ".tmp")
- if (!opts.safeEnv.isEmpty()) {
- // Export the environment variables we want to keep into a temporary script we can pass to Nix and source it from the build script
- def exportCommandList = opts.safeEnv.collect { envVarName -> """
- echo \"export ${envVarName}=\\\"\$(printenv ${envVarName})\\\"\" >> ${envFile.absolutePath}
- """ }
- def exportCommands = exportCommandList.join("")
- sh """
- ${exportCommands}
- chmod u+x ${envFile.absolutePath}
- """
-
- opts.args = opts.args + [ 'secrets-file': envFile.absolutePath ]
- opts.sandboxPaths = opts.sandboxPaths + envFile.absolutePath
- }
-
- return envFile
-}
-
-private def _getNixCommandArgs(Map opts = [:], boolean isShell) {
- def keepFlags = []
- def entryPoint = "\'${env.WORKSPACE}/shell.nix\'"
- if (!isShell || opts.attr != null) {
- entryPoint = "\'${env.WORKSPACE}/default.nix\'"
- }
- /* don't let nix.conf control sandbox status */
- def extraSandboxPathsFlag = "--option sandbox ${opts.sandbox}"
-
- if (isShell) {
- keepFlags = opts.keepEnv.collect { var -> "--keep ${var} " }
- } else {
- def envVarsList = opts.keepEnv.collect { var -> "${var}=\"${env[var]}\";" }
- keepFlags = ["--arg env \'{${envVarsList.join("")}}\'"]
-
- /* Export the environment variables we want to keep into
- * a Nix attribute set we can pass to Nix and source it from the build script */
- def envFile = makeNixBuildEnvFile(opts)
- envFile.deleteOnExit()
- }
-
- def configFlag = ''
- def argsFlags = opts.args.collect { key,val -> "--argstr ${key} \'${val}\'" }
- def attrFlag = ''
- if (opts.attr != null) {
- attrFlag = "--attr '${opts.attr}'"
- }
- if (opts.conf != null && opts.conf != [:]) {
- def configFlags = opts.conf.collect { key,val -> "${key}=\"${val}\";" }
- configFlag = "--arg config \'{${configFlags.join('')}}\'"
- }
- if (opts.sandboxPaths != null && !opts.sandboxPaths.isEmpty()) {
- extraSandboxPathsFlag += " --option extra-sandbox-paths \"${opts.sandboxPaths.join(' ')}\""
- }
-
- return [
- opts.pure ? "--pure" : "",
- opts.link ? "" : "--no-out-link",
- configFlag,
- keepFlags.join(" "),
- argsFlags.join(" "),
- extraSandboxPathsFlag,
- attrFlag,
- entryPoint,
- ].join(" ")
-}
-
-def prepEnv() {
- if (env.TARGET in ['linux', 'windows', 'android']) {
- def glibcLocales = sh(
- returnStdout: true,
- script: """
- . ~/.nix-profile/etc/profile.d/nix.sh && \\
- nix-build --no-out-link '' -A glibcLocales
- """
- ).trim()
- /**
- * This is a hack to fix missing locale errors.
- * See:
- * - https://github.com/NixOS/nixpkgs/issues/38991
- * - https://qiita.com/kimagure/items/4449ceb0bda5c10ca50f
- **/
- env.LOCALE_ARCHIVE_2_27 = "${glibcLocales}/lib/locale/locale-archive"
- }
-}
-
-return this
diff --git a/ci/utils.groovy b/ci/utils.groovy
deleted file mode 100644
index ebaf7cf7e2..0000000000
--- a/ci/utils.groovy
+++ /dev/null
@@ -1,151 +0,0 @@
-def getVersion() {
- def path = "${env.WORKSPACE}/VERSION"
- return readFile(path).trim()
-}
-
-def branchName() {
- return env.GIT_BRANCH.replaceAll(/.*origin\//, '')
-}
-
-def parentOrCurrentBuild() {
- def c = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
- if (c == null) { return currentBuild }
- return c.getUpstreamRun()
-}
-
-def timestamp() {
- /* we use parent if available to make timestmaps consistent */
- def now = new Date(parentOrCurrentBuild().timeInMillis)
- return now.format('yyMMdd-HHmmss', TimeZone.getTimeZone('UTC'))
-}
-
-def gitCommit() {
- return GIT_COMMIT.take(6)
-}
-
-def pkgFilename(type, ext, arch=null) {
- /* the grep removes the null arch */
- return [
- "StatusIm", timestamp(), gitCommit(), type, arch,
- ].grep().join('-') + ".${ext}"
-}
-
-def doGitRebase() {
- if (!isPRBuild()) {
- println 'Skipping rebase due for non-PR build...'
- return
- }
- def rebaseBranch = 'develop'
- if (env.CHANGE_TARGET) { /* This is available for PR builds */
- rebaseBranch = env.CHANGE_TARGET
- }
- sh 'git status'
- sh "git fetch --force origin ${rebaseBranch}:${rebaseBranch}"
- try {
- sh "git rebase ${rebaseBranch}"
- } catch (e) {
- sh 'git rebase --abort'
- throw e
- }
-}
-
-def genBuildNumber() {
- def number = sh(
- returnStdout: true,
- script: "${env.WORKSPACE}/scripts/version/gen_build_no.sh"
- ).trim()
- println "Build Number: ${number}"
- return number
-}
-
-def readBuildNumber() {
- def number = sh(
- returnStdout: true,
- script: "${env.WORKSPACE}/scripts/version/build_no.sh"
- ).trim()
- return number
-}
-
-def getDirPath(path) {
- return path.tokenize('/')[0..-2].join('/')
-}
-
-def getFilename(path) {
- return path.tokenize('/')[-1]
-}
-
-def getEnv(build, envvar) {
- return build.getBuildVariables().get(envvar)
-}
-
-def buildDuration() {
- def duration = currentBuild.durationString
- return '~' + duration.take(duration.lastIndexOf(' and counting'))
-}
-
-def pkgFind(glob) {
- def fullGlob = "pkg/*${glob}"
- def found = findFiles(glob: fullGlob)
- if (found.size() == 0) {
- sh 'ls -l pkg/'
- error("File not found via glob: ${fullGlob} ${found.size()}")
- }
- return found[0].path
-}
-
-def isPRBuild() {
- return env.JOB_NAME.startsWith('status-react/prs')
-}
-
-def isE2EBuild() {
- return env.JOB_NAME.contains('e2e')
-}
-
-def getBuildType() {
- def jobName = env.JOB_NAME
- if (isE2EBuild()) {
- return 'e2e'
- }
- if (isPRBuild()) {
- return 'pr'
- }
- if (jobName.startsWith('status-react/nightly')) {
- return 'nightly'
- }
- if (jobName.startsWith('status-react/release')) {
- return 'release'
- }
- return params.BUILD_TYPE
-}
-
-def getParentRunEnv(name) {
- def c = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
- if (c == null) { return null }
- return c.getUpstreamRun().getEnvironment()[name]
-}
-
-def changeId() {
- /* CHANGE_ID can be provided via the build parameters or from parent */
- def changeId = env.CHANGE_ID
- changeId = params.CHANGE_ID ? params.CHANGE_ID : changeId
- changeId = getParentRunEnv('CHANGE_ID') ? getParentRunEnv('CHANGE_ID') : changeId
- if (!changeId) {
- println('This build is not related to a PR, CHANGE_ID missing.')
- println('GitHub notification impossible, skipping...')
- return null
- }
- return changeId
-}
-
-def updateEnv(type) {
- def envFile = "${env.WORKSPACE}/.env.jenkins"
- /* select .env based on type of build */
- if (['nightly', 'release', 'e2e'].contains(type)) {
- envFile = "${env.WORKSPACE}/.env.${type}"
- }
- sh "ln -sf ${envFile} .env"
- /* show contents for debugging purposes */
- sh "cat ${envFile}"
-}
-
-return this
diff --git a/scripts/generate-keystore.sh b/scripts/generate-keystore.sh
index 84a5e56b26..775d80e3d7 100755
--- a/scripts/generate-keystore.sh
+++ b/scripts/generate-keystore.sh
@@ -22,7 +22,7 @@ if [[ -z ${KEYSTORE_PATH} ]]; then
KEYSTORE_PATH=$(property_gradle 'KEYSTORE_FILE')
fi
# Replace ~ with proper absolute path
-KEYSTORE_PATH=${KEYSTORE_FILE/#\~/$HOME}
+KEYSTORE_PATH=${KEYSTORE_PATH/#\~/$HOME}
if [[ -e "${KEYSTORE_PATH}" ]]; then
echo -e "${YLW}Keystore file already exists:${RST} ${KEYSTORE_PATH}" > /dev/stderr