Skip to content

Commit 6db30b7

Browse files
committed
e2e: add windows pipeline
Referenced issue: * status-im/infra-ci#86
1 parent dd6489a commit 6db30b7

File tree

3 files changed

+300
-3
lines changed

3 files changed

+300
-3
lines changed

ci/Jenkinsfile.tests-e2e.windows

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
#!/usr/bin/env groovy
2+
3+
4+
pipeline {
5+
6+
agent {
7+
label 'windows && x86_64 && qt-6.9.2 && go-1.24 && windows-e2e'
8+
}
9+
10+
parameters {
11+
gitParameter(
12+
name: 'GIT_REF',
13+
description: 'Git branch to checkout.',
14+
branchFilter: 'origin/(.*)',
15+
branch: '',
16+
defaultValue: 'master',
17+
quickFilterEnabled: false,
18+
selectedValue: 'DEFAULT',
19+
sortMode: 'ASCENDING_SMART',
20+
tagFilter: '*',
21+
type: 'PT_BRANCH'
22+
)
23+
string(
24+
name: 'BUILD_SOURCE',
25+
description: 'URL to tar.gz file OR path to Jenkins build.',
26+
defaultValue: getDefaultBuildSource()
27+
)
28+
string(
29+
name: 'TEST_NAME',
30+
description: 'Paste test name/part of test name to run specific test.',
31+
defaultValue: ''
32+
)
33+
string(
34+
name: 'TEST_SCOPE_FLAG',
35+
description: 'Paste a known mark to run tests labeled with this mark',
36+
defaultValue: getDefaultTestScopeFlag()
37+
)
38+
string(
39+
name: 'TESTRAIL_RUN_NAME',
40+
description: 'Test run name in Test Rail.',
41+
defaultValue: ''
42+
)
43+
choice(
44+
name: 'LOG_LEVEL',
45+
description: 'Log level for pytest.',
46+
choices: ['INFO', 'DEBUG', 'TRACE', 'WARNING', 'CRITICAL']
47+
)
48+
}
49+
50+
options {
51+
timestamps()
52+
/* Prevent Jenkins jobs from running forever */
53+
timeout(time: 120, unit: 'MINUTES')
54+
/* manage how many builds we keep */
55+
buildDiscarder(logRotator(
56+
daysToKeepStr: '60',
57+
numToKeepStr: '50',
58+
artifactNumToKeepStr: '50',
59+
))
60+
disableRestartFromStage()
61+
}
62+
63+
environment {
64+
PLATFORM = 'tests/e2e'
65+
66+
SQUISH_DIR = 'C:\\squish-runner-9.0.1-qt-6.9'
67+
PYTHONPATH = "${SQUISH_DIR}\\lib;${SQUISH_DIR}\\bin;${SQUISH_DIR}\\lib\\python;${PYTHONPATH}"
68+
69+
/* To stop e2e tests using port 8545 */
70+
STATUS_RUNTIME_HTTP_API = 'False'
71+
STATUS_RUNTIME_WS_API = 'False'
72+
73+
/* Avoid race conditions with other builds using virtualenv. */
74+
VIRTUAL_ENV = "${WORKSPACE_TMP}\\venv"
75+
PATH = "${VIRTUAL_ENV}\\bin;C:\\Qt\\6.9.2\\msvc2022_64\\bin;${PATH}"
76+
77+
/* To store user configuratiin files in temp dir */
78+
XDG_CONFIG_HOME = "${WORKSPACE_TMP}/config"
79+
80+
TESTRAIL_URL = 'https://ethstatus.testrail.net'
81+
TESTRAIL_PROJECT_ID = 18
82+
/* Override QT xcb plugin with linux to avoid errors like:
83+
* "Could not load the Qt platform plugin "xcb" in "" even though it was found."
84+
QT_QPA_PLATFORM = "linuxfb"*/
85+
86+
/* Runtime flag to make testing of the app easier. Switched off: unpredictable app behavior under new tests */
87+
STATUS_RUNTIME_TEST_MODE = 1
88+
89+
/* Logging rules let you enable or disable logging for categories */
90+
QT_LOGGING_RULES = '*.warning=true'
91+
92+
/* Set to a non-zero value to make Qt print out diagnostic information about the each (C++) plugin it tries to load. */
93+
/* QT_DEBUG_PLUGINS = 0 */
94+
95+
/* Hack fix for params not being set in job on first run */
96+
BUILD_SOURCE = "${params.BUILD_SOURCE}"
97+
TEST_NAME = "${params.TEST_NAME}"
98+
TEST_SCOPE_FLAG = "${params.TEST_SCOPE_FLAG}"
99+
TESTRAIL_RUN_NAME = "${params.TESTRAIL_RUN_NAME}"
100+
LOG_LEVEL = "${params.LOG_LEVEL}"
101+
102+
}
103+
104+
stages {
105+
stage('Cleanup Workspace') {
106+
steps {
107+
sh './scripts/clean-git.sh'
108+
}
109+
}
110+
stage('Prep') {
111+
steps { script {
112+
setNewBuildName()
113+
updateGitHubStatus()
114+
} }
115+
}
116+
117+
stage('Deps') {
118+
steps { script { dir('test/e2e') {
119+
bat """
120+
python310 -m venv ${VIRTUAL_ENV}
121+
python310 -m pip install --upgrade pip
122+
python310 -m pip install -r requirements.txt
123+
"""
124+
} } }
125+
}
126+
127+
stage('Download') {
128+
when { expression { params.BUILD_SOURCE.startsWith('http') } }
129+
steps { timeout(5) { script { dir('test/e2e') {
130+
sh 'mkdir -p ./pkg/'
131+
setBuildDescFromFile(params.BUILD_SOURCE)
132+
fileOperations([
133+
fileDownloadOperation(
134+
url: params.BUILD_SOURCE,
135+
targetFileName: 'StatusIm-Desktop.7z',
136+
targetLocation: './pkg/',
137+
userName: '',
138+
password: '',
139+
)
140+
])
141+
} } } }
142+
}
143+
144+
stage('Copy') {
145+
when { expression { ! params.BUILD_SOURCE.startsWith('http') } }
146+
steps { timeout(5) { script { dir('test/e2e') {
147+
copyArtifacts(
148+
projectName: params.BUILD_SOURCE,
149+
filter: 'pkg/*-x86_64.7z',
150+
selector: lastWithArtifacts(),
151+
target: './'
152+
)
153+
setBuildDescFromFile(utils.findFile('pkg/*7z'))
154+
} } } }
155+
}
156+
157+
stage('Unpack') {
158+
steps { timeout(5) { script { dir('test/e2e') {
159+
sh 'mkdir aut'
160+
sh "7z x '${utils.findFile('pkg/*.7z')}' -o'./aut'"
161+
env.AUT_PATH = utils.findFile('aut/Status/bin/Status.exe').replace('\\','/')
162+
} } } }
163+
}
164+
165+
stage('Test') {
166+
steps {
167+
timeout(time: getTestStageTimeout()) {
168+
dir('test/e2e') {
169+
script {
170+
def flags = []
171+
if (params.TEST_NAME) { flags.add("-k=${params.TEST_NAME}") }
172+
if (params.TEST_SCOPE_FLAG) { flags.add(params.TEST_SCOPE_FLAG) }
173+
if (params.LOG_LEVEL) { flags.addAll(["--log-level=${params.LOG_LEVEL}", "--log-cli-level=${params.LOG_LEVEL}"]) }
174+
def flagStr = flags.join(' ')
175+
176+
withCredentials([
177+
usernamePassword(credentialsId: 'test-rail-api-devops', usernameVariable: 'TESTRAIL_USR', passwordVariable: 'TESTRAIL_PSW'),
178+
string(credentialsId: 'wallet-test-user-seed', variable: 'WALLET_TEST_USER_SEED')
179+
]) {
180+
sh"""
181+
pushd configs
182+
ln -sf _local.ci.py _local.py || cp _local.ci.py _local.py
183+
popd
184+
185+
"""
186+
bat"""
187+
python310 -m pytest -m "not keycard" -v --reruns=1 --timeout=300 ${flagStr} --disable-warnings --alluredir=./allure-results -o timeout_func_only=true
188+
"""
189+
}
190+
}
191+
}
192+
}
193+
}
194+
}
195+
}
196+
197+
post {
198+
always { script { dir('test/e2e') {
199+
archiveArtifacts('aut/Status/bin/*.log')
200+
201+
/* Needed to categorize types of errors and add environment section in allure report. */
202+
sh 'cp ext/allure_files/categories.json allure-results'
203+
sh 'cp ext/allure_files/environment.properties allure-results'
204+
205+
allure([
206+
results: [[path: 'allure-results']],
207+
reportBuildPolicy: 'ALWAYS',
208+
properties: [],
209+
jdk: '',
210+
])
211+
/* Link for Jenkins Builds GitHub comment. */
212+
env.PKG_URL = "${env.BUILD_URL}allure/"
213+
updateGitHubStatus()
214+
} } }
215+
success { script {
216+
github.notifyPR(true)
217+
} }
218+
failure { script {
219+
github.notifyPR(false)
220+
discord.send(
221+
header: '**Desktop E2E test failure!**',
222+
cred: 'discord-status-desktop-e2e-webhook',
223+
)
224+
} }
225+
cleanup { cleanWs(disableDeferredWipeout: true) }
226+
}
227+
}
228+
229+
def setNewBuildName() {
230+
if (currentBuild.upstreamBuilds) {
231+
def parent = utils.parentOrCurrentBuild()
232+
currentBuild.displayName = parent.getFullDisplayName().minus('status-desktop » ')
233+
}
234+
}
235+
236+
def setBuildDescFromFile(fileNameOrPath) {
237+
def tokens = utils.parseFilename(utils.baseName(fileNameOrPath))
238+
if (tokens == null) { /* Fallback for regex fail. */
239+
currentBuild.description = utils.baseName(fileNameOrPath)
240+
return
241+
}
242+
if (tokens.build && tokens.build.startsWith('pr')) {
243+
currentBuild.displayName = tokens.build.replace(/^pr/, 'PR-')
244+
}
245+
currentBuild.description = formatMap([
246+
Node: NODE_NAME,
247+
Build: tokens.build,
248+
Commit: tokens.commit,
249+
Version: (tokens.tstamp ?: tokens.version),
250+
])
251+
}
252+
253+
def updateGitHubStatus() {
254+
/* For PR builds update check status. */
255+
if (params.BUILD_SOURCE ==~ /.*\/PR-[0-9]+\/?$/) {
256+
github.statusUpdate(
257+
context: 'jenkins/prs/tests/e2e-new.windows',
258+
commit: jenkins.getJobCommitByPath(params.BUILD_SOURCE),
259+
repo_url: 'https://github.com/status-im/status-desktop'
260+
)
261+
}
262+
}
263+
264+
def formatMap(Map data=[:]) {
265+
def text = ''
266+
data.each { key, val -> text += "<b>${key}</b>: ${val}</a><br>\n" }
267+
return text
268+
}
269+
270+
def getDefaultBuildSource() {
271+
return ''
272+
}
273+
274+
def getDefaultTestScopeFlag() {
275+
if (JOB_NAME == "status-desktop/systems/windows/x86_64/tests-e2e") {
276+
return ''
277+
} else {
278+
return '-m=critical'
279+
}
280+
}
281+
282+
def getTestStageTimeout() { params.TEST_SCOPE_FLAG == '-m=critical' ? 30 : 120 }

ci/Jenkinsfile.windows

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pipeline {
7373
QTDIR = "/c/Qt/6.9.2/msvc2022_64"
7474
PATH = "${env.QTDIR}/bin:${goPath()}/bin:${env.PATH}"
7575
/* Avoid weird bugs caused by stale cache. */
76-
QML_DISABLE_DISK_CACHE = "true"
76+
QML_DISABLE_DISK_CACHE = 1
7777
/* Control output the filename */
7878
VERSION = sh(script: "./scripts/version.sh", returnStdout: true).trim()
7979
STATUS_CLIENT_EXE = "pkg/${utils.pkgFilename(ext: 'exe', arch: getArch(), version: env.VERSION)}"
@@ -149,6 +149,21 @@ pipeline {
149149
jenkins.setBuildDesc(Zip: zip_url, Exe: exe_url)
150150
} }
151151
}
152+
153+
154+
stage('E2E') {
155+
when { expression { utils.isPRBuild() } }
156+
steps { script {
157+
build(
158+
job: 'status-desktop/e2e/prs-windows',
159+
wait: false,
160+
parameters: jenkins.mapToParams([
161+
GIT_REF: env.GIT_COMMIT,
162+
BUILD_SOURCE: env.JOB_NAME,
163+
]),
164+
)
165+
} }
166+
}
152167
}
153168
post {
154169
success { script { github.notifyPR(true) } }

test/e2e/configs/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
if AUT_PATH is None:
2121
exit('Please add "AUT_PATH" in ./configs/_local.py')
22-
if get_platform() == "Windows" and 'bin' not in AUT_PATH:
23-
exit('Please use launcher from "bin" folder in "AUT_PATH"')
22+
if get_platform() == "Windows" and 'Status' not in AUT_PATH:
23+
exit('Please use launcher from "Status" folder in "AUT_PATH"')
2424
AUT_PATH = SystemPath(AUT_PATH)
2525
WALLET_SEED = os.getenv('WALLET_TEST_USER_SEED')
2626

0 commit comments

Comments
 (0)