+"""Test runner module for ONAP Python SDK tests."""
import configparser
import importlib
import importlib.util
import sys
import glob
+from opentelemetry import trace
from onapsdk.exceptions import ModuleError
import onaptests.utils.exceptions as onap_test_exceptions
+tracer = trace.get_tracer(__name__)
+
SETTING_FILE_EXCEPTIONS = {
"clearwater_ims": "clearwater_ims_nomulticloud_settings",
"basic_cnf": "basic_cnf_yaml_settings",
"onaptests"
]
+
def get_entrypoints():
+ """Get entry points from setup.cfg."""
config = configparser.ConfigParser()
config.read('setup.cfg')
entry_points = config['options.entry_points']['xtesting.testcase']
}
return entry_points_result
+
def check_scenarios(scenarios, entry_points):
+ """Check that all scenarios are registered in entry points."""
path = importlib.util.find_spec(scenarios.__name__).submodule_search_locations
modules = glob.glob(f"{path._path[0]}/*.py")
- all_mods = [ os.path.basename(f)[:-3] for f in modules if os.path.isfile(f) and not f.endswith('__init__.py')]
+ all_mods = [os.path.basename(f)[:-3] for f in modules if os.path.isfile(f) and not f.endswith('__init__.py')]
for mod_name in all_mods:
full_mod_name = f"{scenarios.__name__}.{mod_name}"
if mod_name != "scenario_base":
raise onap_test_exceptions.TestConfigurationException(
f"Scenario defined in {full_mod_name}.py is not added to setup.cfg file")
+
def run_test(test_name, validation, force_cleanup, entry_point):
- print(f"Configuring {test_name} test")
- settings_env = "ONAP_PYTHON_SDK_SETTINGS"
- if force_cleanup:
- validation_env = "PYTHON_SDK_TESTS_FORCE_CLEANUP"
- os.environ[validation_env] = "True"
+ """Run a single test scenario."""
+ with tracer.start_as_current_span(
+ f"test.{test_name}",
+ attributes={
+ "test.name": test_name,
+ "test.validation": validation,
+ "test.force_cleanup": force_cleanup
+ }
+ ) as root_span:
+ print(f"Configuring {test_name} test")
+ settings_env = "ONAP_PYTHON_SDK_SETTINGS"
+ if force_cleanup:
+ validation_env = "PYTHON_SDK_TESTS_FORCE_CLEANUP"
+ os.environ[validation_env] = "True"
setting_file_name = f"{test_name}_settings"
if test_name in SETTING_FILE_EXCEPTIONS:
if validation:
logger.info(f"Validating {test_name} test")
test_instance.validate()
+ root_span.set_attribute("test.result", "success")
return scenarios
+
def validate_scenario_base_class(test_name, scenario, scenarios):
+ """Validate that scenario class properly inherits from ScenarioBase."""
has_scenario_base = False
if test_name != scenario.case_name:
raise onap_test_exceptions.TestConfigurationException(
raise onap_test_exceptions.TestConfigurationException(
f"[{test_name}] {scenario.__class__.__name__} class does not inherit from ScenarioBase")
+
def main(argv):
"""Script is used to run one or all the tests.
entry_point = entry_points[test_name]
run_test(test_name, validation, force_cleanup, entry_point)
+
if __name__ == "__main__":
main(sys.argv[1:])
"""onaptests package."""
+
+from opentelemetry import trace
+
+tracer = trace.get_tracer(__name__)
+"""Base scenario classes for ONAP test scenarios."""
import logging
import time
+from opentelemetry import trace
from onapsdk.configuration import settings
from onapsdk.exceptions import SDKException, SettingsError
from xtesting.core import testcase
from onaptests.utils.exceptions import (OnapTestException,
TestConfigurationException)
+tracer = trace.get_tracer(__name__)
+
class ScenarioBase(testcase.TestCase):
"""Scenario base class."""
self.test: BaseStep = None
def run(self, **kwargs):
- """Run scenario and cleanup resources afterwards"""
- self.start_time = time.time()
- try:
- for test_phase in (self.test.execute, self.test.cleanup):
- phase_name = test_phase.__name__
- try:
- if (phase_name == "cleanup" and settings.CLEANUP_FLAG and
- settings.CLEANUP_ACTIVITY_TIMER > 0):
- time.sleep(settings.CLEANUP_ACTIVITY_TIMER)
- self.__logger.info("%s %s Phase Started",
- self.scenario_name, phase_name.title())
- test_phase()
- self.result += 50
- except OnapTestException as exc:
- self.__logger.exception("Test Exception %s on %s", str(exc), phase_name)
- self.__logger.info("ROOT CAUSE")
- self.__logger.info(exc.root_cause)
- except SDKException as exc:
- self.__logger.exception("SDK Exception %s on %s", str(exc), phase_name)
- self.__logger.info("ROOT CAUSE")
- self.__logger.info(str(exc))
- except Exception as exc:
- self.__logger.exception("General Exception %s on %s", str(exc), phase_name)
- if self.general_exception:
- exc = ExceptionGroup("General Exceptions", [self.general_exception, exc]) # noqa
- self.general_exception = exc
- finally:
- self.stop_time = time.time()
- self.__logger.info(f"{self.scenario_name} Execution {self.result}% Completed")
- if self.general_exception:
- raise self.general_exception
+ """Run scenario and cleanup resources afterwards."""
+ with tracer.start_as_current_span(
+ f"scenario.{self.case_name}",
+ attributes={
+ "scenario.name": self.scenario_name,
+ "scenario.case_name": self.case_name
+ }
+ ) as scenario_span:
+ self.start_time = time.time()
+ try:
+ for test_phase in (self.test.execute, self.test.cleanup):
+ phase_name = test_phase.__name__
+ with tracer.start_as_current_span(
+ f"phase.{phase_name}",
+ attributes={"phase.name": phase_name}
+ ) as phase_span:
+ try:
+ if (phase_name == "cleanup" and settings.CLEANUP_FLAG and
+ settings.CLEANUP_ACTIVITY_TIMER > 0):
+ time.sleep(settings.CLEANUP_ACTIVITY_TIMER)
+ self.__logger.info("%s %s Phase Started",
+ self.scenario_name, phase_name.title())
+ test_phase()
+ self.result += 50
+ phase_span.set_attribute("phase.result", "success")
+ except OnapTestException as exc:
+ phase_span.record_exception(exc)
+ phase_span.set_attribute("phase.result", "failed")
+ self.__logger.exception("Test Exception %s on %s", str(exc), phase_name)
+ self.__logger.info("ROOT CAUSE")
+ self.__logger.info(exc.root_cause)
+ except SDKException as exc:
+ phase_span.record_exception(exc)
+ phase_span.set_attribute("phase.result", "failed")
+ self.__logger.exception("SDK Exception %s on %s", str(exc), phase_name)
+ self.__logger.info("ROOT CAUSE")
+ self.__logger.info(str(exc))
+ except Exception as exc:
+ phase_span.record_exception(exc)
+ phase_span.set_attribute("phase.result", "failed")
+ self.__logger.exception("General Exception %s on %s", str(exc), phase_name)
+ if self.general_exception:
+ exc = ExceptionGroup("General Exceptions", [self.general_exception, exc]) # noqa
+ self.general_exception = exc
+ finally:
+ self.stop_time = time.time()
+ scenario_span.set_attribute("scenario.result_percentage", self.result)
+ scenario_span.set_attribute("scenario.duration", self.stop_time - self.start_time)
+ self.__logger.info(f"{self.scenario_name} Execution {self.result}% Completed")
+ if self.general_exception:
+ raise self.general_exception
def clean(self):
"""Clean Additional resources if needed."""
def validate(self):
"""Validate implementation of the scenario."""
-
self._validate_service_details()
self.test.validate_step_implementation()
self.test.validate_execution()
self.test.validate_cleanup()
def _validate_service_details(self):
+ """Validate that service details are properly configured."""
self._check_setting("SERVICE_NAME")
self._check_setting("SERVICE_DETAILS")
@BaseStep.store_state
def execute(self) -> None:
+ """Execute base scenario step."""
super().execute()
+"""Base step classes for ONAP test scenarios."""
import functools
import itertools
import logging
from abc import ABC, abstractmethod
from typing import Iterator, List, Optional
+from opentelemetry import trace
from onapsdk.aai.business import Customer, ServiceInstance, ServiceSubscription
from onapsdk.configuration import settings
from onapsdk.exceptions import SDKException, SettingsError
SubstepExecutionExceptionGroup,
TestConfigurationException)
+tracer = trace.get_tracer(__name__)
+
# pylint: disable=protected-access
IF_FORCE_CLEANUP = "PYTHON_SDK_TESTS_FORCE_CLEANUP"
self._state_execute = True
initial_exception = None
error_reason = []
- try:
- execution_status: Optional[ReportStepStatus] = ReportStepStatus.FAIL
- if cleanup:
- self._start_cleanup_time = time.time()
- try:
- if (self._cleanup and self._state_execute and
- (not self.has_substeps or self._substeps_executed) and
- (self._is_validation_only or
- self.check_preconditions(cleanup=True))):
+
+ operation = "cleanup" if cleanup else "execute"
+ with tracer.start_as_current_span(
+ f"step.{operation}.{self.name}",
+ attributes={
+ "step.name": self.name,
+ "step.component": self.component,
+ "step.description": self.description,
+ "step.operation": operation,
+ "step.nesting_level": self._nesting_level,
+ "step.is_root": self.is_root
+ }
+ ) as step_span:
+ try:
+ execution_status: Optional[ReportStepStatus] = ReportStepStatus.FAIL
+ if cleanup:
+ self._start_cleanup_time = time.time()
+ try:
+ if (self._cleanup and self._state_execute and
+ (not self.has_substeps or self._substeps_executed) and
+ (self._is_validation_only or
+ self.check_preconditions(cleanup=True))):
+ self._log_execution_state("START", cleanup)
+ if not self._is_validation_only or self._is_force_cleanup:
+ fun(self, *args, **kwargs)
+ self._cleaned_up = True
+ execution_status = ReportStepStatus.PASS
+ else:
+ execution_status = ReportStepStatus.NOT_EXECUTED
+ except (OnapTestException, SDKException) as test_exc:
+ initial_exception = test_exc
+ finally:
+ self._log_execution_state(execution_status.name, cleanup)
+ self._cleanup_substeps()
+ if initial_exception:
+ new_exception = initial_exception
+ initial_exception = None
+ raise new_exception
+ else:
+ if self._is_validation_only or self.check_preconditions():
self._log_execution_state("START", cleanup)
- if not self._is_validation_only or self._is_force_cleanup:
+ self._execute_substeps()
+ if not self._is_validation_only:
fun(self, *args, **kwargs)
- self._cleaned_up = True
execution_status = ReportStepStatus.PASS
+ self._executed = True
else:
execution_status = ReportStepStatus.NOT_EXECUTED
- except (OnapTestException, SDKException) as test_exc:
- initial_exception = test_exc
- finally:
- self._log_execution_state(execution_status.name, cleanup)
- self._cleanup_substeps()
+ except SubstepExecutionException as substep_exc:
+ step_span.record_exception(substep_exc)
+ if not cleanup:
+ execution_status = ReportStepStatus.NOT_EXECUTED
if initial_exception:
- new_exception = initial_exception
- initial_exception = None
- raise new_exception
- else:
- if self._is_validation_only or self.check_preconditions():
- self._log_execution_state("START", cleanup)
- self._execute_substeps()
- if not self._is_validation_only:
- fun(self, *args, **kwargs)
- execution_status = ReportStepStatus.PASS
- self._executed = True
+ substep_exc = OnapTestExceptionGroup("Cleanup Exceptions",
+ [initial_exception, substep_exc])
+ error_reason = substep_exc.root_cause
+ raise substep_exc
+ except (OnapTestException, SDKException) as test_exc:
+ step_span.record_exception(test_exc)
+ if initial_exception:
+ test_exc = OnapTestExceptionGroup("Cleanup Exceptions",
+ [initial_exception, test_exc])
+ if isinstance(test_exc, OnapTestException):
+ error_reason = test_exc.root_cause
else:
- execution_status = ReportStepStatus.NOT_EXECUTED
- except SubstepExecutionException as substep_exc:
- if not cleanup:
- execution_status = ReportStepStatus.NOT_EXECUTED
- if initial_exception:
- substep_exc = OnapTestExceptionGroup("Cleanup Exceptions",
- [initial_exception, substep_exc])
- error_reason = substep_exc.root_cause
- raise substep_exc
- except (OnapTestException, SDKException) as test_exc:
- if initial_exception:
- test_exc = OnapTestExceptionGroup("Cleanup Exceptions",
- [initial_exception, test_exc])
- if isinstance(test_exc, OnapTestException):
- error_reason = test_exc.root_cause
- else:
- error_reason = [str(test_exc)]
- raise test_exc
- finally:
- if not cleanup:
- self._log_execution_state(execution_status.name, cleanup)
- if cleanup:
- self._cleanup_report = Report(
- step_description=self._step_title(cleanup),
- step_execution_status=execution_status,
- step_execution_duration=time.time() - self._start_cleanup_time,
- step_component=self.component,
- step_error_reason=error_reason
- )
- else:
- if not self._start_execution_time:
- if execution_status != ReportStepStatus.NOT_EXECUTED:
- self._logger.error("No execution start time saved for %s step. "
- "Fix it by call `super.execute()` "
- "in step class `execute()` method definition",
- self.name)
- self._start_execution_time = time.time()
- self._execution_report = Report(
- step_description=self._step_title(cleanup),
- step_execution_status=(execution_status if execution_status else
- ReportStepStatus.FAIL),
- step_execution_duration=time.time() - self._start_execution_time,
- step_component=self.component,
- step_error_reason=error_reason
- )
+ error_reason = [str(test_exc)]
+ raise test_exc
+ finally:
+ if not cleanup:
+ self._log_execution_state(execution_status.name, cleanup)
+
+ # Set span attributes for final status
+ if execution_status:
+ step_span.set_attribute("step.status", execution_status.name)
+ if error_reason:
+ step_span.set_attribute("step.error_reasons", str(error_reason))
+
+ if cleanup:
+ duration = time.time() - self._start_cleanup_time
+ step_span.set_attribute("step.duration", duration)
+ self._cleanup_report = Report(
+ step_description=self._step_title(cleanup),
+ step_execution_status=execution_status,
+ step_execution_duration=duration,
+ step_component=self.component,
+ step_error_reason=error_reason
+ )
+ else:
+ if not self._start_execution_time:
+ if execution_status != ReportStepStatus.NOT_EXECUTED:
+ self._logger.error("No execution start time saved for %s step. "
+ "Fix it by call `super.execute()` "
+ "in step class `execute()` method definition",
+ self.name)
+ self._start_execution_time = time.time()
+ duration = time.time() - self._start_execution_time
+ step_span.set_attribute("step.duration", duration)
+ self._execution_report = Report(
+ step_description=self._step_title(cleanup),
+ step_execution_status=(execution_status if execution_status else
+ ReportStepStatus.FAIL),
+ step_execution_duration=duration,
+ step_component=self.component,
+ step_error_reason=error_reason
+ )
wrapper._is_wrapped = True
return wrapper
return True
def _execute_substeps(self) -> None:
- """Step's action execution.
+ """Execute step's action.
Run all substeps action before it's own action.
Override this method and remember to call `super().execute()` before.
if step._is_optional:
self._logger.info("Step is optional, error ignored, continue test execution")
elif step._break_on_error:
- raise SubstepExecutionException("", substep_err) # noqa: W0707
+ raise SubstepExecutionException("", substep_err) # noqa: W0707
else:
substep_exceptions.append(substep_err)
if self._steps:
step._default_cleanup_handler()
except (OnapTestException, SDKException) as substep_err:
try:
- raise SubstepExecutionException("", substep_err) # noqa: W0707
+ raise SubstepExecutionException("", substep_err) # noqa: W0707
except Exception as e:
exceptions_to_raise.append(e)
if len(exceptions_to_raise) > 0:
raise SubstepExecutionExceptionGroup("", exceptions_to_raise)
def execute(self) -> None:
- """Step's execute.
+ """Execute step.
Must be implemented in the steps with store_state decorator
"""
def cleanup(self) -> None:
- """Step's cleanup.
+ """Clean up step.
Not all steps has to have cleanup method
def validate_step_implementation(self):
"""Validate is step addes store_state decorators."""
-
if not getattr(self.execute, "_is_wrapped", False):
raise TestConfigurationException(
f"{self._step_title()} - store_state decorator not present in execute() method")
def validate_execution(self):
"""Validate if each step was executed by decorator."""
-
if self._is_validation_only:
self._log_execution_state(f"VALIDATE EXECUTION [{self._state_execute}]")
if not self._state_execute:
def validate_cleanup(self):
"""Validate if each step was cleaned by decorator."""
-
if self._is_validation_only:
for step in reversed(self._steps):
step.validate_cleanup()
def __init__(self, cleanup: bool):
"""Initialize step."""
-
super().__init__(cleanup=cleanup)
self._service_instance: ServiceInstance = None
self._service_subscription: ServiceSubscription = None
"""Delay step -- useful if some delay between two steps is needed."""
def __init__(self, delay: int, break_on_error=True):
+ """Initialize delay step.
+
+ Args:
+ delay (int): Delay duration in seconds
+ break_on_error (bool): Whether to break on error
+
+ """
super().__init__(BaseStep.HAS_NO_CLEANUP, break_on_error)
self.delay: int = delay
@property
def description(self) -> str:
+ """Step description."""
return f"Wait for {self.delay} seconds."
@property
def component(self) -> str:
+ """Component name."""
return "Python ONAP SDK"
@BaseStep.store_state
def execute(self):
+ """Execute delay step."""
super().execute()
time.sleep(self.delay)
+"""Service onboarding step module."""
import time
from typing import Any, Dict, Iterator
from urllib.parse import urlencode
import mysql.connector as mysql
+from opentelemetry import trace
from onapsdk.aai.service_design_and_creation import Model
from onapsdk.configuration import settings
from onapsdk.exceptions import InvalidResponse, ResourceNotFound
from .pnf import YamlTemplatePnfOnboardStep
from .vf import YamlTemplateVfOnboardStep
+tracer = trace.get_tracer(__name__)
+
class YamlTemplateServiceOnboardStep(YamlTemplateBaseStep):
"""Service onboard using YAML template step."""
return "SDC"
def check_preconditions(self, cleanup=False) -> bool:
+ """Check preconditions before step execution.
+
+ Args:
+ cleanup (bool): Whether this is cleanup phase
+
+ Returns:
+ bool: True if preconditions are met, False otherwise
+
+ """
if not super().check_preconditions(cleanup):
return False
if cleanup:
self.yaml_template[self.service_name]["instantiation_type"])
else:
instantiation_type: ServiceInstantiationType = ServiceInstantiationType.A_LA_CARTE
- try:
- service: Service = Service.get_by_name(name=self.service_name)
- if service.distributed:
- return
- except ResourceNotFound:
+
+ with tracer.start_as_current_span(
+ "sdc.service.get_or_create",
+ attributes={"service.name": self.service_name}
+ ) as sdc_span:
+ try:
+ service: Service = Service.get_by_name(name=self.service_name)
+ sdc_span.set_attribute("service.existed", True)
+ sdc_span.set_attribute("service.distributed", service.distributed)
+ if service.distributed:
+ return
+ except ResourceNotFound:
+ sdc_span.set_attribute("service.existed", False)
self._logger.info("before service create")
service = Service.create(name=self.service_name,
instantiation_type=instantiation_type,
category=category)
self._logger.info("after service create")
+ sdc_span.set_attribute("service.instantiation_type", instantiation_type.value)
self.declare_resources(service)
self.assign_properties(service)
+
if service.lifecycle_state != LifecycleState.CERTIFIED:
- service.lifecycle_operation(LifecycleOperation.CERTIFY)
+ with tracer.start_as_current_span(
+ "sdc.service.certify",
+ attributes={
+ "service.name": self.service_name,
+ "service.lifecycle_state": service.lifecycle_state.value
+ }
+ ):
+ service.lifecycle_operation(LifecycleOperation.CERTIFY)
def declare_resources(self, service: Service) -> None:
"""Declare resources.
@YamlTemplateBaseStep.store_state(cleanup=True)
def cleanup(self) -> None:
"""Cleanup service onboard step."""
- try:
- service: Service = Service.get_by_name(name=self.service_name)
- if service.lifecycle_state == LifecycleState.CERTIFIED:
- service.archive()
- service.delete()
- except ResourceNotFound:
- self._logger.info(f"Service {self.service_name} not found")
+ with tracer.start_as_current_span(
+ "sdc.service.delete",
+ attributes={"service.name": self.service_name}
+ ) as cleanup_span:
+ try:
+ service: Service = Service.get_by_name(name=self.service_name)
+ cleanup_span.set_attribute("service.found", True)
+ cleanup_span.set_attribute("service.lifecycle_state", service.lifecycle_state.value)
+ if service.lifecycle_state == LifecycleState.CERTIFIED:
+ service.archive()
+ service.delete()
+ cleanup_span.set_attribute("service.deleted", True)
+ except ResourceNotFound:
+ cleanup_span.set_attribute("service.found", False)
+ self._logger.info(f"Service {self.service_name} not found")
super().cleanup()
def execute(self):
"""Distribute service."""
super().execute()
- service: Service = Service.get_by_name(name=self.service_name)
- if service:
- if not service.distributed:
- service.distribute()
- self._logger.info(f"Service {self.service_name} distributed successfully.")
+ with tracer.start_as_current_span(
+ "sdc.service.distribute",
+ attributes={"service.name": self.service_name}
+ ) as dist_span:
+ service: Service = Service.get_by_name(name=self.service_name)
+ if service:
+ dist_span.set_attribute("service.found", True)
+ if not service.distributed:
+ dist_span.set_attribute("service.already_distributed", False)
+ service.distribute()
+ self._logger.info(f"Service {self.service_name} distributed successfully.")
+ else:
+ dist_span.set_attribute("service.already_distributed", True)
+ self._logger.info(f"Service {self.service_name} is already distributed.")
else:
- self._logger.info(f"Service {self.service_name} is already distributed.")
- else:
- raise onap_test_exceptions.OnapTestException(f"Service {self.service_name} "
- f"not found for distribution.")
+ dist_span.set_attribute("service.found", False)
+ raise onap_test_exceptions.OnapTestException(f"Service {self.service_name} "
+ f"not found for distribution.")
class BaseServiceDistributionComponentCheckStep(BaseStep):
"""Check service distribution in AAI step."""
class ModelWithGet(Model):
- """"Workaround to fix """
+ """Workaround to fix."""
@classmethod
def get_all(cls,
notified_module (str): Name of notified module
component_name (str): Name of the module's component
"""
-
super().__init__(
component_name=component_name, break_on_error=False, load_model=False)
self.component_id = notified_module
requires = pip >= 8
[testenv]
-basepython = python3.9
+basepython = python3.10
allowlist_externals =
git
/bin/sh
sh
/bin/bash
bash
-deps =
- pyyaml == 3.13
- bandit == 1.3
- coala-bears
- nodeenv
+ xargs
[testenv:json]
+deps =
+skip_install = True
commands_pre =
/bin/sh -c "git --no-pager diff HEAD HEAD^ --name-only '*.json' > /tmp/.coalist_json"
commands =
-# '\ ' at the end of command is needed for a case where above command returns empty list (it adds empty file
-# parameter to '--files' opt
- /bin/bash -c "coala --non-interactive --disable-caching --no-autoapply-warn json --files $(</tmp/.coalist_json) \ "
+ /bin/bash -c "cat /tmp/.coalist_json | xargs -r python -m json.tool > /dev/null"
[testenv:yaml]
+deps =
+ yamllint
+skip_install = True
commands_pre =
/bin/sh -c "git --no-pager diff HEAD HEAD^ --name-only '*.yaml' '*.yml' > /tmp/.coalist_yaml"
commands =
-# '\ ' at the end of command is needed for a case where above command returns empty list (it adds empty file
-# parameter to '--files' opt
- /bin/bash -c "coala --non-interactive --disable-caching --no-autoapply-warn yaml --files $(</tmp/.coalist_yaml) \ "
+ /bin/bash -c "cat /tmp/.coalist_yaml | xargs -r yamllint -d relaxed"
[testenv:py]
+deps =
+ flake8
+ flake8-docstrings
+skip_install = True
commands_pre =
/bin/sh -c "git --no-pager diff HEAD HEAD^ --name-only '*.py' > /tmp/.coalist_py"
commands =
- /bin/bash -c "coala --non-interactive --disable-caching --no-autoapply-warn py --files $(</tmp/.coalist_py) \ "
+ /bin/bash -c "cat /tmp/.coalist_py | xargs -r flake8 --max-line-length=120"
[testenv:md]
+deps =
+ nodeenv
+skip_install = True
commands_pre =
nodeenv -p --verbose
- npm install --global remark-cli
+ npm install --global markdownlint-cli
/bin/sh -c "git --no-pager diff HEAD HEAD^ --name-only '*.md' > /tmp/.coalist_md"
commands =
- /bin/bash -c "coala --non-interactive --disable-caching --no-autoapply-warn md --files $(</tmp/.coalist_md) \ "
+ /bin/bash -c "cat /tmp/.coalist_md | xargs -r markdownlint"
[testenv:pylama]
-basepython = python3.11
+basepython = python3.10
deps =
pylama[all]
-rrequirements.txt
commands = pylama -o pylama.ini src/
[testenv:validate]
-basepython = python3.11
+basepython = python3.10
deps =
-rrequirements.txt
skip_install = True
commands = python run_test.py all true
[testenv:run-test]
-basepython = python3.11
+basepython = python3.10
deps =
-rrequirements.txt
skip_install = True
commands = python run_test.py {posargs}
[testenv:isort-check]
-basepython = python3.11
+basepython = python3.10
deps =
isort
skip_install = True
commands = isort src/onaptests --check --thirdparty=onapsdk
[testenv:isort-fix]
-basepython = python3.11
+basepython = python3.10
deps =
isort
skip_install = True