diff --git a/.clabot b/.clabot new file mode 100644 index 0000000..9278130 --- /dev/null +++ b/.clabot @@ -0,0 +1,3 @@ +{ + "contributors": "https://api.infrasonar.com/contributors" +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57c0da4..4f4f754 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,31 +1,29 @@ -permissions: - contents: read name: CI on: push: branches: - - main + - main pull_request: branches: - - main + - main jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.12 - uses: actions/setup-python@v5 - with: - python-version: 3.12 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pytest pycodestyle pyright - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Lint with PyCodeStyle - run: | - find . -name \*.py -exec pycodestyle {} + - - name: Type checking with PyRight - run: | - pyright \ No newline at end of file + - uses: actions/checkout@v6 + - name: Set up Python 3.14 + uses: actions/setup-python@v6 + with: + python-version: 3.14 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest pycodestyle pyright + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with PyCodeStyle + run: | + find . -name \*.py -exec pycodestyle {} + + - name: Type checking with PyRight + run: | + pyright diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5846fde..cce616a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -18,10 +18,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Log in to the Container registry - uses: docker/login-action@v2 + uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -29,7 +29,7 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v6 with: images: ${{ env.REGISTRY }}/infrasonar/selenium-probe @@ -38,7 +38,7 @@ jobs: run: echo "VERSION=$(echo $GITHUB_REF | cut -d / -f 3)" >> $GITHUB_OUTPUT - name: Build and push Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v7 env: PAT: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ad100de..9a6aed8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,10 +19,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Log in to the Container registry - uses: docker/login-action@v2 + uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -30,7 +30,7 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v6 with: images: ${{ env.REGISTRY }}/infrasonar/selenium-probe @@ -39,7 +39,7 @@ jobs: run: echo "VERSION=$(echo $GITHUB_REF | cut -d / -f 3)" >> $GITHUB_OUTPUT - name: Build and push Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v7 env: PAT: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/Dockerfile b/Dockerfile index b1c66ea..529b9b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/infrasonar/python:3.12.9 +FROM ghcr.io/infrasonar/python:3.14.3 ADD . /code WORKDIR /code RUN pip install --no-cache-dir -r requirements.txt diff --git a/lib/check/selenium.py b/lib/check/selenium.py index c4af994..5ef8607 100644 --- a/lib/check/selenium.py +++ b/lib/check/selenium.py @@ -2,6 +2,7 @@ import asyncio from selenium import webdriver from libprobe.asset import Asset +from libprobe.check import Check from libprobe.exceptions import IncompleteResultException, Severity from ..module import get_module @@ -10,70 +11,74 @@ COMMAND_EXECUTER = os.getenv("COMMAND_EXECUTER", "http://localhost:4444") -async def check_selenium( - asset: Asset, - asset_config: dict, - config: dict) -> dict: - exc = None - items = [] - password = asset_config.get('password') - secret = asset_config.get('secret') - file_ids: list[int] = config.get('file_ids', []) - for file_id in file_ids: - async with _lock: - if password: - os.environ['PASSWORD'] = password - if secret: - os.environ['SECRET'] = secret - try: - try: - module = await get_module(file_id=file_id) - except Exception as e: - exc = e - continue +class CheckSelenium(Check): + key = 'selenium' + unchanged_eol = 0 - options = webdriver.ChromeOptions() - driver = webdriver.Remote( - options=options, - command_executor=COMMAND_EXECUTER) + @staticmethod + async def run(asset: Asset, local_config: dict, config: dict) -> dict: + exc = None + items = [] + password = local_config.get('password') + secret = local_config.get('secret') + file_ids: list[int] = config.get('file_ids', []) + for file_id in file_ids: + async with _lock: + if password: + os.environ['PASSWORD'] = password + if secret: + os.environ['SECRET'] = secret try: - item = module.export.run(name=str(file_id), driver=driver) - except Exception as e: - # When `run() is correct, it can't fail` as potential - # errors will be part of the result - msg = str(e) or type(e).__name__ - raise Exception( - f'The `export` in file ID {file_id} is not a valid ' - f'subclass of `TestBase` (error: {msg})') - else: - item['file_id'] = file_id # int - items.append(item) - finally: - os.environ.pop('PASSWORD', None) - os.environ.pop('SECRET', None) + try: + module = await get_module(file_id=file_id) + except Exception as e: + exc = e + continue + + options = webdriver.ChromeOptions() + driver = webdriver.Remote( + options=options, + command_executor=COMMAND_EXECUTER) + + try: + item = module.export.run(name=str(file_id), + driver=driver) + except Exception as e: + # When `run() is correct, it can't fail` as potential + # errors will be part of the result + msg = str(e) or type(e).__name__ + raise Exception( + f'The `export` in file ID {file_id} is not a valid' + f' subclass of `TestBase` (error: {msg})') + else: + item['file_id'] = file_id # int + items.append(item) + finally: + os.environ.pop('PASSWORD', None) + os.environ.pop('SECRET', None) - if exc is not None and not items: - raise exc + if exc is not None and not items: + raise exc - total = { - 'name': 'total', # str - 'success_count': sum(i['success'] for i in items), # int - 'failed_count': sum(not i['success'] for i in items), # int - 'num_checks': len(items), # int - 'total_duration': sum(i['duration'] for i in items), # float - } + total = { + 'name': 'total', # str + 'success_count': sum(i['success'] for i in items), # int + 'failed_count': sum(not i['success'] for i in items), # int + 'num_checks': len(items), # int + 'total_duration': sum(i['duration'] for i in items), # float + } - state = { - 'total': [total], # single item - 'tests': items, # multi item - } + state = { + 'total': [total], # single item + 'tests': items, # multi item + } - if exc is not None: - msg = str(exc) or type(exc).__name__ - raise IncompleteResultException( - msg=msg, - result=state, - severity=Severity.LOW) + if exc is not None: + msg = str(exc) or type(exc).__name__ + raise IncompleteResultException( + msg=msg, + result=state, + severity=Severity.LOW) - return state + return state diff --git a/lib/module.py b/lib/module.py index 1bfbd2b..bb45f26 100644 --- a/lib/module.py +++ b/lib/module.py @@ -5,7 +5,7 @@ # Function to dynamically import a module given its full path -def import_module_from_path(path): +def import_module_from_path(path: str): # Create a module spec from the given path spec = importlib.util.spec_from_file_location("module_name", path) if spec is None or spec.loader is None: diff --git a/main.py b/main.py index e613204..8595db7 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,12 @@ from libprobe.probe import Probe -from lib.check.selenium import check_selenium +from lib.check.selenium import CheckSelenium from lib.version import __version__ as version from lib.probe import register_probe if __name__ == '__main__': - checks = { - 'selenium': check_selenium - } + checks = ( + CheckSelenium, + ) probe = Probe("selenium", version, checks) register_probe(probe) diff --git a/requirements.txt b/requirements.txt index 158088f..78889c7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -libprobe==1.0.1 +libprobe==2.0.6 infrasonar_selenium==1.0.2