status-desktop/test/e2e/ci/Jenkinsfile
Jakub Sokołowski 873a804155 ci: use virtualenv to avoid race conditions
Desktop QA tests also use Pytest packages and their versions are
different, so we can't install them globally, it needs to be done per
build using `WORKSPACE_TMP` as destination.

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2024-04-15 17:45:04 +03:00

252 lines
7.0 KiB
Groovy

#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.6'
pipeline {
agent {
label "${params.AGENT} && x86_64 && qt-5.15.2"
}
parameters {
gitParameter(
name: 'GIT_REF',
description: 'Git branch to checkout.',
branchFilter: 'origin/(.*)',
branch: '',
defaultValue: 'master',
quickFilterEnabled: false,
selectedValue: 'DEFAULT',
sortMode: 'ASCENDING_SMART',
tagFilter: '*',
type: 'PT_BRANCH'
)
string(
name: 'BUILD_SOURCE',
description: 'URL to tar.gz file OR path to Jenkins build.',
defaultValue: getDefaultBuildSource()
)
string(
name: 'TEST_NAME',
description: 'Paste test name/part of test name to run specific test.',
defaultValue: ''
)
string(
name: 'TEST_SCOPE_FLAG',
description: 'Paste a known mark to run tests labeled with this mark',
defaultValue: getDefaultTestScopeFlag()
)
string(
name: 'TESTRAIL_RUN_NAME',
description: 'Test run name in Test Rail.',
defaultValue: ''
)
choice(
name: 'LOG_LEVEL',
description: 'Log level for pytest.',
choices: ['INFO', 'DEBUG', 'TRACE', 'WARNING', 'CRITICAL']
)
/* FIXME: This is temporary and should be removed. */
choice(
name: 'AGENT',
description: 'Agent name to run tests on it.',
choices: ['linux', 'linux-01', 'linux-02', 'linux-03', 'linux-04', 'linux-05']
)
}
options {
timestamps()
/* Prevent Jenkins jobs from running forever */
timeout(time: 120, unit: 'MINUTES')
/* manage how many builds we keep */
buildDiscarder(logRotator(
daysToKeepStr: '60',
numToKeepStr: '50',
artifactNumToKeepStr: '50',
))
}
environment {
SQUISH_DIR = '/opt/squish-runner-7.2.1'
PYTHONPATH = "${SQUISH_DIR}/lib:${SQUISH_DIR}/lib/python:${PYTHONPATH}"
LD_LIBRARY_PATH = "${SQUISH_DIR}/lib:${SQUISH_DIR}/python3/lib:${LD_LIBRARY_PATH}"
/* Avoid race conditions with other builds using virtualenv. */
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
TESTRAIL_URL = 'https://ethstatus.testrail.net'
TESTRAIL_PROJECT_ID = 17
/* Runtime flag to make testing of the app easier. Switched off: unpredictable app behavior under new tests */
/* STATUS_RUNTIME_TEST_MODE = 'True' */
}
stages {
stage('Prep') {
steps { script {
setNewBuildName()
updateGitHubStatus()
} }
}
stage('Deps') {
steps { script {
sh "python3 -m venv ${VIRTUAL_ENV}"
sh 'pip3 install -r requirements.txt'
} }
}
stage('Download') {
when { expression { params.BUILD_SOURCE.startsWith('http') } }
steps { timeout(5) { script {
sh 'mkdir -p ./pkg/'
setBuildDescFromFile(params.BUILD_SOURCE)
fileOperations([
fileDownloadOperation(
url: params.BUILD_SOURCE,
targetFileName: 'StatusIm-Desktop.tar.gz',
targetLocation: './pkg/',
userName: '',
password: '',
)
])
} } }
}
stage('Copy') {
when { expression { ! params.BUILD_SOURCE.startsWith('http') } }
steps { timeout(5) { script {
copyArtifacts(
projectName: params.BUILD_SOURCE,
filter: 'pkg/*-x86_64.tar.gz',
selector: lastWithArtifacts(),
target: './'
)
setBuildDescFromFile(utils.findFile('pkg/*tar.gz'))
} } }
}
stage('Unpack') {
steps { timeout(5) { script {
sh 'mkdir aut'
sh "tar -zxvf '${utils.findFile('pkg/*tar.gz')}' -C './aut'"
env.AUT_PATH = utils.findFile('aut/*.AppImage')
} } }
}
stage('Test') {
steps { timeout(90) { script {
def flags = []
if (params.TEST_NAME) { flags.add("-k=${params.TEST_NAME}") }
if (params.TEST_SCOPE_FLAG) { flags.add(params.TEST_SCOPE_FLAG) }
if (params.LOG_LEVEL) { flags.addAll(["--log-level=${params.LOG_LEVEL}", "--log-cli-level=${params.LOG_LEVEL}"]) }
dir ('configs') { sh 'ln -s _local.ci.py _local.py' }
wrap([
$class: 'Xvfb',
autoDisplayName: true,
parallelBuild: true,
screen: '1920x1080x24',
additionalOptions: '-dpi 1'
]) {
sh 'fluxbox &'
withCredentials([
usernamePassword(
credentialsId: 'test-rail-api-devops',
usernameVariable: 'TESTRAIL_USR',
passwordVariable: 'TESTRAIL_PSW'
)
]) {
/* Keep the --reruns flag first, or it won't work */
sh """
python3 -m pytest --reruns=1 ${flags.join(" ")} \
--disable-warnings \
--alluredir=./allure-results
"""
}
}
} } }
}
}
post {
always { script {
archiveArtifacts('aut/*.log')
/* Needed to categorize types of errors and add environment section in allure report. */
sh 'cp ext/allure_files/categories.json allure-results'
sh 'cp ext/allure_files/environment.properties allure-results'
allure([
results: [[path: 'allure-results']],
reportBuildPolicy: 'ALWAYS',
properties: [],
jdk: '',
])
updateGitHubStatus()
} }
failure { script {
discord.send(
header: '**Desktop E2E test failure!**',
cred: 'discord-status-desktop-e2e-webhook',
)
} }
cleanup { cleanWs() }
}
}
def setNewBuildName() {
if (currentBuild.upstreamBuilds) {
def parent = utils.parentOrCurrentBuild()
currentBuild.displayName = parent.getFullDisplayName().minus('status-desktop » ')
}
}
def setBuildDescFromFile(fileNameOrPath) {
def tokens = utils.parseFilename(utils.baseName(fileNameOrPath))
if (tokens == null) { /* Fallback for regex fail. */
currentBuild.description = utils.baseName(fileNameOrPath)
return
}
if (tokens.build && tokens.build.startsWith('pr')) {
currentBuild.displayName = tokens.build.replace(/^pr/, 'PR-')
}
currentBuild.description = formatMap([
Node: NODE_NAME,
Build: tokens.build,
Commit: tokens.commit,
Version: (tokens.tstamp ?: tokens.version),
])
}
def updateGitHubStatus() {
/* For PR builds update check status. */
if (params.BUILD_SOURCE ==~ /.*\/PR-[0-9]+\/?$/) {
github.statusUpdate(
context: 'jenkins/prs/tests/e2e-new',
commit: jenkins.getJobCommitByPath(params.BUILD_SOURCE),
repo_url: 'https://github.com/status-im/status-desktop'
)
}
}
def formatMap(Map data=[:]) {
def text = ''
data.each { key, val -> text += "<b>${key}</b>: ${val}</a><br>\n" }
return text
}
def getDefaultBuildSource() {
if (JOB_NAME ==~ 'status-desktop/qa-automation/prs/.*') {
return 'status-desktop/nightly'
}
return ''
}
def getDefaultTestScopeFlag() {
if (JOB_NAME == "status-desktop/systems/linux/x86_64/tests-e2e-new") {
return ''
} else {
return '-m=critical'
}
}