Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b97b77a
Apply PR #878 changes: Add task correlation fields and structured log…
myakove Nov 7, 2025
f294792
Update Dockerfile: Add systemd-machine-id-setup and manual hub instal…
myakove Nov 7, 2025
59c4bc9
Fix pyproject.toml deprecation warning and update log parser tests
myakove Nov 7, 2025
e34c493
Update uv.lock after dependency group changes
myakove Nov 7, 2025
da5099e
Apply changes from feature/graphql-migration to app.py (excluding Gra…
myakove Nov 7, 2025
69bfa02
Fix pre-commit errors and apply PR review comments
myakove Nov 7, 2025
5c9a2c7
Complete all Archon tasks: non-GraphQL improvements
myakove Nov 7, 2025
4e274e9
Fix RuntimeWarning and increase test coverage to 90.49%
myakove Nov 7, 2025
305beb0
Fix TRY003 violations and Wellcome typo
myakove Nov 7, 2025
034a754
Fix code quality issues: logger.exception, tag regex, shutil.rmtree, …
myakove Nov 8, 2025
eec48d5
Fix async mocking in tests and improve log viewer consistency
myakove Nov 8, 2025
0406049
fix: Replace Mock with AsyncMock for all async method patches in tests
myakove Nov 8, 2025
be95e2a
test: optimize test_api_with_malformed_parameters by mocking disk I/O
myakove Nov 8, 2025
684d467
test: improve test assertions and fix async mock usage
myakove Nov 8, 2025
63efd01
fix: implement stateless MCP session manager for fastapi-mcp 0.4.0 co…
myakove Nov 8, 2025
740154f
fix: Address CodeRabbit AI review comments
myakove Nov 8, 2025
e00e015
fix: wrap PyGithub blocking calls in asyncio.to_thread() to prevent e…
myakove Nov 9, 2025
1ac3619
fix: add missing token spend logging and PR flow completion
myakove Nov 9, 2025
1b63f4d
catching GithubException, not global Exception
myakove Nov 9, 2025
47359b1
revert catching GithubException, not global Exception
myakove Nov 9, 2025
07d4330
add log_prefix to all log statements across codebase
myakove Nov 9, 2025
996e5f8
fix: handle GHCR packages owned by users with fallback mechanism
myakove Nov 9, 2025
97ac034
feat: make _redact_secrets() honor mask-sensitive-data config
myakove Nov 9, 2025
d3d7d94
fix: add default values for IP verification config lookups
myakove Nov 9, 2025
a40d1f1
fix: correct EN DASH character and is_merged() method call
myakove Nov 9, 2025
466a406
perf: optimize OWNERS handler with caching and parallelization
myakove Nov 9, 2025
9e10190
fix: ensure webhook_processing completion log always runs and remove …
myakove Nov 9, 2025
88a29fd
refactor: convert owners_data_for_changed_files to cached_property
myakove Nov 9, 2025
a85b8dd
refactor: consolidate webhook completion logging
myakove Nov 9, 2025
0fc5a67
feat: parallelize slash command execution in PR comments
myakove Nov 9, 2025
d5654b7
fix: add logging for webhook processing when no PR found
myakove Nov 9, 2025
7e5eff8
fix: ensure log parser timestamps are timezone-aware
myakove Nov 10, 2025
ee384d6
test: update test_log_parser.py to expect timezone-aware datetimes
myakove Nov 10, 2025
56e9aa9
fix: use pattern parameter in monitor_log_directory
myakove Nov 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ webhook-server.private-key.pem
log-colors.json
webhook_server/tests/manifests/logs
.coverage_report.txt
coverage.json
webhook-examples
find_unused_code.py

# AI
.cursor/
Expand All @@ -159,3 +162,4 @@ CLAUDE.md
.claude/
.claude-flow/
.swarm/
CRUSH.md
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,13 @@ repos:
- id: mypy
exclude: (tests/)
additional_dependencies: [types-requests, types-PyYAML, types-colorama]

- repo: https://github.com/pre-commit/mirrors-eslint
rev: v9.38.0
hooks:
- id: eslint
files: \.js$
exclude: eslint\.config\.js
args: [--fix]
additional_dependencies:
- eslint@9.38.0
12 changes: 10 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ ENV PATH="$PATH:$BIN_DIR"
ENV DATA_DIR="$HOME_DIR/data"
ENV APP_DIR="$HOME_DIR/github-webhook-server"

RUN systemd-machine-id-setup

RUN dnf -y install dnf-plugins-core \
&& dnf -y update \
&& dnf -y install \
git \
hub \
unzip \
gcc \
python3-devel \
Expand Down Expand Up @@ -51,6 +52,7 @@ ENV UV_PYTHON=python3.13
ENV UV_COMPILE_BYTECODE=1
ENV UV_NO_SYNC=1
ENV UV_CACHE_DIR=${APP_DIR}/.cache
ENV PYTHONUNBUFFERED=1

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx ${BIN_DIR}/
RUN uv tool install pre-commit && uv tool install poetry && uv tool install prek
Expand All @@ -62,7 +64,13 @@ RUN set -x \
&& chmod +x $BIN_DIR/rosa \
&& rm -rf $BIN_DIR/rosa-linux.tar.gz \
&& curl -L https://github.com/regclient/regclient/releases/latest/download/regctl-linux-amd64 >$BIN_DIR/regctl \
&& chmod +x $BIN_DIR/regctl
&& chmod +x $BIN_DIR/regctl \
&& curl -L https://github.com/mislav/hub/releases/download/v2.14.2/hub-linux-amd64-2.14.2.tgz --output ${BIN_DIR}/hub-linux-amd64.tgz \
&& tmp_dir="$(mktemp -d)" \
&& tar xvf ${BIN_DIR}/hub-linux-amd64.tgz -C "${tmp_dir}" \
&& mv "${tmp_dir}"/hub-linux-amd64-2.14.2/bin/hub ${BIN_DIR}/hub \
&& chmod +x ${BIN_DIR}/hub \
&& rm -rf "${tmp_dir}" ${BIN_DIR}/hub-linux-amd64.tgz

WORKDIR $APP_DIR

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ GitHub Events → Webhook Server → Repository Management
└─────────────────────────────────────┘
```

**Key Architecture Components:**

- **Performance Optimized**: Repository data fetched efficiently to minimize API calls
- **Type-Safe**: Full mypy strict mode coverage ensuring code reliability

## Features

### 🔧 Repository Management
Expand Down
7 changes: 7 additions & 0 deletions entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ def run_podman_cleanup() -> None:
run_podman_cleanup()

result = asyncio.run(repository_and_webhook_settings(webhook_secret=_webhook_secret))

# Logging Configuration:
# - Uvicorn uses default logging which automatically respects FORCE_COLOR environment variable
# for colored terminal output (useful for Docker logs with color support)
# - Application logs use simple-logger with console=True for colored output in Docker logs
# - Both logging systems work together: uvicorn handles HTTP request logs,
# while simple-logger handles application-level logs with structured formatting
uvicorn.run(
"webhook_server.app:FASTAPI_APP",
host=_ip_bind,
Expand Down
92 changes: 92 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
module.exports = [
// Frontend configuration - for browser-based JavaScript
{
files: ["webhook_server/web/static/**/*.js"],
languageOptions: {
ecmaVersion: 2022,
sourceType: "script",
globals: {
// Browser environment globals
window: "readonly",
document: "readonly",
console: "readonly",
fetch: "readonly",
WebSocket: "readonly",
localStorage: "readonly",
sessionStorage: "readonly",
alert: "readonly",
confirm: "readonly",
prompt: "readonly",
setTimeout: "readonly",
clearTimeout: "readonly",
setInterval: "readonly",
clearInterval: "readonly",
URLSearchParams: "readonly",
AbortController: "readonly",
},
},
Comment thread
myakove marked this conversation as resolved.
rules: {
// ESLint recommended rules (manually specified for broader coverage)
"constructor-super": "error",
"for-direction": "error",
"getter-return": "error",
"no-async-promise-executor": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-const-assign": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-args": "error",
"no-dupe-class-members": "error",
"no-dupe-else-if": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-fallthrough": "error",
"no-func-assign": "error",
"no-global-assign": "error",
"no-import-assign": "error",
"no-inner-declarations": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-new-symbol": "error",
"no-obj-calls": "error",
"no-octal": "error",
"no-prototype-builtins": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-setter-return": "error",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "error",
"no-unexpected-multiline": "error",
"no-unreachable": "error",
"no-unsafe-finally": "error",
"no-unsafe-negation": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-labels": "error",
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-with": "error",
"require-yield": "error",
"use-isnan": "error",
"valid-typeof": "error",
// Project-specific overrides
"no-unused-vars": "warn",
"no-undef": "error",
"no-console": "off",
},
},
];
26 changes: 14 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ line-length = 120
fix = true
output-format = "grouped"

[tool.ruff.lint]
select = ["E", "F", "W", "I", "B", "UP", "PLC0415", "ARG"]

[tool.ruff.lint.per-file-ignores]
"webhook_server/tests/*" = ["ARG"]

[tool.ruff.format]
exclude = [".git", ".venv", ".mypy_cache", ".tox", "__pycache__"]

Expand All @@ -33,20 +39,11 @@ warn_redundant_casts = true
[tool.hatch.build.targets.wheel]
packages = ["webhook_server"]

[tool.uv]
dev-dependencies = [
"ipdb>=0.13.13",
"ipython>=8.12.3",
"types-colorama>=0.4.15.20240311",
"types-pyyaml>=6.0.12.20250516",
"types-requests>=2.32.4.20250611",
]

[project]
name = "github-webhook-server"
version = "3.0.7"
requires-python = ">=3.12"
description = "A webhook server to manage Github reposotories and pull requests."
description = "A webhook server to manage Github repositories and pull requests."
readme = "README.md"
license = "Apache-2.0"
classifiers = [
Expand Down Expand Up @@ -101,6 +98,11 @@ requires = ["hatchling"]
build-backend = "hatchling.build"

[dependency-groups]
tests = [
"psutil>=7.0.0",
dev = [
"ipdb>=0.13.13",
"ipython>=8.12.3",
"types-colorama>=0.4.15.20240311",
"types-pyyaml>=6.0.12.20250516",
"types-requests>=2.32.4.20250611",
]
tests = ["psutil>=7.0.0", "pytest-asyncio>=0.26.0", "pytest-xdist>=3.7.0"]
13 changes: 9 additions & 4 deletions scripts/generate_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ def json_line(line: str) -> dict:
Format str line to str that can be parsed with json.

In case line is not formatted for json for example:
'{"title": "Revert "feat: Use git cliff to generate the change log. (#2322)" (#2324)", "commit": "137331fd", "author": "Meni Yakove", "date": "2025-02-16"}'
title have `"` inside the external `"` `"Revert "feat: Use git cliff to generate the change log. (#2322)" (#2324)"`
'{"title": "Revert "feat: Use git cliff to generate the change log. (#2322)" '
'(#2324)", "commit": "137331fd", "author": "Meni Yakove", "date": "2025-02-16"}'
title have `"` inside the external `"` `"Revert "feat: Use git cliff to '
'generate the change log. (#2322)" (#2324)"`
"""
try:
return json.loads(line)
except json.JSONDecodeError:
# split line like by `,`
# '{"title": "Revert "feat: Use git cliff to generate the change log. (#2322)" (#2324)", "commit": "137331fd", "author": "Meni Yakove", "date": "2025-02-16"}'
# '{"title": "Revert "feat: Use git cliff to generate the change log. '
# '(#2322)" (#2324)", "commit": "137331fd", "author": "Meni Yakove", '
# '"date": "2025-02-16"}'
line_split = line.split(",")

# Pop and save `title key` and `title body` from '{"title": "Revert "feat: Use git cliff to generate the change log. (#2322)" (#2324)"'
# Pop and save `title key` and `title body` from '{"title": "Revert '
# '"feat: Use git cliff to generate the change log. (#2322)" (#2324)"'
title_key, title_body = line_split.pop(0).split(":", 1)

if title_body.count('"') > 2:
Expand Down
Loading