Skip to content

Commit b805743

Browse files
authored
Merge pull request #37 from Integration-Automation/dev
fix: resolve open Sonar and Codacy findings; ship stable publish workflow
2 parents a349ebb + 3cf9029 commit b805743

16 files changed

Lines changed: 180 additions & 49 deletions

File tree

.bandit

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[bandit]
2+
exclude = /test
3+
skips = B101
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
name: Publish MailThunder Stable to PyPI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
paths-ignore:
7+
- '**.md'
8+
- 'docs/**'
9+
- '.github/**'
10+
11+
concurrency:
12+
group: publish-stable
13+
cancel-in-progress: false
14+
15+
jobs:
16+
test:
17+
permissions:
18+
contents: read
19+
runs-on: ${{ matrix.os }}
20+
strategy:
21+
fail-fast: true
22+
matrix:
23+
os: [ ubuntu-latest, windows-latest, macos-latest ]
24+
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
25+
26+
steps:
27+
- uses: actions/checkout@v4
28+
29+
- name: Set up Python ${{ matrix.python-version }}
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: ${{ matrix.python-version }}
33+
34+
- name: Install dependencies
35+
run: |
36+
python -m pip install --upgrade pip
37+
pip install pytest
38+
pip install -e .
39+
40+
- name: Run tests
41+
run: python -m pytest test/unit_test/ --ignore=test/unit_test/manual_test -v
42+
43+
publish:
44+
needs: test
45+
runs-on: ubuntu-latest
46+
permissions:
47+
contents: write
48+
steps:
49+
- uses: actions/checkout@v4
50+
with:
51+
ref: main
52+
token: ${{ secrets.GITHUB_TOKEN }}
53+
fetch-depth: 0
54+
55+
- name: Set up Python
56+
uses: actions/setup-python@v5
57+
with:
58+
python-version: "3.12"
59+
60+
- name: Install build tooling
61+
run: |
62+
python -m pip install --upgrade pip
63+
pip install build twine tomli tomli-w
64+
65+
- name: Bump patch version in pyproject.toml
66+
id: bump
67+
run: |
68+
python - <<'PY'
69+
import os
70+
import tomli
71+
import tomli_w
72+
73+
path = "pyproject.toml"
74+
with open(path, "rb") as handle:
75+
data = tomli.load(handle)
76+
77+
current = data["project"]["version"]
78+
major, minor, patch = (int(part) for part in current.split("."))
79+
patch += 1
80+
new_version = f"{major}.{minor}.{patch}"
81+
data["project"]["version"] = new_version
82+
83+
with open(path, "wb") as handle:
84+
tomli_w.dump(data, handle)
85+
86+
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as out:
87+
out.write(f"old_version={current}\n")
88+
out.write(f"new_version={new_version}\n")
89+
90+
print(f"Bumped version: {current} -> {new_version}")
91+
PY
92+
93+
- name: Build distributions
94+
run: python -m build
95+
96+
- name: Publish to PyPI
97+
env:
98+
TWINE_USERNAME: __token__
99+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
100+
run: python -m twine upload --non-interactive dist/*
101+
102+
- name: Commit and tag version bump
103+
run: |
104+
git config user.name "github-actions[bot]"
105+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
106+
git add pyproject.toml
107+
git commit -m "chore: bump stable version to ${{ steps.bump.outputs.new_version }}"
108+
git tag "v${{ steps.bump.outputs.new_version }}"
109+
git push origin main
110+
git push origin "v${{ steps.bump.outputs.new_version }}"
111+
112+
- name: Create GitHub Release
113+
env:
114+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
115+
run: |
116+
gh release create "v${{ steps.bump.outputs.new_version }}" \
117+
--title "v${{ steps.bump.outputs.new_version }}" \
118+
--notes "Automated stable release for v${{ steps.bump.outputs.new_version }}. Published to PyPI as \`je-mail-thunder==${{ steps.bump.outputs.new_version }}\`." \
119+
--target main \
120+
dist/*

dev.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Rename to dev version
22
# This is dev version
33
[build-system]
4-
requires = ["setuptools>=61.0"]
4+
requires = ["setuptools>=82.0.1"]
55
build-backend = "setuptools.build_meta"
66

77
[project]

je_mail_thunder/imap/imap_wrapper.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,10 @@ def _resolve_credentials():
4444
if user is not None and password is not None:
4545
return user, password
4646
env_info = get_mail_thunder_os_environ()
47-
if isinstance(env_info, dict):
48-
user = env_info.get("mail_thunder_user")
49-
password = env_info.get("mail_thunder_user_password")
50-
if user is not None and password is not None:
51-
return user, password
47+
user = env_info.get("mail_thunder_user")
48+
password = env_info.get("mail_thunder_user_password")
49+
if user is not None and password is not None:
50+
return user, password
5251
return None
5352

5453
def try_to_login_with_env_or_content(self):
@@ -90,7 +89,7 @@ def search_mailbox(self, search_str: [str, list] = "ALL", charset: str = None) -
9089
mail_thunder_logger.info(f"imap_search_mailbox, search_str: {search_str}, charset: {charset}")
9190
try:
9291
response, mail_number_string = self.search(charset, search_str)
93-
mail_detail_list = list()
92+
mail_detail_list = []
9493
for num_of_mail in mail_number_string[0].split():
9594
response, mail_data = self.fetch(num_of_mail, "(RFC822)")
9695
mail_data: List[List]
@@ -113,8 +112,8 @@ def mail_content_list(
113112
mail_thunder_logger.info(f"imap_mail_content_list, search_str: {search_str}, charset: {charset}")
114113
try:
115114
mail_list = self.search_mailbox(search_str, charset)
116-
mail_content_dict = dict()
117-
mail_content_list = list()
115+
mail_content_dict = {}
116+
mail_content_list = []
118117
for mail_data in mail_list:
119118
mail = mail_data[2]
120119
mail_content_dict.update({"SUBJECT": mail.get("Subject")})
@@ -129,7 +128,7 @@ def mail_content_list(
129128
body = str(decode_header(str(body))[0][0])
130129
mail_content_dict.update({"BODY": body})
131130
mail_content_list.append(mail_content_dict)
132-
mail_content_dict = dict()
131+
mail_content_dict = {}
133132
return mail_content_list
134133
except Exception as error:
135134
mail_thunder_logger.error(
@@ -163,7 +162,7 @@ def output_all_mail_as_file(
163162
mail_thunder_logger.info(f"imap_output_all_mail_as_file, search_str: {search_str}, charset: {charset}")
164163
try:
165164
all_mail = self.mail_content_list(search_str=search_str, charset=charset)
166-
same_name_dict: Dict[str, int] = dict()
165+
same_name_dict: Dict[str, int] = {}
167166
cwd = os.path.abspath(os.getcwd())
168167
for mail in all_mail:
169168
safe_name = self._sanitize_subject_as_filename(mail.get("SUBJECT"))

je_mail_thunder/smtp/smtp_wrapper.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,10 @@ def _resolve_credentials():
119119
if user is not None and password is not None:
120120
return user, password
121121
env_info = get_mail_thunder_os_environ()
122-
if isinstance(env_info, dict):
123-
user = env_info.get("mail_thunder_user")
124-
password = env_info.get("mail_thunder_user_password")
125-
if user is not None and password is not None:
126-
return user, password
122+
user = env_info.get("mail_thunder_user")
123+
password = env_info.get("mail_thunder_user_password")
124+
if user is not None and password is not None:
125+
return user, password
127126
return None
128127

129128
def try_to_login_with_env_or_content(self):

je_mail_thunder/utils/executor/action_executor.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import builtins
22
import types
33
from inspect import getmembers, isbuiltin
4+
from typing import Union
45

56
from je_mail_thunder.imap.imap_wrapper import imap_instance
67
from je_mail_thunder.smtp.smtp_wrapper import smtp_instance
@@ -52,7 +53,7 @@ def _execute_event(self, action: list):
5253
else:
5354
raise ExecuteActionException(cant_execute_action_error + " " + str(action))
5455

55-
def execute_action(self, action_list) -> dict:
56+
def execute_action(self, action_list: Union[list, dict]) -> dict:
5657
"""
5758
use to execute all action on action list(action file or program list)
5859
:param action_list the list include action
@@ -117,7 +118,7 @@ def add_command_to_executor(command_dict: dict):
117118
raise AddCommandException(add_command_exception)
118119

119120

120-
def execute_action(action_list: list) -> dict:
121+
def execute_action(action_list: Union[list, dict]) -> dict:
121122
return executor.execute_action(action_list)
122123

123124

je_mail_thunder/utils/json/json_file.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def read_action_json(json_file_path: str) -> list:
2323
)
2424
with open(json_file_path) as read_file:
2525
return json.loads(read_file.read())
26-
except (OSError, ValueError, json.JSONDecodeError) as error:
26+
except (OSError, ValueError) as error:
2727
raise JsonActionException(cant_find_json_error + f": {repr(error)}") from error
2828

2929

je_mail_thunder/utils/save_mail_user_content/mail_thunder_content_save.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from je_mail_thunder.utils.json_format.json_process import reformat_json
66
from je_mail_thunder.utils.save_mail_user_content.mail_thunder_content_data import mail_thunder_content_data_dict
77

8+
_CONTENT_FILENAME = "/mail_thunder_content.json"
89
_lock = Lock()
910

1011

@@ -14,9 +15,9 @@ def read_output_content():
1415
"""
1516
with _lock:
1617
cwd = str(Path.cwd())
17-
file_path = Path(cwd + "/mail_thunder_content.json")
18+
file_path = Path(cwd + _CONTENT_FILENAME)
1819
if file_path.exists() and file_path.is_file():
19-
with open(cwd + "/mail_thunder_content.json", "r+") as read_file:
20+
with open(cwd + _CONTENT_FILENAME, "r+") as read_file:
2021
user_info = json.loads(read_file.read())
2122
mail_thunder_content_data_dict.update(user_info)
2223
return user_info
@@ -29,5 +30,5 @@ def write_output_content():
2930
"""
3031
with _lock:
3132
cwd = str(Path.cwd())
32-
with open(cwd + "/mail_thunder_content.json", "w+") as file_to_write:
33+
with open(cwd + _CONTENT_FILENAME, "w+") as file_to_write:
3334
file_to_write.write(reformat_json(json.dumps(mail_thunder_content_data_dict)))

je_mail_thunder/utils/socket_server/mail_thunder_socket_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def handle(self):
5757
try:
5858
execute_str = json.loads(command_string)
5959
_validate_payload(execute_str)
60-
for _, execute_return in execute_action(execute_str).items():
60+
for execute_return in execute_action(execute_str).values():
6161
client_socket.sendto(str(execute_return).encode("utf-8"), self.client_address)
6262
client_socket.sendto("\n".encode("utf-8"), self.client_address)
6363
client_socket.sendto("Return_Data_Over_JE".encode("utf-8"), self.client_address)

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Rename to dev version
22
# This is dev version
33
[build-system]
4-
requires = ["setuptools>=61.0"]
4+
requires = ["setuptools>=82.0.1"]
55
build-backend = "setuptools.build_meta"
66

77
[project]
@@ -32,3 +32,7 @@ find = { namespaces = false }
3232

3333
[tool.pytest.ini_options]
3434
testpaths = ["test"]
35+
36+
[tool.bandit]
37+
exclude_dirs = ["test"]
38+
skips = ["B101"]

0 commit comments

Comments
 (0)