devops-events-local 0.0.1b4163__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- devops_events_local/__init__.py +0 -0
- devops_events_local/src/__init__.py +0 -0
- devops_events_local/src/constants_src_devops_events_local.py +18 -0
- devops_events_local/src/handle_request_to_open_a_jira_work_item.py +46 -0
- devops_events_local/src/handle_slack_request.py +30 -0
- devops_events_local/src/version.py +2 -0
- devops_events_local-0.0.1b4163.dist-info/METADATA +23 -0
- devops_events_local-0.0.1b4163.dist-info/RECORD +10 -0
- devops_events_local-0.0.1b4163.dist-info/WHEEL +5 -0
- devops_events_local-0.0.1b4163.dist-info/top_level.txt +1 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from logger_local.LoggerComponentEnum import LoggerComponentEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ConstantsSrcDevopsEventsLocal:
|
|
5
|
+
"""The constants of devops-events-local"""
|
|
6
|
+
|
|
7
|
+
# TODO you can check component_table or for any #request-to-open-component-id request.
|
|
8
|
+
# generic-webhook to call components-local to get the CODE and TEST componets ids
|
|
9
|
+
DEVOPS_EVENTS_LOCAL_PYTHON_CODE_COMPONENT_ID: int = 0
|
|
10
|
+
DEVOPS_EVENTS_LOCAL_PYTHON_CODE_COMPONENT_NAME = "devops-events-local-python-package"
|
|
11
|
+
DEVOPS_EVENTS_LOCAL_PYTHON_CODE_DEVELOPER_EMAIL_ADDRESS = "yuval.r@circ.zone"
|
|
12
|
+
|
|
13
|
+
DEVOPS_EVENTS_LOCAL_PYTHON_CODE_LOGGER_OBJECT = {
|
|
14
|
+
'component_id': DEVOPS_EVENTS_LOCAL_PYTHON_CODE_COMPONENT_ID,
|
|
15
|
+
'component_name': DEVOPS_EVENTS_LOCAL_PYTHON_CODE_COMPONENT_NAME,
|
|
16
|
+
'component_category': LoggerComponentEnum.ComponentCategory.Code.value,
|
|
17
|
+
'developer_email_address': DEVOPS_EVENTS_LOCAL_PYTHON_CODE_DEVELOPER_EMAIL_ADDRESS
|
|
18
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from logger_local.LoggerLocal import Logger
|
|
5
|
+
|
|
6
|
+
from .constants_src_devops_events_local import ConstantsSrcDevopsEventsLocal
|
|
7
|
+
from .handle_slack_request import HandleSlackRequest
|
|
8
|
+
|
|
9
|
+
logger = Logger.create_logger(object=ConstantsSrcDevopsEventsLocal.DEVOPS_EVENTS_LOCAL_PYTHON_CODE_LOGGER_OBJECT)
|
|
10
|
+
|
|
11
|
+
LABEL_TO_FIELD = {"summary": "summary", "description": "description", "reponame": "repo_name",
|
|
12
|
+
"components": "components", "component": "components"}
|
|
13
|
+
MANDATORY_FIELD_LABELS = {"summary": "Summary", "description": "Description", "repo_name": "RepoName"}
|
|
14
|
+
|
|
15
|
+
# Slack wraps text in *bold*, _italic_, `code`, ```blocks``` and > quotes; allow them around the labels.
|
|
16
|
+
FORMATTING = r"[ \t>*_`]*"
|
|
17
|
+
TRAILING_FORMATTING = r"[ \t*_`]*"
|
|
18
|
+
LABEL = r"(?:summary|description|repo[ _]?name|components?)"
|
|
19
|
+
FIELD_PATTERN = re.compile(
|
|
20
|
+
rf"^{FORMATTING}(?P<label>{LABEL}){TRAILING_FORMATTING}:{TRAILING_FORMATTING}(?P<value>.*?){TRAILING_FORMATTING}"
|
|
21
|
+
rf"(?=\n{FORMATTING}{LABEL}{TRAILING_FORMATTING}:|\Z)",
|
|
22
|
+
re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RequestToOpenAJiraWorkItemParseException(ValueError):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# TODO What if the request arrives in email/Telegram/REST-API ...?
|
|
30
|
+
class HandleRequestToOpenAJiraWorkItem(HandleSlackRequest):
|
|
31
|
+
field_pattern = FIELD_PATTERN
|
|
32
|
+
|
|
33
|
+
def parse(self, text: str) -> dict[str, Any]:
|
|
34
|
+
"""Split a #request-to-open-a-jira-issue Slack message into the fields jira_local expects:
|
|
35
|
+
summary, description, repo_name and components (list, may be empty)."""
|
|
36
|
+
fields: dict[str, Any] = {}
|
|
37
|
+
for match in self.field_pattern.finditer(self.clean_slack_text(text or "")):
|
|
38
|
+
field = LABEL_TO_FIELD[re.sub(r"[ _]", "", match.group("label").lower())]
|
|
39
|
+
fields.setdefault(field, match.group("value").strip())
|
|
40
|
+
missing_labels = [label for field, label in MANDATORY_FIELD_LABELS.items() if not fields.get(field)]
|
|
41
|
+
if missing_labels:
|
|
42
|
+
logger.warning(f"Request without {', '.join(missing_labels)}")
|
|
43
|
+
raise RequestToOpenAJiraWorkItemParseException(f"Missing {', '.join(missing_labels)}")
|
|
44
|
+
fields["components"] = [component.strip() for component in fields.get("components", "").split(",")
|
|
45
|
+
if component.strip()]
|
|
46
|
+
return fields
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import html
|
|
2
|
+
import re
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
# <https://url|label> -> label, <https://url> -> https://url (user/channel mentions <@U1>/<#C1> are kept)
|
|
7
|
+
SLACK_LINK_PATTERN = re.compile(r"<((?:https?|mailto):[^|>]+)(?:\|([^>]+))?>")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class HandleSlackRequest(ABC):
|
|
11
|
+
"""A request posted in a Slack request channel, e.g. #request-to-open-a-jira-issue.
|
|
12
|
+
Each request type gives the pattern of its "Label: value" fields and parses them."""
|
|
13
|
+
|
|
14
|
+
field_pattern: re.Pattern
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def clean_slack_text(text: str) -> str:
|
|
18
|
+
text_without_links = SLACK_LINK_PATTERN.sub(lambda match: match.group(2) or match.group(1), text)
|
|
19
|
+
clean_text = html.unescape(text_without_links).replace("\r\n", "\n")
|
|
20
|
+
return clean_text
|
|
21
|
+
|
|
22
|
+
def has_request_fields(self, text: str) -> bool:
|
|
23
|
+
"""True when the text has at least one field label (e.g. "Summary:"),
|
|
24
|
+
i.e. it is a request and not a chat reply."""
|
|
25
|
+
has_fields = self.field_pattern.search(self.clean_slack_text(text or "")) is not None
|
|
26
|
+
return has_fields
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def parse(self, text: str) -> dict[str, Any]:
|
|
30
|
+
"""The fields of the request, by their names in the target system"""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devops-events-local
|
|
3
|
+
Version: 0.0.1b4163
|
|
4
|
+
Summary: PyPI devops-events-local Python Package owned by Circlez.ai
|
|
5
|
+
Home-page: https://github.com/circles-zone/devops-events-local-python-package
|
|
6
|
+
Author: Circles
|
|
7
|
+
Author-email: info@circlez.ai
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: python-sdk-remote
|
|
12
|
+
Requires-Dist: logger-local
|
|
13
|
+
Dynamic: author
|
|
14
|
+
Dynamic: author-email
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-dist
|
|
20
|
+
Dynamic: summary
|
|
21
|
+
|
|
22
|
+
PyPI devops-events-local Python Package owned by Circlez.ai
|
|
23
|
+
GHA: https://github.com/circles-zone/devops-events-local-python-package/actions
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
devops_events_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
devops_events_local/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
devops_events_local/src/constants_src_devops_events_local.py,sha256=dfU7lKciqZwsbIb16d-uPh2AV3hp1xaoASb3DCwyf1Q,936
|
|
4
|
+
devops_events_local/src/handle_request_to_open_a_jira_work_item.py,sha256=3drFGD1FOUP5YeBd0bvD7dW0zJ_43-RzMpWBK9AeI6k,2308
|
|
5
|
+
devops_events_local/src/handle_slack_request.py,sha256=qidXyw8d2npRYkIrtR8Eo_cTz_hfGvLegrPb3BDSgbs,1234
|
|
6
|
+
devops_events_local/src/version.py,sha256=zJxrMPsUnBUY2lnD3AQv6itQvLgWWewqoE2P42Au80w,99
|
|
7
|
+
devops_events_local-0.0.1b4163.dist-info/METADATA,sha256=LrTwIFWxcrqusuSC5D0a7jsQ81OHsT_moiPWOeLf0Rg,772
|
|
8
|
+
devops_events_local-0.0.1b4163.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
9
|
+
devops_events_local-0.0.1b4163.dist-info/top_level.txt,sha256=HEeKOc6_g-BHAsRM12SX8xmw_79pNxrUDycysWWE2SI,20
|
|
10
|
+
devops_events_local-0.0.1b4163.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
devops_events_local
|