Honest CI: fix ruff lint and harden gates
CI / skip-ci-check (pull_request) Successful in 30s
CI / secret-scan (pull_request) Successful in 29s
CI / python-ci (pull_request) Failing after 46s

This commit is contained in:
2026-08-05 18:13:34 -04:00
parent 26fec1fcf6
commit e8d5354ca9
13 changed files with 21 additions and 30 deletions
+2 -2
View File
@@ -49,7 +49,7 @@ jobs:
pip install bandit pip-audit ruff --break-system-packages pip install bandit pip-audit ruff --break-system-packages
- name: Ruff lint - name: Ruff lint
run: ruff check . || true run: ruff check .
- name: Bandit (advisory) - name: Bandit (advisory)
run: bandit -r . -q || true run: bandit -r . -q || true
@@ -61,7 +61,7 @@ jobs:
run: | run: |
if [ -d tests ] || ls test_*.py *_test.py 2>/dev/null; then if [ -d tests ] || ls test_*.py *_test.py 2>/dev/null; then
pip install pytest --break-system-packages pip install pytest --break-system-packages
pytest -q || true pytest -q
else else
echo "No tests found — skip" echo "No tests found — skip"
fi fi
Regular → Executable
+3 -9
View File
@@ -171,9 +171,7 @@ def text_is_factual(text: str) -> bool:
return True return True
if DATA_PHONE.search(text) or DATA_MONEY.search(text) or DATA_EMAIL.search(text): if DATA_PHONE.search(text) or DATA_MONEY.search(text) or DATA_EMAIL.search(text):
return True return True
if DATA_ADDRESS.search(text) and DATA_DATE.search(text): return bool(DATA_ADDRESS.search(text) and DATA_DATE.search(text))
return True
return False
def looks_conversational(text: str) -> bool: def looks_conversational(text: str) -> bool:
@@ -184,9 +182,7 @@ def looks_conversational(text: str) -> bool:
if text.count("?") >= 2 and len(text) < 500: if text.count("?") >= 2 and len(text) < 500:
return True return True
# Short back-and-forth without hard facts. # Short back-and-forth without hard facts.
if len(text) < 80 and not has_data_signals(text): return len(text) < 80 and not has_data_signals(text)
return True
return False
def is_name_list_message(text: str) -> bool: def is_name_list_message(text: str) -> bool:
@@ -295,9 +291,7 @@ def msg_selection(
if latest_draft_files and fid in latest_draft_files: if latest_draft_files and fid in latest_draft_files:
files[fid] = True files[fid] = True
continue continue
if is_doc(f) or informative_filename(f.get("name") or ""): if is_doc(f) or informative_filename(f.get("name") or "") or is_image(f) and informative_image(f, text):
files[fid] = True
elif is_image(f) and informative_image(f, text):
files[fid] = True files[fid] = True
return { return {
"action": "import", "action": "import",
Regular → Executable
View File
Regular → Executable
View File
+5 -5
View File
@@ -9,8 +9,8 @@ import json
import mimetypes import mimetypes
import os import os
import sys import sys
import zipfile
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import zipfile
from datetime import datetime, timezone from datetime import datetime, timezone
from http import HTTPStatus from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
@@ -115,7 +115,7 @@ class ReviewHandler(BaseHTTPRequestHandler):
export: SlackExport export: SlackExport
manifest_path: Path manifest_path: Path
def log_message(self, format: str, *args) -> None: # noqa: A003 def log_message(self, format: str, *args) -> None:
if os.environ.get("SLACK_IMPORT_QUIET") != "1": if os.environ.get("SLACK_IMPORT_QUIET") != "1":
super().log_message(format, *args) super().log_message(format, *args)
@@ -166,14 +166,14 @@ class ReviewHandler(BaseHTTPRequestHandler):
except json.JSONDecodeError: except json.JSONDecodeError:
return None return None
def do_OPTIONS(self) -> None: # noqa: N802 def do_OPTIONS(self) -> None:
self.send_response(HTTPStatus.NO_CONTENT) self.send_response(HTTPStatus.NO_CONTENT)
self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
self.send_header("Access-Control-Allow-Headers", "Content-Type") self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.end_headers() self.end_headers()
def do_GET(self) -> None: # noqa: N802 def do_GET(self) -> None:
parsed = urlparse(self.path) parsed = urlparse(self.path)
path = parsed.path path = parsed.path
qs = parse_qs(parsed.query) qs = parse_qs(parsed.query)
@@ -364,7 +364,7 @@ class ReviewHandler(BaseHTTPRequestHandler):
self.send_error(HTTPStatus.NOT_FOUND) self.send_error(HTTPStatus.NOT_FOUND)
def do_POST(self) -> None: # noqa: N802 def do_POST(self) -> None:
parsed = urlparse(self.path) parsed = urlparse(self.path)
if parsed.path != "/api/manifest": if parsed.path != "/api/manifest":
self.send_error(HTTPStatus.NOT_FOUND) self.send_error(HTTPStatus.NOT_FOUND)
-1
View File
@@ -9,7 +9,6 @@ from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
DEFAULT_EXPORT = Path.home() / "Downloads" / "slack-export" DEFAULT_EXPORT = Path.home() / "Downloads" / "slack-export"
+1 -1
View File
@@ -60,7 +60,7 @@ def test_wilson_not_in_auto_channels(cherry_pick):
def test_dry_run_pick_count(cherry_pick, export, empty_manifest, tmp_path, monkeypatch): def test_dry_run_pick_count(cherry_pick, export, empty_manifest, tmp_path, monkeypatch):
path, manifest = empty_manifest _path, manifest = empty_manifest
monkeypatch.setattr(cherry_pick, "MANIFEST_PATH", tmp_path / "manifest.json") monkeypatch.setattr(cherry_pick, "MANIFEST_PATH", tmp_path / "manifest.json")
monkeypatch.setattr(cherry_pick, "DEFAULT_EXPORT", export.paths.root) monkeypatch.setattr(cherry_pick, "DEFAULT_EXPORT", export.paths.root)
+3 -3
View File
@@ -2,12 +2,11 @@
from __future__ import annotations from __future__ import annotations
import io
import json import json
import urllib.error import urllib.error
import urllib.request import urllib.request
import zipfile
from pathlib import Path from pathlib import Path
import pytest import pytest
@@ -117,9 +116,10 @@ def test_manifest_post_skips_non_dict_user(api):
def test_safe_export_path_rejects_dotdot(): def test_safe_export_path_rejects_dotdot():
from unittest.mock import Mock
import server import server
from slack_export import SlackExport from slack_export import SlackExport
from unittest.mock import Mock
root = Path(__file__).resolve().parents[1] / "tests/fixtures/mini-export" root = Path(__file__).resolve().parents[1] / "tests/fixtures/mini-export"
handler = Mock(spec=server.ReviewHandler) handler = Mock(spec=server.ReviewHandler)
+7 -2
View File
@@ -5,11 +5,16 @@ from __future__ import annotations
import io import io
import json import json
import zipfile import zipfile
from pathlib import Path
import pytest import pytest
from slack_export import SlackExport, load_json, resolve_paths, slack_ts_to_iso, user_display from slack_export import (
SlackExport,
load_json,
resolve_paths,
slack_ts_to_iso,
user_display,
)
def test_slack_ts_to_iso(): def test_slack_ts_to_iso():
-2
View File
@@ -3,8 +3,6 @@
from __future__ import annotations from __future__ import annotations
import json import json
import shutil
import sys
from pathlib import Path from pathlib import Path
import pytest import pytest
-2
View File
@@ -6,8 +6,6 @@ import importlib.util
import json import json
from pathlib import Path from pathlib import Path
import pytest
REPO = Path(__file__).resolve().parents[1] REPO = Path(__file__).resolve().parents[1]
-2
View File
@@ -2,8 +2,6 @@
from __future__ import annotations from __future__ import annotations
import json
def test_health(api): def test_health(api):
data = api["get"]("/api/health") data = api["get"]("/api/health")
-1
View File
@@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
import json import json
from pathlib import Path
import pytest import pytest