Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion testit-adapter-behave/setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup

VERSION = "4.2.2"
VERSION = "4.2.3"

setup(
name='testit-adapter-behave',
Expand Down
2 changes: 1 addition & 1 deletion testit-adapter-nose/setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

VERSION = "4.2.2"
VERSION = "4.2.3"

setup(
name='testit-adapter-nose',
Expand Down
2 changes: 1 addition & 1 deletion testit-adapter-pytest/setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup

VERSION = "4.2.2"
VERSION = "4.2.3"

setup(
name='testit-adapter-pytest',
Expand Down
2 changes: 1 addition & 1 deletion testit-adapter-robotframework/setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup

VERSION = "4.2.2"
VERSION = "4.2.3"

setup(
name='testit-adapter-robotframework',
Expand Down
4 changes: 2 additions & 2 deletions testit-python-commons/setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup

VERSION = "4.2.2"
VERSION = "4.2.3"

setup(
name='testit-python-commons',
Expand All @@ -25,5 +25,5 @@
py_modules=['testit', 'testit_python_commons'],
packages=find_packages(where='src'),
package_dir={'': 'src'},
install_requires=['pluggy', 'tomli', 'testit-api-client==7.5.6']
install_requires=['pluggy', 'tomli', 'testit-api-client==7.5.10']
)
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
TestRunV2ApiResult,
LinkAutoTestToWorkItemRequest,
AutoTestWorkItemIdentifierApiResult,
ProjectModel,
WorkflowApiResult,
)

Expand Down Expand Up @@ -547,7 +546,7 @@ def get_configuration_id(self):

@adapter_logger
@retry
def __get_project(self) -> ProjectModel:
def __get_project(self):
return self.__projects_api.get_project_by_id(id=self.__config.get_project_id())

@adapter_logger
Expand All @@ -557,7 +556,7 @@ def __get_workflow_by_id(self, workflow_id: str) -> WorkflowApiResult:

@adapter_logger
def __get_status_codes(self) -> List[str]:
project: ProjectModel = self.__get_project()
workflow: WorkflowApiResult = self.__get_workflow_by_id(project.workflow_id)
project = self.__get_project()
workflow = self.__get_workflow_by_id(project.workflow_id)

return [status.code for status in workflow.statuses]
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import logging
import os
import platform
Expand Down Expand Up @@ -39,13 +40,15 @@ class SyncStorageRunner:
across multiple workers.
"""

SYNC_STORAGE_VERSION = "v0.3.2"
SYNC_STORAGE_VERSION = "v0.3.3"
SYNC_STORAGE_REPO_URL = (
"https://github.com/testit-tms/sync-storage-public/releases/download/"
)
AMD64 = "amd64"
ARM64 = "arm64"
SYNC_STORAGE_STARTUP_TIMEOUT = 5 # seconds
KEEP_ALIVE_INTERVAL_SECONDS = 30
KEEP_ALIVE_REQUEST_TIMEOUT_SECONDS = 5

def __init__(
self,
Expand Down Expand Up @@ -82,6 +85,9 @@ def __init__(
self.workers_api: Optional[WorkersApi] = None
self.test_results_api: Optional[TestResultsApi] = None

self._keep_alive_stop_event = threading.Event()
self._keep_alive_thread: Optional[threading.Thread] = None

logger.debug(
f"Initialized SyncStorageRunner with test_run_id={test_run_id}, port={self.port}"
)
Expand Down Expand Up @@ -113,6 +119,7 @@ def start(self) -> bool:
except Exception as e:
logger.error(f"Error registering worker: {e}")

self._start_keep_alive()
return True

# Get executable file name for current platform
Expand Down Expand Up @@ -170,6 +177,7 @@ def start(self) -> bool:
except Exception as e:
logger.error(f"Error registering worker: {e}")

self._start_keep_alive()
return True
else:
raise RuntimeError("Cannot start the SyncStorage until timeout")
Expand Down Expand Up @@ -213,6 +221,49 @@ def get_url(self) -> str:
"""Get the Sync Storage URL."""
return f"http://localhost:{self.port}"

def _keep_alive(self) -> None:
try:
payload = json.dumps({
"pid": self.worker_pid,
"testRunId": self.test_run_id,
}).encode("utf-8")
request = urllib.request.Request(
f"{self.get_url()}/keep_alive",
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
urllib.request.urlopen(
request,
timeout=self.KEEP_ALIVE_REQUEST_TIMEOUT_SECONDS,
)
except Exception:
pass

def _keep_alive_loop(self) -> None:
while not self._keep_alive_stop_event.is_set():
self._keep_alive()
if self._keep_alive_stop_event.wait(self.KEEP_ALIVE_INTERVAL_SECONDS):
break

def _start_keep_alive(self) -> None:
if self._keep_alive_thread and self._keep_alive_thread.is_alive():
return

self._keep_alive_stop_event.clear()
self._keep_alive_thread = threading.Thread(
target=self._keep_alive_loop,
name="sync-storage-keep-alive",
daemon=True,
)
self._keep_alive_thread.start()
logger.debug("Sync Storage keep-alive thread started")

def _stop_keep_alive(self) -> None:
self._keep_alive_stop_event.set()
if self._keep_alive_thread and self._keep_alive_thread.is_alive():
self._keep_alive_thread.join(timeout=1)

def send_in_progress_test_result(
self, model: TestResultCutApiModel
) -> bool:
Expand Down
41 changes: 41 additions & 0 deletions testit-python-commons/tests/services/test_sync_storage_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import json
from unittest.mock import MagicMock, patch

from testit_python_commons.services.sync_storage.sync_storage_runner import SyncStorageRunner


class TestSyncStorageKeepAlive:
def test_keep_alive_posts_expected_payload(self):
runner = SyncStorageRunner(
test_run_id="run-id",
port="49152",
)
runner.worker_pid = "worker-1"

with patch("urllib.request.urlopen") as urlopen_mock:
runner._keep_alive()

urlopen_mock.assert_called_once()
request = urlopen_mock.call_args[0][0]
assert request.full_url == "http://localhost:49152/keep_alive"
assert request.method == "POST"
assert json.loads(request.data.decode("utf-8")) == {
"pid": "worker-1",
"testRunId": "run-id",
}

def test_keep_alive_ignores_errors(self):
runner = SyncStorageRunner(test_run_id="run-id", port="49152")

with patch("urllib.request.urlopen", side_effect=OSError("down")):
runner._keep_alive()

def test_start_keep_alive_starts_background_thread(self):
runner = SyncStorageRunner(test_run_id="run-id", port="49152")

with patch.object(runner, "_keep_alive_loop") as loop_mock:
runner._start_keep_alive()
runner._keep_alive_stop_event.set()
runner._keep_alive_thread.join(timeout=1)

loop_mock.assert_called_once()
4 changes: 2 additions & 2 deletions update_versions.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

NEW_VERSION="4.2.2"
TESTIT_API_CLIENT_VERSION="7.5.6"
NEW_VERSION="4.2.3"
TESTIT_API_CLIENT_VERSION="7.5.10"

echo "Updating all adapters to version: $NEW_VERSION"
echo "Updating testit-api-client to version: $TESTIT_API_CLIENT_VERSION"
Expand Down
Loading