修正
All checks were successful
Python Test / python-test (push) Successful in 10s

This commit is contained in:
ry.yamafuji 2025-12-05 00:44:16 +09:00
parent 02d6d34b02
commit f0a74c1122
8 changed files with 83 additions and 53 deletions

View File

@ -48,8 +48,19 @@ jobs:
- name: pull_request message with Ruff Lint results
id: prMessageRuffLint
run: |
curl -v -X POST \
-H "Content-Type: application/json" \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-d @lint-result.json \
${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/issues/8/comments
# イベントがプルリクエストの場合はPRにコメントを追加する
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "Posting Ruff Lint results to Pull Request..."
curl -v -X POST \
-H "Content-Type: application/json" \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-d @lint-result.json \
${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/issues/${{ github.event.pull_request.number }}/comments
else
echo "Not a pull request event."
echo "Ruff Lint results:"
echo "-------------------"
cat lint-result.md
echo "-------------------"
echo "No PR detected. Skipping API comment."
fi

2
.gitignore vendored
View File

@ -4,7 +4,9 @@ __pycache__/
*.py[cod]
*$py.class
ruff-report.*
lint-result.md
lint-result.json
# C extensions
*.so

View File

@ -1,15 +0,0 @@
## Linter(リンタ)レビュー
以下の指摘事項があります。コードを見直してください。
総数:6個
### 指摘事項一覧
|コード|重要性|項目|ファイル名|行数|
|---|---|---|---|---|
|W291|🟢低|行末に不要な空白があります。|examples/example.py|14行目27列 〜 14行目28列|
|W291|🟢低|行末に不要な空白があります。|scripts/generate_coverage.py|5行目23列 〜 5行目24列|
|E501|🟢低|行が長すぎます。79文字以内にしてください。|scripts/generate_coverage.py|38行目89列 〜 38行目107列|
|W291|🟢低|行末に不要な空白があります。|scripts/generate_linter_from_json.py|4行目23列 〜 4行目24列|
|W291|🟢低|行末に不要な空白があります。|scripts/generate_linter_from_json.py|25行目31列 〜 25行目39列|
|W292|🟢低|ファイルの最後に改行がありません。|scripts/generate_linter_from_json.py|53行目42列 〜 53行目42列|

View File

@ -1,6 +1,12 @@
line-length = 88
# 末尾スペース・空行まわりをチェックするのは E と W系のルール
# E7xx/E9xx構文/実行時エラーの可能性)
# W1xx/W5xxスタイル・フォーマット関連
# DXXXドキュメンテーション文字列関連
# F (未使用インポートなどのエラー)
# BXXバグの可能性
[lint]
select = ["E", "W"]
select = ["F", "E", "W", "D101", "B"]
ignore = []

View File

@ -2,9 +2,11 @@ import re
class GenerateCoverage:
def __init__(self,
coverage_file="pytest-coverage.txt",
output_file="coverage_table.md"):
"""カバレッジ結果を解析して Markdown テーブルを生成"""
def __init__(
self, coverage_file="pytest-coverage.txt", output_file="coverage_table.md"
):
"""
初期化
@ -35,26 +37,28 @@ class GenerateCoverage:
if in_coverage_section and line.strip().startswith("---"):
continue
# Coverage セクションの終わりを検出TOTAL行の次の空行
if in_coverage_section and (line.strip().startswith("TOTAL") or line.strip().startswith("=")):
if in_coverage_section and (
line.strip().startswith("TOTAL") or line.strip().startswith("=")
):
break
# Coverage データを抽出
if in_coverage_section:
match = re.match(
r"(.+?)\s+(\d+)\s+(\d+)\s+(\d+%)\s*(.*)", line)
match = re.match(r"(.+?)\s+(\d+)\s+(\d+)\s+(\d+%)\s*(.*)", line)
if match:
filename = match.group(1).strip()
statements = match.group(2).strip()
missed = match.group(3).strip()
coverage = match.group(4).strip()
missing_lines = match.group(
5).strip() if match.group(5) else "-"
coverage_info.append({
"filename": filename,
"statements": statements,
"missed": missed,
"coverage": coverage,
"missing_lines": missing_lines
})
missing_lines = match.group(5).strip() if match.group(5) else "-"
coverage_info.append(
{
"filename": filename,
"statements": statements,
"missed": missed,
"coverage": coverage,
"missing_lines": missing_lines,
}
)
self.coverage_data = coverage_info
@ -72,9 +76,11 @@ class GenerateCoverage:
# テーブル行を生成
table_rows = [
(f"| {data['filename']} | {data['statements']} | "
f"{data['missed']} | {data['coverage']} | "
f"{data['missing_lines']} |")
(
f"| {data['filename']} | {data['statements']} | "
f"{data['missed']} | {data['coverage']} | "
f"{data['missing_lines']} |"
)
for data in self.coverage_data
]

View File

@ -7,13 +7,18 @@ print(f"Project Name: {PROJECT_NAME}")
CODE_MAP = {
"W291": {"message": "行末に不要な空白があります。", "severity": "🟢低"},
"W292": {"message": "ファイルの最後に改行がありません。", "severity": "🟢低"} ,
"W292": {"message": "ファイルの最後に改行がありません。", "severity": "🟢低"},
"E501": {
"message": "行が長すぎます。79文字以内にしてください。",
"severity": "🟢低",
},
"D101": {
"message": "クラスにドキュメンテーション文字列がありません。",
"severity": "⚪️無害",
},
}
def get_relative_path(absolute_path: str) -> str:
"""
絶対パスからプロジェクトルートからの相対パスを取得
@ -26,7 +31,8 @@ def get_relative_path(absolute_path: str) -> str:
class GenerateLinter:
def __init__(self, json_file="ruff-report.json", output_file="lint-result.json"):
"""Linterレポートを生成するクラス"""
def __init__(self, json_file="ruff-report.json", output_file="lint-result"):
"""
初期化
"""
@ -46,43 +52,56 @@ class GenerateLinter:
_str += f"総数:{len(data)}\n"
_str += "### 指摘事項一覧\n"
_str += "|コード|重要性|項目|ファイル名|行数|\n"
_str += "|---|---|---|---|---|\n"
_str += "|コード|重要性|項目|ファイル名|行数|自動修正|\n"
_str += "|---|---|---|---|---|---|\n"
for issue in data:
code = issue.get("code", "-")
severity = (
CODE_MAP.get(code, {}).get("severity", "❓不明")
if code != "-"
else "-"
CODE_MAP.get(code, {}).get("severity", "❓不明") if code != "-" else "-"
)
message = CODE_MAP.get(code, {}).get("message", issue.get("message", "-"))
filename = get_relative_path(issue.get("filename", "-"))
file_link = f"./{filename}"
line = ""
if issue.get("location") and issue["location"].get("row"):
line = f"{issue['location']['row']}行目"
if issue["location"].get("column"):
line += f"{issue['location']['column']}"
if issue.get("end_location"):
if issue["end_location"].get("row"):
line += f"{issue['end_location']['row']}行目"
if issue["end_location"].get("column"):
line += f"{issue['end_location']['column']}"
auto_fix = "" if issue.get("fix") else ""
_str += f"|{code}|{severity}|{message}|"
_str += f"[{filename}]({file_link})|{line}|{auto_fix}|\n"
_str += "\n\n"
_str += "### 自動修正コマンド\n"
_str += ("自動修正が可能な指摘事項については、"
"以下のコマンドで自動修正を試みることができます。\n\n"
)
_str += "```bash\n"
_str += "ruff check --fix .\n"
_str += "```\n\n"
_str += f"|{code}|{severity}|{message}|{filename}|{line}|\n"
return _str
def generate_lint_report_json(self):
with open(self.json_file, "r") as f:
data = json.load(f)
with open(self.output_file, "w") as f:
# report_body = self._genarate_lint_report(data)
# f.write(report_body)
with open(f"{self.output_file}.md", "w") as f:
report_body = self._genarate_lint_report(data)
f.write(report_body)
with open(f"{self.output_file}.json", "w") as f:
report = {"body": self._genarate_lint_report(data)}
json.dump(report, f, ensure_ascii=False, indent=4)
print(f"Linter report generated: {self.output_file}")
print(f"Linter report generated: {self.output_file}.md, {self.output_file}.json")
if __name__ == "__main__":

View File

@ -11,6 +11,7 @@ import threading
class Singleton(object):
"""シングルトンパターンの基底クラス"""
_instances = {}
_lock = threading.Lock()