devops-events-local 0.0.1b4163__tar.gz
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-0.0.1b4163/.env.local1.example +34 -0
- devops_events_local-0.0.1b4163/.env.play1.example +35 -0
- devops_events_local-0.0.1b4163/.flake8 +2 -0
- devops_events_local-0.0.1b4163/.logger.json5 +27 -0
- devops_events_local-0.0.1b4163/CODEOWNERS +2 -0
- devops_events_local-0.0.1b4163/PKG-INFO +23 -0
- devops_events_local-0.0.1b4163/README.md +23 -0
- devops_events_local-0.0.1b4163/__init__.py +0 -0
- devops_events_local-0.0.1b4163/bin/cmd/profile.bat +3 -0
- devops_events_local-0.0.1b4163/bin/powershell/ExamplePowerShellModule/ExamplePowershellModule.psm1 +0 -0
- devops_events_local-0.0.1b4163/bin/powershell/profile.ps1 +5 -0
- devops_events_local-0.0.1b4163/bin/sh/profile.sh +5 -0
- devops_events_local-0.0.1b4163/bin/sh/run.sh +7 -0
- devops_events_local-0.0.1b4163/component.local1.json5.example +11 -0
- devops_events_local-0.0.1b4163/pyproject.toml +34 -0
- devops_events_local-0.0.1b4163/pytest.ini +5 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/__init__.py +0 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/src/__init__.py +0 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/src/constants_src_devops_events_local.py +18 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/src/handle_request_to_open_a_jira_work_item.py +46 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/src/handle_slack_request.py +30 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/src/version.py +2 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/tests/__init__.py +0 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/tests/conftest.py +5 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/tests/unit/conftest.py +8 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local/tests/unit/handle_request_to_open_a_jira_work_item_unit_test.py +95 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local.egg-info/PKG-INFO +23 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local.egg-info/SOURCES.txt +33 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local.egg-info/dependency_links.txt +1 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local.egg-info/requires.txt +2 -0
- devops_events_local-0.0.1b4163/python_packages/devops_events_local.egg-info/top_level.txt +1 -0
- devops_events_local-0.0.1b4163/requirements-dev.txt +8 -0
- devops_events_local-0.0.1b4163/requirements.txt +3 -0
- devops_events_local-0.0.1b4163/setup.cfg +4 -0
- devops_events_local-0.0.1b4163/setup.py +91 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# TODO Please add all the environment variables uses in this repo here without any sensative/private information/credentials
|
|
2
|
+
|
|
3
|
+
# This is the .env file for play1 environment in the project directory and not in the root directory
|
|
4
|
+
# Please do not delete/rename this file
|
|
5
|
+
|
|
6
|
+
BRAND_NAME=Circlez
|
|
7
|
+
ENVIRONMENT_NAME=local1
|
|
8
|
+
|
|
9
|
+
# TODO In -local-package we need RDS environment variables, in -remote-package please delete the RDS variables from this file
|
|
10
|
+
RDS_HOSTNAME=db.local1.circ.zone
|
|
11
|
+
# TODO: Please update your RDS_USERNAME and RDS_PASSWORD
|
|
12
|
+
# RDS_USERNAME withour the @circ.zone
|
|
13
|
+
RDS_USERNAME=tal.r
|
|
14
|
+
RDS_PASSWORD=
|
|
15
|
+
|
|
16
|
+
# TODO In -local-package we need JWT_SECRET_KEY environment variables, in -remote-package please delete the JWT_SECRET_KEY variables from this file
|
|
17
|
+
JWT_SECRET_KEY=4rehrkj43h5lkefkdslcw4r
|
|
18
|
+
|
|
19
|
+
# LOGZIO_TOKEN=cXNHuVkkffkilnkKzZlWExECRlSKqopE
|
|
20
|
+
DATADOG_API_KEY=c3d63dc8998d86434b38142e50a05e74
|
|
21
|
+
|
|
22
|
+
# Needed by the logger-local
|
|
23
|
+
# TODO: Please update you username in the product i.e. tal.r@circ.zone and the password in the product
|
|
24
|
+
PRODUCT_USER_IDENTIFIER=
|
|
25
|
+
PRODUCT_PASSWORD=
|
|
26
|
+
|
|
27
|
+
# AWS (in case of Local you need AWS environment variables, in case of remote AWS environment variables are not needed)
|
|
28
|
+
|
|
29
|
+
AWS_ACCESS_KEY_ID=
|
|
30
|
+
AWS_SECRET_ACCESS_KEY=
|
|
31
|
+
|
|
32
|
+
AWS_DEFAULT_STORAGE_BUCKET_NAME="storage.us-east-1.local1.circ.zone"
|
|
33
|
+
|
|
34
|
+
AWS_DEFAULT_REGION=us-east-1
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# TODO Please add all the environment variables uses in this repo here without any sensative/private information/credentials
|
|
2
|
+
|
|
3
|
+
# This is the .env file for play1 environment in the project directory and not in the root directory
|
|
4
|
+
# Please do not delete/rename this file
|
|
5
|
+
|
|
6
|
+
BRAND_NAME=Circlez
|
|
7
|
+
ENVIRONMENT_NAME=play1
|
|
8
|
+
|
|
9
|
+
# TODO In -local-package we need RDS environment variables, in -remote-package please delete the RDS variables from this file
|
|
10
|
+
RDS_HOSTNAME=db.play1.circ.zone
|
|
11
|
+
# TODO: Please update your RDS_USERNAME and RDS_PASSWORD
|
|
12
|
+
# RDS_USERNAME withour the @circ.zone
|
|
13
|
+
RDS_USERNAME=tal.r
|
|
14
|
+
RDS_PASSWORD=
|
|
15
|
+
|
|
16
|
+
# TODO In -local-package we need JWT_SECRET_KEY environment variables, in -remote-package please delete the JWT_SECRET_KEY variables from this file
|
|
17
|
+
JWT_SECRET_KEY=4rehrkj43h5lkefkdslcw4r
|
|
18
|
+
|
|
19
|
+
# LOGZIO_TOKEN=cXNHuVkkffkilnkKzZlWExECRlSKqopE
|
|
20
|
+
DATADOG_API_KEY=c3d63dc8998d86434b38142e50a05e74
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Needed by the logger-local
|
|
24
|
+
# TODO: Please update you username in the product i.e. tal.r@circ.zone and the password in the product
|
|
25
|
+
PRODUCT_USER_IDENTIFIER=
|
|
26
|
+
PRODUCT_PASSWORD=
|
|
27
|
+
|
|
28
|
+
# AWS (in case of Local you need AWS environment variables, in case of remote AWS environment variables are not needed)
|
|
29
|
+
|
|
30
|
+
AWS_ACCESS_KEY_ID=
|
|
31
|
+
AWS_SECRET_ACCESS_KEY=
|
|
32
|
+
|
|
33
|
+
AWS_DEFAULT_STORAGE_BUCKET_NAME="storage.us-east-1.play1.circ.zone"
|
|
34
|
+
|
|
35
|
+
AWS_DEFAULT_REGION=us-east-1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"database without ORM": {
|
|
3
|
+
"Console": "Warning"
|
|
4
|
+
},
|
|
5
|
+
"person_local_python": {
|
|
6
|
+
"Logz.io": "Warning"
|
|
7
|
+
},
|
|
8
|
+
"sdk local": {
|
|
9
|
+
"Logz.io": "Warning"
|
|
10
|
+
},
|
|
11
|
+
"contact-person-local": {
|
|
12
|
+
"Logz.io": "Warning"
|
|
13
|
+
},
|
|
14
|
+
"text_block": {
|
|
15
|
+
"Logz.io": "Warning"
|
|
16
|
+
},
|
|
17
|
+
"contact-notes-local": {
|
|
18
|
+
"Logz.io": "Warning"
|
|
19
|
+
},
|
|
20
|
+
"wrong-component": {
|
|
21
|
+
"Logz.io": "Warning"
|
|
22
|
+
},
|
|
23
|
+
"default": {
|
|
24
|
+
"Console": "Error",
|
|
25
|
+
"Logz.io": "Error"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -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,23 @@
|
|
|
1
|
+
# General
|
|
2
|
+
|
|
3
|
+
Unlike the README.md in the root directory, this is a README.md of this specific repo/package<br>
|
|
4
|
+
|
|
5
|
+
TODO Please update the README.md of this specific repo/package and not the README.md in the root directory based on the python-package-template repo<br>
|
|
6
|
+
|
|
7
|
+
## TODOs
|
|
8
|
+
|
|
9
|
+
TODO example of a TODO, please it with a real TODO<br>
|
|
10
|
+
|
|
11
|
+
## Versions
|
|
12
|
+
|
|
13
|
+
[pub] 0.0.1 Initial version (change the directories, files, setup.py, .github/workflows/*.yml)<br>
|
|
14
|
+
|
|
15
|
+
## Installation instructions
|
|
16
|
+
|
|
17
|
+
It's advised to use venv<br>
|
|
18
|
+
If you have Windows, it's also advised to use the Windows Subsystem for Linux<br>
|
|
19
|
+
|
|
20
|
+
## Install dependencies
|
|
21
|
+
|
|
22
|
+
Run ./download-beta-sdk.sh from the bash terminal<br>
|
|
23
|
+
Run pip install -r requirements.txt from the bash terminal<br>
|
|
File without changes
|
devops_events_local-0.0.1b4163/bin/powershell/ExamplePowerShellModule/ExamplePowershellModule.psm1
ADDED
|
File without changes
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# This file should be in the future instead of setup.py
|
|
2
|
+
# https://python-poetry.org/docs/pyproject
|
|
3
|
+
# https://stackoverflow.com/questions/78048223/adding-folder-with-data-with-pyproject-toml
|
|
4
|
+
# https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license
|
|
5
|
+
|
|
6
|
+
# This file is mandatory for the `poetry version patch`
|
|
7
|
+
|
|
8
|
+
# It seems we need to copy this file also to serverless-com repo, as required by dialog-workflow-python-package
|
|
9
|
+
|
|
10
|
+
[build-system]
|
|
11
|
+
# "setuptools_scm>=6.2" is required for writing the version in my_package/_version.py and may be also for "poetry version patch" to work
|
|
12
|
+
requires = ["setuptools>=61.0", "setuptools_scm>=6.2"]
|
|
13
|
+
build-backend = "setuptools.build_meta"
|
|
14
|
+
|
|
15
|
+
[tool.setuptools_scm]
|
|
16
|
+
write_to = "python_packages/devops_events_local/_version.py"
|
|
17
|
+
|
|
18
|
+
[tool.pytest.ini_options]
|
|
19
|
+
pythonpath = ["."]
|
|
20
|
+
|
|
21
|
+
[tool.poetry]
|
|
22
|
+
name = "devops-events-local"
|
|
23
|
+
# TODO After the b (beta), you should add the Jira Work Item ID (was generated by Jira). If you run sdk-local Makec.ps1 it should do it for you.
|
|
24
|
+
# I believe we are still using the version from setup.py and not from here until Potery will work
|
|
25
|
+
version = "0.0.1b4163" # https://pypi.org/project/devops-events-local/
|
|
26
|
+
description = "devops-events-local Python Package"
|
|
27
|
+
readme = "README.md"
|
|
28
|
+
authors = [
|
|
29
|
+
"Circlez.ai <info@circlez.ai>",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[tool.poetry.dev-dependencies]
|
|
33
|
+
pytest = "^8.0"
|
|
34
|
+
pytest-cov = "^5.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
|
devops_events_local-0.0.1b4163/python_packages/devops_events_local/src/handle_slack_request.py
ADDED
|
@@ -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"""
|
|
File without changes
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from logger_local.src.component import Component
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@pytest.fixture(autouse=True)
|
|
6
|
+
def logger_without_database(monkeypatch):
|
|
7
|
+
"""Unit tests run without a database: the logger does not read the component details from it"""
|
|
8
|
+
monkeypatch.setattr(Component, "get_details_by_component_id", staticmethod(lambda component_id: {}))
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from devops_events_local.src.handle_request_to_open_a_jira_work_item import (
|
|
4
|
+
HandleRequestToOpenAJiraWorkItem,
|
|
5
|
+
RequestToOpenAJiraWorkItemParseException,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
handler = HandleRequestToOpenAJiraWorkItem()
|
|
9
|
+
|
|
10
|
+
EXPECTED = {"summary": "add-tests-yuval-rotich", "description": "Add unit tests",
|
|
11
|
+
"repo_name": "jira-local-python-package", "components": ["Python"]}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_parse_the_skill_format():
|
|
15
|
+
text = ("Summary: add-tests-yuval-rotich\nDescription: Add unit tests\n"
|
|
16
|
+
"RepoName: jira-local-python-package\nComponents: Python")
|
|
17
|
+
|
|
18
|
+
assert handler.parse(text) == EXPECTED
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_parse_slack_formatting_bold_code_block_quote_and_crlf():
|
|
22
|
+
text = ("```*Summary:* add-tests-yuval-rotich\r\n> _Description_: Add unit tests\r\n"
|
|
23
|
+
"`RepoName`: jira-local-python-package\r\n*Components*: Python```")
|
|
24
|
+
|
|
25
|
+
assert handler.parse(text) == EXPECTED
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_parse_labels_are_case_insensitive_and_allow_spaces_and_singular_component():
|
|
29
|
+
text = ("SUMMARY : add-tests-yuval-rotich\ndescription:Add unit tests\n"
|
|
30
|
+
"Repo Name: jira-local-python-package\ncomponent: Python")
|
|
31
|
+
|
|
32
|
+
assert handler.parse(text) == EXPECTED
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_parse_multi_line_description_until_next_label():
|
|
36
|
+
text = ("Summary: a-b\nDescription: first line\nsecond line: with a colon\n\n"
|
|
37
|
+
"RepoName: repo_name")
|
|
38
|
+
|
|
39
|
+
fields = handler.parse(text)
|
|
40
|
+
|
|
41
|
+
assert fields["description"] == "first line\nsecond line: with a colon"
|
|
42
|
+
assert fields["repo_name"] == "repo_name"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_parse_ignores_text_before_first_label_and_keeps_first_duplicate():
|
|
46
|
+
text = "Hi Tal, please open:\nSummary: first\nSummary: second\nDescription: d\nRepoName: repo"
|
|
47
|
+
|
|
48
|
+
assert handler.parse(text)["summary"] == "first"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_parse_components_optional_and_comma_separated():
|
|
52
|
+
base = "Summary: a-b\nDescription: d\nRepoName: repo"
|
|
53
|
+
|
|
54
|
+
assert handler.parse(base)["components"] == []
|
|
55
|
+
assert handler.parse(base + "\nComponents: Python, , Jira ")["components"] == \
|
|
56
|
+
["Python", "Jira"]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_parse_slack_links_and_html_entities():
|
|
60
|
+
text = ("Summary: a-b\nDescription: see <https://example.com/x|the doc> & <https://example.com/y> "
|
|
61
|
+
"<tag> <@U123>\nRepoName: <http://yuval.r-circlez.ai|yuval.r-circlez.ai>")
|
|
62
|
+
|
|
63
|
+
fields = handler.parse(text)
|
|
64
|
+
|
|
65
|
+
assert fields["description"] == "see the doc & https://example.com/y <tag> <@U123>"
|
|
66
|
+
assert fields["repo_name"] == "yuval.r-circlez.ai"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@pytest.mark.parametrize("text, missing", [
|
|
70
|
+
("", "Summary, Description, RepoName"),
|
|
71
|
+
(None, "Summary, Description, RepoName"),
|
|
72
|
+
("Summary: a-b\nRepoName: repo", "Description"),
|
|
73
|
+
("Summary: a-b\nDescription:\nRepoName: repo", "Description"),
|
|
74
|
+
("Description: d\nRepoName: repo", "Summary"),
|
|
75
|
+
("Summary: a-b\nDescription: d", "RepoName"),
|
|
76
|
+
])
|
|
77
|
+
def test_parse_missing_mandatory_fields(text, missing):
|
|
78
|
+
with pytest.raises(RequestToOpenAJiraWorkItemParseException) as exception_info:
|
|
79
|
+
handler.parse(text)
|
|
80
|
+
assert str(exception_info.value) == f"Missing {missing}"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_clean_slack_text_keeps_mailto_label():
|
|
84
|
+
assert handler.clean_slack_text("<mailto:a@b.c|a@b.c>") == "a@b.c"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.parametrize("text, expected", [
|
|
88
|
+
("Summary: a-b", True),
|
|
89
|
+
("*RepoName*: repo", True),
|
|
90
|
+
("thanks, done", False),
|
|
91
|
+
("", False),
|
|
92
|
+
(None, False),
|
|
93
|
+
])
|
|
94
|
+
def test_has_request_fields(text, expected):
|
|
95
|
+
assert handler.has_request_fields(text) is expected
|
|
@@ -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,33 @@
|
|
|
1
|
+
.env.local1.example
|
|
2
|
+
.env.play1.example
|
|
3
|
+
.flake8
|
|
4
|
+
.logger.json5
|
|
5
|
+
CODEOWNERS
|
|
6
|
+
README.md
|
|
7
|
+
__init__.py
|
|
8
|
+
component.local1.json5.example
|
|
9
|
+
pyproject.toml
|
|
10
|
+
pytest.ini
|
|
11
|
+
requirements-dev.txt
|
|
12
|
+
requirements.txt
|
|
13
|
+
setup.py
|
|
14
|
+
bin/cmd/profile.bat
|
|
15
|
+
bin/powershell/profile.ps1
|
|
16
|
+
bin/powershell/ExamplePowerShellModule/ExamplePowershellModule.psm1
|
|
17
|
+
bin/sh/profile.sh
|
|
18
|
+
bin/sh/run.sh
|
|
19
|
+
python_packages/devops_events_local/__init__.py
|
|
20
|
+
python_packages/devops_events_local.egg-info/PKG-INFO
|
|
21
|
+
python_packages/devops_events_local.egg-info/SOURCES.txt
|
|
22
|
+
python_packages/devops_events_local.egg-info/dependency_links.txt
|
|
23
|
+
python_packages/devops_events_local.egg-info/requires.txt
|
|
24
|
+
python_packages/devops_events_local.egg-info/top_level.txt
|
|
25
|
+
python_packages/devops_events_local/src/__init__.py
|
|
26
|
+
python_packages/devops_events_local/src/constants_src_devops_events_local.py
|
|
27
|
+
python_packages/devops_events_local/src/handle_request_to_open_a_jira_work_item.py
|
|
28
|
+
python_packages/devops_events_local/src/handle_slack_request.py
|
|
29
|
+
python_packages/devops_events_local/src/version.py
|
|
30
|
+
python_packages/devops_events_local/tests/__init__.py
|
|
31
|
+
python_packages/devops_events_local/tests/conftest.py
|
|
32
|
+
python_packages/devops_events_local/tests/unit/conftest.py
|
|
33
|
+
python_packages/devops_events_local/tests/unit/handle_request_to_open_a_jira_work_item_unit_test.py
|
devops_events_local-0.0.1b4163/python_packages/devops_events_local.egg-info/dependency_links.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
devops_events_local
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Requirements for Tests/Testing (Do not add to setup.py install_requires)
|
|
2
|
+
pytest # https://pypi.org/project/pytest/
|
|
3
|
+
pytest-cov # This is used by MakePy.ps1 pytest to simulate the tests running in GHA and save us time and money
|
|
4
|
+
# TODO When do we use this? - I think we are not using it in all packages
|
|
5
|
+
# pytest-mock
|
|
6
|
+
|
|
7
|
+
# TODO Do we need this in all packages?
|
|
8
|
+
# pycallgraph2
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# serverless.com repo "python -m build" works without setup.py
|
|
2
|
+
# Should update package_dir if not using our recommended directory structure
|
|
3
|
+
|
|
4
|
+
import setuptools
|
|
5
|
+
|
|
6
|
+
# For reading the version my_package/_version.py or my_package/__init__.py
|
|
7
|
+
|
|
8
|
+
import codecs
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def read(rel_path):
|
|
13
|
+
here = os.path.abspath(os.path.dirname(__file__))
|
|
14
|
+
with codecs.open(os.path.join(here, rel_path), 'r') as fp:
|
|
15
|
+
return fp.read()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_version(rel_path):
|
|
19
|
+
for line in read(rel_path).splitlines():
|
|
20
|
+
if line.startswith('__version__'):
|
|
21
|
+
return line.split('"')[1] # או "'" בהתאם לשימוש
|
|
22
|
+
raise RuntimeError("Unable to find version string.")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# TODO: Change the PACKAGE_NAME to the package's name - Either xxx-local or
|
|
26
|
+
# xxx-remote (without the -python-package suffix). Only lowercase, no
|
|
27
|
+
# underlines.
|
|
28
|
+
# Used by pypa/gh-action-pypi-publish
|
|
29
|
+
# Package Name should be identical to the inner directory name
|
|
30
|
+
# Changing the package name here, will cause a change in the package directory
|
|
31
|
+
# name as well
|
|
32
|
+
# PACKAGE_NAME should be singular if handling only one instance
|
|
33
|
+
# PACKAGE_NAME should not include the word "main"
|
|
34
|
+
|
|
35
|
+
# e.g.: queue-local, without python-package suffix
|
|
36
|
+
PACKAGE_NAME = "devops-events-local"
|
|
37
|
+
|
|
38
|
+
package_dir = PACKAGE_NAME.replace("-", "_")
|
|
39
|
+
# If we need backward-compatible:
|
|
40
|
+
# old_package_dir = "old_package_name"
|
|
41
|
+
|
|
42
|
+
PACKAGE_DESCRIPTION = f"PyPI {PACKAGE_NAME} Python Package owned by Circlez.ai"
|
|
43
|
+
|
|
44
|
+
setuptools.setup(
|
|
45
|
+
name=PACKAGE_NAME,
|
|
46
|
+
# Increase this number every time you make a change
|
|
47
|
+
# want to publish. After 0.0.9 switch to 0.0.10 and not 0.1.0
|
|
48
|
+
# version can't be 0.0.
|
|
49
|
+
# If you find yourself increasing the version in more than one patch number (it might indicate there are multiple branches, which you should submit their PRs before your PR) # noqa: E501
|
|
50
|
+
# Updating the b<Jira Work Item ID> done automatically by makec.ps1 / make_py.ps1
|
|
51
|
+
# TODO add the Jira Work Item (Jira Issue) number after the version, i.e., 0.0.1b2432
|
|
52
|
+
# TODO: According to GitFlow, in the Feature Branch, please update after the letter 'b' the Jira Work Item ID, and in the exceptional case you can't get a Jira Work Item directly or using the Slack Channel, please use the PR number. Semantic Version simver.org
|
|
53
|
+
version='0.0.1b4163', # https://pypi.org/project/devops-events-local#History
|
|
54
|
+
author="Circles",
|
|
55
|
+
author_email="info@circlez.ai",
|
|
56
|
+
description=f"{PACKAGE_DESCRIPTION}",
|
|
57
|
+
long_description=f"{PACKAGE_DESCRIPTION} \nGHA: https://github.com/circles-zone/devops-events-local-python-package/actions",
|
|
58
|
+
long_description_content_type='text/markdown',
|
|
59
|
+
url="https://github.com/circles-zone/devops-events-local-python-package",
|
|
60
|
+
# packages=[package_dir],
|
|
61
|
+
# packages=[package_dir, old_package_dir],
|
|
62
|
+
packages=setuptools.find_packages(where="python_packages", exclude=["*.tests", "*.tests.*"]),
|
|
63
|
+
package_dir={"": "python_packages"},
|
|
64
|
+
|
|
65
|
+
# I'm not sure we need package_dir
|
|
66
|
+
# package_dir={package_dir: f'{package_dir}/src'},
|
|
67
|
+
# TODO Unfortunately in event-main-local-restapi there are no
|
|
68
|
+
# repo-directory and no package directory (flat directory structure)
|
|
69
|
+
# package_dir={package_dir: f'src'},
|
|
70
|
+
|
|
71
|
+
# package_dir={package_dir: f'{package_dir}/src',
|
|
72
|
+
# old_package_dir: f'{package_dir}/src'},
|
|
73
|
+
classifiers=[
|
|
74
|
+
"Programming Language :: Python :: 3",
|
|
75
|
+
# https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license
|
|
76
|
+
# TODO Fix all repos, especially the Python templates
|
|
77
|
+
# "License :: MIT AND (Apache-2.0 OR BSD-2-Clause)",
|
|
78
|
+
"Operating System :: OS Independent",
|
|
79
|
+
],
|
|
80
|
+
# Do not add packages needed only for tests, i.e., packages for get_test_xxx(
|
|
81
|
+
# TODO: Update which packages to include with this package in production
|
|
82
|
+
# (dependencies) - Not for development/testing
|
|
83
|
+
install_requires=[
|
|
84
|
+
'python-sdk-remote',
|
|
85
|
+
# TODO: in -remote package, please use logger-remote instead.
|
|
86
|
+
'logger-local',
|
|
87
|
+
# TODO: In -local package, please uncomment the line below. In -remote packages, please delete this line. # noqa E501
|
|
88
|
+
# 'smart-datastore-local',
|
|
89
|
+
# 'logzio-python-handler>=4.1.2', # https://pypi.org/project/logzio-python-handler/ # noqa E501
|
|
90
|
+
]
|
|
91
|
+
)
|