From 271bcd014f7a7217e9bef582bee985a8c53d5493 Mon Sep 17 00:00:00 2001 From: Vedran <82972815+mendelskiv93@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:49:26 +0200 Subject: [PATCH] chore(@e2e): use local waku fleet for linux E2E tests (#20215) * chore(@e2e): use local waku fleet for E2E tests Start local waku nodes via docker-compose before running E2E tests and configure the app to use them instead of status.prod. This avoids skewing production metrics, adding unnecessary load to prod hosts, and generating noise in prod storage DBs. - https://github.com/status-im/status-app/issues/20126 - https://github.com/status-im/status-go//tree/feat/fleet-override * fix(@e2e): use host networking for local waku nodes Switch docker-compose to network_mode:host so waku nodes bind directly to localhost. Fixes ENR multiaddr containing Docker internal hostnames/IPs unreachable by the app. - Remove dns4-domain-name (caused Docker hostname in ENR) - Use /ip4/127.0.0.1 for staticnode references - Separate discv5 UDP ports (9000/9001 - Enable REST API for proper healthchecks - Update fleet config JSON with correct DNS ENRs and store addr * chore(@e2e): remove status community link from tests --------- Co-authored-by: Anastasiya --- assets/local-waku-fleets-config.json | 37 +++--- ci/Jenkinsfile.tests-e2e | 50 ++++++--- ci/tests.Dockerfile | 2 + docker-compose.waku.yml | 106 +++++++++++++----- test/e2e/constants/links.py | 4 +- .../test_messaging_group_chat.py | 20 +--- 6 files changed, 141 insertions(+), 78 deletions(-) diff --git a/assets/local-waku-fleets-config.json b/assets/local-waku-fleets-config.json index 6943a5681a..957c6eb68f 100644 --- a/assets/local-waku-fleets-config.json +++ b/assets/local-waku-fleets-config.json @@ -1,16 +1,25 @@ { - "status-desktop.test": { - "clusterId": 16, - "wakuNodes": [ - "enr:-La4QPTs3q_umVW06q5r1a3pmnG0ahbvDJCyccAqwQxBSvbGcQAlsWokcsqWyfPABqowZHvJ1YIzVcLy1GZ1T0bQ3wgBgmlkgnY0gmlwhH8AAAGKbXVsdGlhZGRyc40ACzYGYm9vdC0xBuphgnJzhwAQAgAgAECJc2VjcDI1NmsxoQOGH0cGbQrDKGJKZUReERKxvaIcSk_pZ3lILaIL90iZAoN0Y3CC6mGDdWRwgiMohXdha3UyDQ" - ], - "discV5BootstrapNodes": [], - "storeNodes": [ - { - "id": "store-1", - "enr": "enr:-LW4QP-PB5tg4cTQB2FvYFhPu3yG9jilownIJmz5w8DvMZZOWBWWLHv3jCr88xUjLxr_Cei3-YzsmKhkQJBexiuRSpEBgmlkgnY0gmlwhH8AAAGKbXVsdGlhZGRyc4wACjYFc3RvcmUG6mKCcnOHABACACAAQIlzZWNwMjU2azGhAo3JozGxzJ2AeSAtgU0YzmxURKi6sveikwnF2cvZAhY1g3RjcILqYoN1ZHCCIyiFd2FrdTID", - "fleet": "status-desktop.test" - } - ] - } + "status-app.test": { + "clusterId": 16, + "wakuNodes": [ + "enr:-K-4QCaLys0F9CWHiXr9igN3oYGf3iWW-S444Xt49rCTpyiQQwMyfjCX52UeXPVG8vPGSSkP0mISMw-an-0HMhlZ-C4BgmlkgnY0gmlwhH8AAAGKbXVsdGlhZGRyc4CCcnONABAFAAEAIABAAIABAIlzZWNwMjU2azGhA4YfRwZtCsMoYkplRF4RErG9ohxKT-lneUgtogv3SJkCg3RjcILqYYN1ZHCCv2iFd2FrdTIN" + ], + "discV5BootstrapNodes": [ + "enr:-K-4QCaLys0F9CWHiXr9igN3oYGf3iWW-S444Xt49rCTpyiQQwMyfjCX52UeXPVG8vPGSSkP0mISMw-an-0HMhlZ-C4BgmlkgnY0gmlwhH8AAAGKbXVsdGlhZGRyc4CCcnONABAFAAEAIABAAIABAIlzZWNwMjU2azGhA4YfRwZtCsMoYkplRF4RErG9ohxKT-lneUgtogv3SJkCg3RjcILqYYN1ZHCCv2iFd2FrdTIN" + ], + "storeNodes": [ + { + "id": "store-1", + "enr": "enr:-K-4QI3LQZZaLyS6kA5lvmIcroksqNBZ1fRozAT9t_3yBVT6Vu5VHeNKa9u4eST4yGJ7M8K7Py53ZH7Zb6S6g2WbFrUBgmlkgnY0gmlwhH8AAAGKbXVsdGlhZGRyc4CCcnONABAFAAEAIABAAIABAIlzZWNwMjU2azGhAo3JozGxzJ2AeSAtgU0YzmxURKi6sveikwnF2cvZAhY1g3RjcILqYoN1ZHCCv2mFd2FrdTID", + "addr": "/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAm4y9o3GARfphq8jN1wsVhezCHPMmRuekHCCKJ1EsgzVBi", + "fleet": "status-desktop.test" + }, + { + "id": "store-2", + "enr": "enr:-K-4QP3hbp7CDP7Gn6NuVAtrrYRdqIiq-vX-Ofp-DY3UiRehM1kY2irkHLCfrTMQAwU8imS2A1SSPDV6pIvDrnRsJFABgmlkgnY0gmlwhH8AAAGKbXVsdGlhZGRyc4CCcnONABAFAAEAIABAAIABAIlzZWNwMjU2azGhAl0GSz7dmpanBV_zsW3Jwlp4CAf7-Vh2SMU4-NZt23Cpg3RjcILqY4N1ZHCCv2qFd2FrdTID", + "addr": "/ip4/127.0.0.1/tcp/60003/p2p/16Uiu2HAm1goTmM1zjARKFw82u71Zxhj5gvQDXPFEPW9xea4Zt6dv", + "fleet": "status-desktop.test" + } + ] } +} \ No newline at end of file diff --git a/ci/Jenkinsfile.tests-e2e b/ci/Jenkinsfile.tests-e2e index dd1d3ee2ad..f3c30cf40f 100644 --- a/ci/Jenkinsfile.tests-e2e +++ b/ci/Jenkinsfile.tests-e2e @@ -110,6 +110,10 @@ pipeline { /* Set to a non-zero value to make Qt print out diagnostic information about the each (C++) plugin it tries to load. */ /* QT_DEBUG_PLUGINS = 0 */ + /* Use local waku fleet */ + STATUS_FLEET = 'status-app.test' + STATUS_FLEET_CONFIG_FILE = "${WORKSPACE}/assets/local-waku-fleets-config.json" + /* Hack fix for params not being set in job on first run */ BUILD_SOURCE = "${params.BUILD_SOURCE}" TEST_NAME = "${params.TEST_NAME}" @@ -182,6 +186,15 @@ pipeline { } } } } } + stage('Start Local Fleet') { + steps { timeout(2) { script { + /* Clean up any leftover containers from a previous aborted run */ + sh 'docker compose -f docker-compose.waku.yml down || true' + sh 'docker compose -f docker-compose.waku.yml up -d' + sh 'sleep 15' + } } } + } + stage('Test') { steps { timeout(getTestStageTimeout()) { script { dir('test/e2e') { def flags = [] @@ -219,23 +232,28 @@ pipeline { } post { - always { script { dir('test/e2e') { - archiveArtifacts('aut/*.log') + always { script { + /* Stop local waku fleet */ + sh 'docker compose -f docker-compose.waku.yml down --remove-orphans || true' - /* 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' + dir('test/e2e') { + archiveArtifacts('aut/*.*') - allure([ - results: [[path: 'allure-results']], - reportBuildPolicy: 'ALWAYS', - properties: [], - jdk: '', - ]) - /* Link for Jenkins Builds GitHub comment. */ - env.PKG_URL = "${env.BUILD_URL}allure/" - updateGitHubStatus() - } } } + /* 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: '', + ]) + /* Link for Jenkins Builds GitHub comment. */ + env.PKG_URL = "${env.BUILD_URL}allure/" + updateGitHubStatus() + } + } } success { script { github.notifyPR(true) } } @@ -313,4 +331,4 @@ def getAgentLabel() { return "linuxcontainer && ${params.AGENT_NODE}" } return 'linuxcontainer' -} +} \ No newline at end of file diff --git a/ci/tests.Dockerfile b/ci/tests.Dockerfile index cdd56dc57c..86e8173ec4 100644 --- a/ci/tests.Dockerfile +++ b/ci/tests.Dockerfile @@ -22,6 +22,8 @@ RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor --ba pcscd \ && apt-get clean && rm -rf /var/lib/apt/lists/* +RUN groupadd -g 999 docker && usermod -aG docker jenkins + USER jenkins LABEL maintainer="marko@status.im" diff --git a/docker-compose.waku.yml b/docker-compose.waku.yml index 4d4b08f907..9877ae70dc 100644 --- a/docker-compose.waku.yml +++ b/docker-compose.waku.yml @@ -1,67 +1,119 @@ services: boot-1: - image: wakuorg/nwaku:v0.34.0 + image: wakuorg/nwaku:v0.36.0 + network_mode: host entrypoint: [ "/usr/bin/wakunode", "--discv5-discovery=true", "--discv5-enr-auto-update=True", - "--discv5-udp-port=9000", + "--discv5-udp-port=49000", "--cluster-id=16", - # Docker DNS server - "--dns-addrs-name-server=127.0.0.11", - "--dns4-domain-name=boot-1", + "--num-shards-in-network=0", "--filter=true", "--keep-alive=true", "--lightpush=true", - "--log-level=DEBUG", + "--log-level=INFO", "--max-connections=18000", + "--max-msg-size=1024KiB", + "--ip-colocation-limit=100", "--nodekey=697b008f979c8ae38c1e4e0b9bc3712dd39e2355f49eaf6c63d92f7edd13704d", "--peer-exchange=true", "--relay=true", -# "--rest-address=0.0.0.0", -# "--rest-admin", + "--rest-address=0.0.0.0", + "--rest-admin", + "--rest-port=8645", + "--shard=1", "--shard=32", "--shard=64", - "--staticnode=/dns4/store/tcp/60002/p2p/16Uiu2HAm4y9o3GARfphq8jN1wsVhezCHPMmRuekHCCKJ1EsgzVBi", - "--storenode=/dns4/store/tcp/60002/p2p/16Uiu2HAm4y9o3GARfphq8jN1wsVhezCHPMmRuekHCCKJ1EsgzVBi", + "--shard=128", + "--shard=256", + "--staticnode=/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAm4y9o3GARfphq8jN1wsVhezCHPMmRuekHCCKJ1EsgzVBi", + "--storenode=/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAm4y9o3GARfphq8jN1wsVhezCHPMmRuekHCCKJ1EsgzVBi", "--tcp-port=60001", "--nat=extip:127.0.0.1", ] - depends_on: - - store - ports: - - "60001:60001" healthcheck: - test: ["CMD-SHELL", "curl -X GET -H 'Content-Type: application/json' http://127.0.0.1:8645 || exit 0"] + test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8645/debug/v1/info || exit 1"] + interval: 5s + timeout: 3s + retries: 10 store: - image: wakuorg/nwaku:v0.34.0 + image: wakuorg/nwaku:v0.36.0 + network_mode: host entrypoint: [ "/usr/bin/wakunode", "--discv5-discovery=true", "--discv5-enr-auto-update=True", - "--discv5-udp-port=9000", + "--discv5-udp-port=49001", "--cluster-id=16", - # Docker DNS server - "--dns-addrs-name-server=127.0.0.11", - "--dns4-domain-name=store", + "--num-shards-in-network=0", "--keep-alive=true", - "--log-level=DEBUG", + "--log-level=INFO", + "--legacy-store=true", "--max-connections=18000", + "--max-msg-size=1024KiB", + "--ip-colocation-limit=100", "--nodekey=ba4e531d4ef543fabd838ef4e731d35dfa4deceea8f4a5992ad7f29764c70035", "--peer-exchange=false", "--relay=true", -# "--rest-address=0.0.0.0", -# "--rest-admin", + "--rest-address=0.0.0.0", + "--rest-admin", + "--rest-port=8646", + "--shard=1", "--shard=32", "--shard=64", - "--staticnode=/dns4/boot-1/tcp/60001/p2p/16Uiu2HAmMgYeJrjruJGCgL96aaP2nf85PGsRVkXLyhG2joJMH4pH", + "--shard=128", + "--shard=256", + "--staticnode=/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmMgYeJrjruJGCgL96aaP2nf85PGsRVkXLyhG2joJMH4pH", "--store=true", + "--store-message-db-url=sqlite:///tmp/store1.db", + "--store-message-retention-policy=time:86400", "--tcp-port=60002", "--nat=extip:127.0.0.1", ] - ports: - - "60002:60002" healthcheck: - test: ["CMD-SHELL", "curl -X GET -H 'Content-Type: application/json' http://127.0.0.1:8645 || exit 0"] + test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8646/debug/v1/info || exit 1"] + interval: 5s + timeout: 3s + retries: 10 + store-2: + image: wakuorg/nwaku:v0.36.0 + network_mode: host + entrypoint: [ + "/usr/bin/wakunode", + "--discv5-discovery=true", + "--discv5-enr-auto-update=True", + "--discv5-udp-port=49002", + "--cluster-id=16", + "--num-shards-in-network=0", + "--keep-alive=true", + "--log-level=INFO", + "--legacy-store=true", + "--max-connections=18000", + "--max-msg-size=1024KiB", + "--ip-colocation-limit=100", + "--nodekey=c2a4e44652cd44b2b73093e7d2dba0a1e841e24e59db4a3a8c8e660e6e4d1b3a", + "--peer-exchange=false", + "--relay=true", + "--rest-address=0.0.0.0", + "--rest-admin", + "--rest-port=8647", + "--shard=1", + "--shard=32", + "--shard=64", + "--shard=128", + "--shard=256", + "--staticnode=/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmMgYeJrjruJGCgL96aaP2nf85PGsRVkXLyhG2joJMH4pH", + "--store=true", + "--store-message-db-url=sqlite:///tmp/store2.db", + "--store-message-retention-policy=time:86400", + "--tcp-port=60003", + "--nat=extip:127.0.0.1", + ] + healthcheck: + test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8647/debug/v1/info || exit 1"] + interval: 5s + timeout: 3s + retries: 10 \ No newline at end of file diff --git a/test/e2e/constants/links.py b/test/e2e/constants/links.py index 49321fefbe..f33a18fe7d 100644 --- a/test/e2e/constants/links.py +++ b/test/e2e/constants/links.py @@ -1,6 +1,4 @@ # Links for link preview tests external_link = 'https://github.com/status-im/status-app' -link_to_status_community = 'https://status.app/c/G4IAAMSIuU08Lm3oHzSz695ImidijVBxyoFDGEiSYAvADsk9ZVOKYlT2b' \ - '-lHStyz1MqqkK2Xa4FwoUiq3LBgWsYI_ht6hWXCyLu0TGAk0dGu8IyQWtDSdIXOQ3hWscLjkTo5Vg5' \ - '-eyUuV8jOVv7khJ_uTofT_TijN-sB#zQ3shZeEJqTC1xhGUjxuS4rtHSrhJ8vUYp64v6qWkLpvdy9L9' + diff --git a/test/e2e/tests/crtitical_tests_prs/test_messaging_group_chat.py b/test/e2e/tests/crtitical_tests_prs/test_messaging_group_chat.py index 72fd5c5eec..4f3217bada 100644 --- a/test/e2e/tests/crtitical_tests_prs/test_messaging_group_chat.py +++ b/test/e2e/tests/crtitical_tests_prs/test_messaging_group_chat.py @@ -1,20 +1,19 @@ import random import string -import allure import pytest from allure_commons._allure import step import driver from configs import get_platform -from constants.links import external_link, link_to_status_community +from constants.links import external_link import configs.testpath from constants import UserAccount, RandomUser from constants.messaging import Messaging from helpers.chat_helper import skip_message_backup_popup_if_visible from helpers.multiple_instances_helper import ( - authorize_user_in_aut, get_chat_key, send_contact_request_from_settings, switch_to_aut + authorize_user_in_aut, get_chat_key, switch_to_aut ) from gui.main_window import MainWindow from gui.screens.messages import MessagesScreen @@ -253,21 +252,6 @@ def test_group_chat_add_contact_in_ac(multiple_instances, community_name, domain lambda: domain_link_2 == messages_screen.chat.messages(0)[0].get_link_domain(), configs.timeouts.UI_LOAD_TIMEOUT_MSEC) - with step(f'Paste link to status community'): - message_community = link_to_status_community - messages_screen.group_chat.type_message(message_community) - - with step('Verify title and subtitle of preview are correct and close button exists'): - assert driver.waitFor( - lambda: community_name == messages_screen.group_chat.get_link_preview_bubble_title(), - configs.timeouts.APP_LOAD_TIMEOUT_MSEC) - assert driver.waitFor( - lambda: domain_link == messages_screen.group_chat.get_link_preview_bubble_description(), - configs.timeouts.UI_LOAD_TIMEOUT_MSEC) - - with step('Close link preview options popup and send a message'): - messages_screen.group_chat.confirm_sending_message() - with step(f'Paste link to user profile link and send message'): message_user = profile_link messages_screen.group_chat.type_message(message_user)