#!groovy @Library('SovrinHelpers') _ try { testing() publishing() if (acceptanceTesting()) { releasing() } notifyingSuccess() } catch (err) { notifyingFailure() throw err } def testing() { stage('Testing') { parallel([ 'ubuntu-test' : { ubuntuTesting() }, 'windows-test': { windowsTesting() } ]) } } def publishing() { stage('Publishing') { echo "${env.BRANCH_NAME}: start publishing" publishedVersions = parallel([ 'ubuntu-files' : { ubuntuPublishing() }, 'windows-files': { windowsPublishing() }, ]) if (publishedVersions['windows-files'] != publishedVersions['ubuntu-files']) { error "platforms artifacts have different versions" } } } def acceptanceTesting() { stage('Acceptance testing') { if (env.BRANCH_NAME == 'rc') { echo "${env.BRANCH_NAME}: acceptance testing" if (approval.check("default")) { return true } } else { echo "${env.BRANCH_NAME}: skip acceptance testing" } return false } } def releasing() { stage('Releasing') { if (env.BRANCH_NAME == 'rc') { publishingRCtoStable() } } } def notifyingSuccess() { currentBuild.result = "SUCCESS" node('ubuntu-master') { sendNotification.success('indy-crypto') } } def notifyingFailure() { currentBuild.result = "FAILED" node('ubuntu-master') { sendNotification.fail([slack: true]) } } void getSrcVersion() { commit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim() version = sh(returnStdout: true, script: "wget -q https://raw.githubusercontent.com/hyperledger/indy-crypto/$commit/libindy-crypto/Cargo.toml -O - | grep -E '^version =' | head -n1 | cut -f2 -d= | cut -f2 -d '\"'").trim() return version } def linuxTesting(file, env_name) { try { echo "${env_name} Test: Checkout csm" checkout scm def testEnv dir('libindy-crypto') { echo "${env_name} Test: Build docker image" testEnv = dockerHelpers.build('libindy-crypto', file) testEnv.inside { echo "${env_name} Test: Test" try { echo "${env_name} Test: Build" sh "RUST_BACKTRACE=1 cargo test --release --no-run" echo "${env_name} Test: Run tests" sh "RUST_BACKTRACE=1 RUST_LOG=trace cargo test --release" stash includes: 'target/release/libindy_crypto.so,target/release/libindy_crypto.a', name: 'LibindyCryptoUbuntuBuildResult' } finally { /* TODO FIXME restore after xunit will be fixed junit 'test-results.xml' */ } } } sh "cp libindy-crypto/target/release/libindy_crypto.so wrappers/python" dir('wrappers/python') { testEnv.inside() { echo "${env_name} Test: Test python wrapper" sh ''' python3.5 -m pip install --user -e . LD_LIBRARY_PATH=./ RUST_LOG=trace python3.5 -m pytest ''' } } } finally { step([$class: 'WsCleanup']) } } def windowsTesting() { node('win2016') { stage('Windows Test') { def ws_path = "workspace/${env.JOB_NAME}".replace(' ', '_') ws(ws_path) { try { echo "Windows Test: Checkout scm" checkout scm setupRust() dir('libindy-crypto') { echo "Windows Test: Download prebuilt dependencies" bat 'wget -O prebuilt.zip "https://repo.sovrin.org/windows/libindy_crypto/deps/indy-crypto-deps.zip"' bat 'unzip prebuilt.zip -d prebuilt' echo "Windows Test: Build" withEnv([ "OPENSSL_DIR=$WORKSPACE\\libindy-crypto\\prebuilt", "PATH=$WORKSPACE\\libindy-crypto\\prebuilt\\lib;$PATH", "RUST_BACKTRACE=1" ]) { bat "cargo test --release --no-run" echo "Windows Test: Run tests" withEnv(["RUST_LOG=trace"]) { bat "cargo test --release" } } stash includes: 'target/release/*.dll;prebuilt/lib/*.dll', name: 'LibindyCryptoWindowsBuildResult' } //TODO wrappers testing } finally { cleanWs() } } cleanWs() } } } def ubuntuTesting() { node('ubuntu') { stage('Ubuntu Test') { linuxTesting("ci/ubuntu.dockerfile ci", "Ubuntu") } } } def ubuntuPublishing() { node('ubuntu') { stage('Publish Ubuntu Files') { try { echo 'Publish Ubuntu files: Checkout csm' checkout scm version = getSrcVersion() echo 'Publish Ubuntu files: Build docker image' testEnv = dockerHelpers.build('indy-crypto', 'libindy-crypto/ci/ubuntu.dockerfile libindy-crypto/ci') libindyCryptoDebPublishing(testEnv) libindyCryptoCargoPublishing(testEnv, false) pythonWrapperPypiPublishing(testEnv, false) pythonWrapperDebPublishing(testEnv) } finally { echo 'Publish Ubuntu files: Cleanup' step([$class: 'WsCleanup']) } } } return version } def windowsPublishing() { node('ubuntu') { stage('Publish Libindy Crypto Windows Files') { try { echo 'Publish Windows files: Checkout csm' checkout scm version = getSrcVersion() echo 'Publish Windows files: Build docker image' testEnv = dockerHelpers.build('indy-crypto', 'libindy-crypto/ci/ubuntu.dockerfile libindy-crypto/ci') dir('libindy-crypto') { windowsPublishArtifact(testEnv, "LibindyCryptoWindowsBuildResult") } } finally { echo 'Publish Windows files: Cleanup' step([$class: 'WsCleanup']) } } } return version } def windowsPublishArtifact(testEnv, stashName) { testEnv.inside { sh 'chmod -R 777 ci' unstash name: stashName withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'sovrin_repo_key')]) { sh "./ci/libindy_crypto-win-zip-and-upload.sh $version '${sovrin_repo_key}' $env.BRANCH_NAME $env.BUILD_NUMBER ./prebuilt" } } } def getSuffix(isRelease, target) { def suffix if (env.BRANCH_NAME == 'master' && !isRelease) { suffix = "-dev-$env.BUILD_NUMBER" } else if (env.BRANCH_NAME == 'rc') { if (isRelease) { suffix = "" } else { suffix = "-rc-$env.BUILD_NUMBER" } } else { error "Publish To ${target}: invalid case: branch ${env.BRANCH_NAME}, isRelease ${isRelease}" } return suffix } def libindyCryptoDebPublishing(testEnv) { echo 'Publish Libindy-Crypto deb files to Apt' dir('libindy-crypto/sovrin-packaging') { downloadPackagingUtils() } testEnv.inside { sh 'chmod -R 755 libindy-crypto/ci/*.sh' def suffix = "~$env.BUILD_NUMBER" unstash name: 'LibindyCryptoUbuntuBuildResult' sh 'mkdir --parent libindy-crypto/target/release/ && mv target/release/* libindy-crypto/target/release/' withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'sovrin_key')]) { sh "cd libindy-crypto && ./ci/libindy_crypto-deb-build-and-upload.sh $version $env.BRANCH_NAME $suffix $SOVRIN_SDK_REPO_NAME $SOVRIN_REPO_HOST $sovrin_key" if (env.BRANCH_NAME == 'rc') { stash includes: 'libindy-crypto/debs/*', name: 'libindyCryptoDebs' } } } } def libindyCryptoCargoPublishing(testEnv, isRelease) { dir('libindy-crypto') { echo 'Publish Libindy-Crypto to Cargo' testEnv.inside { def suffix = getSuffix(isRelease, "Cargo") sh "sed -i -E -e 'H;1h;\$!d;x' -e \"s/version = \\\"([0-9,.]+)/version = \\\"\\1$suffix/\" Cargo.toml" withCredentials([string(credentialsId: 'cargoSecretKey', variable: 'LOGIN')]) { sh 'cargo login $LOGIN' sh 'cargo package --allow-dirty' sh 'cargo publish --allow-dirty' } } } } def pythonWrapperPypiPublishing(testEnv, isRelease) { dir('wrappers/python') { echo 'Publish Python Wrapper to Pypi' testEnv.inside { def suffix = getSuffix(isRelease, "Pypi") withCredentials([file(credentialsId: 'pypi_credentials', variable: 'credentialsFile')]) { sh 'cp $credentialsFile ./' sh "sed -i -E \"s/version='([0-9,.]+).*/version='\\1$suffix',/\" setup.py" sh ''' python3.5 setup.py sdist python3.5 -m twine upload dist/* --config-file .pypirc ''' } } } } def pythonWrapperDebPublishing(testEnv) { dir('wrappers/python') { echo 'Publish Python Wrapper deb files to APt' dir('sovrin-packaging') { downloadPackagingUtils() } testEnv.inside { sh 'chmod -R 755 ci/*.sh' def suffix = "~$env.BUILD_NUMBER" withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'sovrin_key')]) { sh "./ci/python-wrapper-deb-build-and-upload.sh $env.BRANCH_NAME $suffix $SOVRIN_SDK_REPO_NAME $SOVRIN_REPO_HOST $sovrin_key" if (env.BRANCH_NAME == 'rc') { stash includes: 'debs/*', name: 'PythonWrapperDebs' } } } } } def publishingRCtoStable() { node('ubuntu') { stage('Moving RC artifacts to Stable') { try { echo 'Moving RC artifacts to Stable: Checkout csm' checkout scm echo 'Moving RC artifacts to Stable: Download packaging utils' dir('sovrin-packaging') { downloadPackagingUtils() } version = getSrcVersion() echo 'Moving Windows RC artifacts to Stable: libindy-crypto' publishLibindyCryptoWindowsFilesRCtoStable(version) echo 'Moving RC artifacts to Stable: Build docker image' testEnv = dockerHelpers.build('indy-crypto', 'libindy-crypto/ci/ubuntu.dockerfile libindy-crypto/ci') echo 'Moving Ubuntu RC artifacts to Stable: libindy-crypto' publishLibindyCryptoDebRCtoStable(testEnv, version) echo 'Moving RC artifacts to Stable: libindy-crypto to Cargo ' libindyCryptoCargoPublishing(testEnv, true) echo 'Moving RC artifacts to Stable: python wrapper to Pypi ' pythonWrapperPypiPublishing(testEnv, true) echo 'Moving RC artifacts to Stable: python wrapper deb files ' publishPythonWrapperDebRCtoStable(testEnv, version) } finally { echo 'Moving RC artifacts to Stable: Cleanup' step([$class: 'WsCleanup']) } } } } def publishLibindyCryptoWindowsFilesRCtoStable(version) { rcFullVersion = "${version}-${env.BUILD_NUMBER}" withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'sovrin_repo_key')]) { src = "/var/repository/repos/windows/libindy_crypto/rc/$rcFullVersion/" target = "/var/repository/repos/windows/libindy_crypto/stable/$version" sh "ssh -v -oStrictHostKeyChecking=no -i '$sovrin_repo_key' repo@192.168.11.115 '! ls $target'" sh "ssh -v -oStrictHostKeyChecking=no -i '$sovrin_repo_key' repo@192.168.11.115 cp -r $src $target" } } def publishLibindyCryptoDebRCtoStable(testEnv, version) { testEnv.inside { rcFullVersion = "${version}~${env.BUILD_NUMBER}" unstash name: 'libindyCryptoDebs' sh "fakeroot deb-reversion -v $version libindy-crypto/debs/libindy-crypto_\"$rcFullVersion\"_amd64.deb" sh "fakeroot deb-reversion -v $version libindy-crypto/debs/libindy-crypto-dev_\"$rcFullVersion\"_amd64.deb" uploadDebianFilesToStable() } } def publishPythonWrapperDebRCtoStable(testEnv, version) { testEnv.inside { rcFullVersion = "${version}~${env.BUILD_NUMBER}" unstash name: 'PythonWrapperDebs' sh "fakeroot deb-reversion -v $version debs/python3-indy-crypto_\"$rcFullVersion\"_amd64.deb" uploadDebianFilesToStable() } } def uploadDebianFilesToStable() { withCredentials([file(credentialsId: 'SovrinRepoSSHKey', variable: 'sovrin_key')]) { path = sh(returnStdout: true, script: 'pwd').trim() sh "./sovrin-packaging/upload_debs.py $path $SOVRIN_SDK_REPO_NAME stable --host $SOVRIN_REPO_HOST --ssh-key $sovrin_key" } } def downloadPackagingUtils() { git branch: 'master', credentialsId: 'evernym-github-machine-user', url: 'https://github.com/evernym/sovrin-packaging' } def shell(command) { if (isUnix()) { sh command } else { bat command } } def setupRust() { shell("rustup default 1.25.0") }