Skip to content

Commit

Permalink
Feature/camunda 7 20 (#87)
Browse files Browse the repository at this point in the history
* remove usage of deprecated keywords

* fix typo

* gitignore vscode and python builds

* add TTL for 7.20

* update github actions to v4

* test python also on push

* specific logs folders

* update setup-python action v5

* dumdidum

* remove outdated styleguide checks

* another

* remove xmlrunner from doctest

* again

* typo

* update supported python versions

* adjust readme

skip-ci

* update xunit publishing
  • Loading branch information
Noordsestern authored Feb 19, 2024
1 parent 89391b8 commit 0ea7872
Show file tree
Hide file tree
Showing 22 changed files with 182 additions and 147 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
13 changes: 3 additions & 10 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

name: Python package

on: [ pull_request ]
on: [ push, pull_request ]

jobs:
build:
Expand All @@ -14,22 +14,15 @@ jobs:
python-version: ['3.8', '3.9', '3.10','3.11','3.12']

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 xmlrunner
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Execute doctests
run: |
python CamundaLibrary/CamundaResources.py -v
33 changes: 12 additions & 21 deletions .github/workflows/robot-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,25 @@ jobs:
env:
camunda.bpm.run.auth.enabled: ${{ matrix.auth_enabled }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Test with robot
run: |
pip install .
sleep 10
robot -d logs -b debug.log -x xunit.xml -L DEBUG -V tests/robot/config_cicd.py -v CAMUNDA_HOST:http://camunda:8080 tests/robot/**/*.robot
- name: Archive production artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
if: always()
with:
name: robot logs
name: robot logs-${{matrix.camunda_version}}-${{matrix.auth_enabled}}
path: |
logs/
publish-test-results:
name: "Publish Unit Tests Results"
needs: integrationtest
runs-on: ubuntu-latest
# the build-and-test job might be skipped, we don't need to run this job then
if: success() || failure()

steps:
- name: Download Artifacts
uses: actions/download-artifact@v2
with:
name: robot logs
logs
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: robot logs-${{matrix.camunda_version}}-${{matrix.auth_enabled}}

- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v1
with:
files: xunit.xml
- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
files: xunit.xml
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ logs/
log/
temp/
tmp/
build/
.idea/
public/
lsp/
__pycache__/
.vscode/

*.egg-info
*.log
*.zip
.robocop
Expand Down
97 changes: 64 additions & 33 deletions CamundaLibrary/CamundaResources.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class CamundaResources:
"""
Singleton containing resources shared by Camunda sub libraries
"""

_instance = None

_client_configuration: Configuration = None
Expand All @@ -19,7 +20,7 @@ class CamundaResources:

def __new__(cls):
if cls._instance is None:
print('Creating the object')
print("Creating the object")
cls._instance = super(CamundaResources, cls).__new__(cls)
# Put any initialization here.
return cls._instance
Expand Down Expand Up @@ -54,21 +55,30 @@ def api_client(self) -> ApiClient:

def _create_task_client(self) -> ApiClient:
if not self.client_configuration:
raise ValueError('No URL to camunda set. Please initialize Library with url or use keyword '
'"Set Camunda URL" first.')
raise ValueError(
"No URL to camunda set. Please initialize Library with url or use keyword "
'"Set Camunda URL" first.'
)

# the generated client for camunda ignores auth parameters from the configuration. Therefore we must set default headers here:
client = ApiClient(self.client_configuration)
if self.client_configuration.username:
client.set_default_header('Authorization',self.client_configuration.get_basic_auth_token())
client.set_default_header(
"Authorization", self.client_configuration.get_basic_auth_token()
)
elif self.client_configuration.api_key:
identifier = list(self.client_configuration.api_key.keys())[0]
client.set_default_header('Authorization', self.client_configuration.get_api_key_with_prefix(identifier))
client.set_default_header(
"Authorization",
self.client_configuration.get_api_key_with_prefix(identifier),
)

return client

@staticmethod
def convert_openapi_variables_to_dict(open_api_variables: Dict[str, VariableValueDto]) -> Dict:
def convert_openapi_variables_to_dict(
open_api_variables: Dict[str, VariableValueDto]
) -> Dict:
"""
Converts the variables to a simple dictionary
:return: dict
Expand All @@ -78,10 +88,15 @@ def convert_openapi_variables_to_dict(open_api_variables: Dict[str, VariableValu
"""
if not open_api_variables:
return {}
return {k: CamundaResources.convert_variable_dto(v) for k, v in open_api_variables.items()}
return {
k: CamundaResources.convert_variable_dto(v)
for k, v in open_api_variables.items()
}

@staticmethod
def convert_dict_to_openapi_variables(variabes: dict) -> Dict[str, VariableValueDto]:
def convert_dict_to_openapi_variables(
variabes: dict,
) -> Dict[str, VariableValueDto]:
"""
Converts the variables to a simple dictionary
:return: dict
Expand All @@ -98,10 +113,14 @@ def convert_dict_to_openapi_variables(variabes: dict) -> Dict[str, VariableValue
"""
if not variabes:
return {}
return {k: CamundaResources.convert_to_variable_dto(v) for k, v in variabes.items()}
return {
k: CamundaResources.convert_to_variable_dto(v) for k, v in variabes.items()
}

@staticmethod
def convert_file_dict_to_openapi_variables(files: Dict[str, str]) -> Dict[str, VariableValueDto]:
def convert_file_dict_to_openapi_variables(
files: Dict[str, str]
) -> Dict[str, VariableValueDto]:
"""
Example:
>>> CamundaResources.convert_file_dict_to_openapi_variables({'testfile': 'tests/resources/test.txt'})
Expand All @@ -119,40 +138,48 @@ def convert_file_dict_to_openapi_variables(files: Dict[str, str]) -> Dict[str, V
@staticmethod
def convert_file_to_dto(path: str) -> VariableValueDto:
if not path:
raise FileNotFoundError('Cannot create DTO from file, because no file provided')
raise FileNotFoundError(
"Cannot create DTO from file, because no file provided"
)

with open(path, 'r+b') as file:
file_content = base64.standard_b64encode(file.read()).decode('utf-8')
with open(path, "r+b") as file:
file_content = base64.standard_b64encode(file.read()).decode("utf-8")

base = os.path.basename(path)
file_name, file_ext = os.path.splitext(base)

if file_ext.lower() in ['.jpg', '.jpeg', '.jpe']:
mimetype = 'image/jpeg'
elif file_ext.lower() in ['.png']:
mimetype = 'image/png'
elif file_ext.lower() in ['.pdf']:
mimetype = 'application/pdf'
elif file_ext.lower() in ['.txt']:
mimetype = 'text/plain'
if file_ext.lower() in [".jpg", ".jpeg", ".jpe"]:
mimetype = "image/jpeg"
elif file_ext.lower() in [".png"]:
mimetype = "image/png"
elif file_ext.lower() in [".pdf"]:
mimetype = "application/pdf"
elif file_ext.lower() in [".txt"]:
mimetype = "text/plain"
else:
mimetype = 'application/octet-stream'
return VariableValueDto(value=file_content, type='File', value_info={'filename': base, 'mimetype': mimetype})
mimetype = "application/octet-stream"
return VariableValueDto(
value=file_content,
type="File",
value_info={"filename": base, "mimetype": mimetype},
)

@staticmethod
def convert_to_variable_dto(value: Any) -> VariableValueDto:
if isinstance(value, str):
return VariableValueDto(value=value)
elif isinstance(value, Collection): # String is also a collection and must be filtered before Collection.
return VariableValueDto(value=json.dumps(value), type='Json')
elif isinstance(
value, Collection
): # String is also a collection and must be filtered before Collection.
return VariableValueDto(value=json.dumps(value), type="Json")
else:
return VariableValueDto(value=value)

@staticmethod
def convert_variable_dto(dto: VariableValueDto) -> Any:
if dto.type == 'File':
if dto.type == "File":
return dto.to_dict()
if dto.type == 'Json':
if dto.type == "Json":
return json.loads(dto.value)
return dto.value

Expand All @@ -172,13 +199,17 @@ def dict_to_camunda_json(d: dict) -> Any:
>>> CamundaResources.dict_to_camunda_json({'person': {'age': 25, 'languages': ['English', 'Suomi']}})
{'person': {'value': '{"age": 25, "languages": ["English", "Suomi"]}', 'type': 'Json'}}
"""
return {k: {'value': json.dumps(v), 'type': 'Json'} if isinstance(v, Collection) else {'value': v}
for k, v in d.items()}
return {
k: (
{"value": json.dumps(v), "type": "Json"}
if isinstance(v, Collection)
else {"value": v}
)
for k, v in d.items()
}


if __name__ == '__main__':
if __name__ == "__main__":
import doctest
import xmlrunner

suite = doctest.DocTestSuite()
xmlrunner.XMLTestRunner(output='logs').run(suite)
doctest.testmod()
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ can be found [here](https://docs.camunda.org/manual/7.14/reference/rest/).
**Please review [issue board](https://github.com/MarketSquare/robotframework-camunda/issues) for
known issues or report one yourself. You are invited to contribute pull requests.**

Supporting:
- Python >= 3.8
- Camunda 7 >= 7.14.0

## Documentation

Keyword documentation is provided [here](https://robotframework-camunda-demos.gitlab.io/robotframework-camunda-mirror/latest/keywords/camundalibrary)
Expand Down
21 changes: 17 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
name = "Markus Stahl"

version_regex = r"^v(?P<version>\d*\.\d*\.\d*$)"
version = os.environ.get('CI_COMMIT_TAG', f'2.{os.environ.get("CI_COMMIT_REF_NAME","0.0")}')
version = os.environ.get(
"CI_COMMIT_TAG", f'2.{os.environ.get("CI_COMMIT_REF_NAME","0.0")}'
)
full_version_match = re.fullmatch(version_regex, version)
if full_version_match:
version = full_version_match.group('version')
version = full_version_match.group("version")

setup(
name="robotframework-camunda",
Expand All @@ -28,14 +30,25 @@
classifiers=[
"Intended Audience :: Developers",
"Natural Language :: English",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Development Status :: 5 - Production/Stable",
"Framework :: Robot Framework",
],
license="Apache License, Version 2.0",
install_requires=["robotframework>=3.2", "requests", "frozendict", 'generic-camunda-client>=7.15.0','requests_toolbelt','url-normalize'],
install_requires=[
"robotframework>=3.2",
"requests",
"frozendict",
"generic-camunda-client>=7.15.0",
"requests_toolbelt",
"url-normalize",
],
include_package_data=True,
)
Loading

0 comments on commit 0ea7872

Please sign in to comment.