#!/usr/bin/env python3 import json import hmac import hashlib from fastapi.testclient import TestClient import types # Import your server module import webhook_endpoint as srv # Ensure safe test config toggles srv.GITHUB_DRY_RUN = True srv.BUGZILLA_ATTACH_DIFF = False # Enable mirroring flag and replace pr_mirror with a fake srv.GITEA_MIRROR_PR_ENABLE = True # Fake PR mirror class FakePRMirror: def __init__(self): self.calls = [] def mirror(self, gh_owner: str, gh_repo: str, pr_number: int, pr_title: str, pr_body: str): self.calls.append({ "owner": gh_owner, "repo": gh_repo, "pr_number": pr_number, "title": pr_title, "body": pr_body, }) # Pretend we created PR #101 on Gitea return 101 fake_mirror = FakePRMirror() srv.pr_mirror = fake_mirror # monkeypatch the orchestrator in the module # Also monkeypatch Bugzilla client to avoid real writes class FakeBZ: def create_bug(self, summary, description, component): return 99999 def update_bug_fields(self, bug_id, fields): pass def add_attachment(self, *a, **k): pass def add_cc(self, *a, **k): pass def add_or_update_author_email_note(self, *a, **k): pass srv.bz = FakeBZ() # Build app client client = TestClient(srv.app) def sign(secret: str, body: bytes) -> str: return "sha256=" + hmac.new(secret.encode("utf-8"), body, hashlib.sha256).hexdigest() def payload(action="opened"): return { "action": action, "repository": { "full_name": "Koozali-SME-Server/smeserver-manager", "owner": {"login": "Koozali-SME-Server"}, "name": "smeserver-manager", }, "pull_request": { "number": 42, "html_url": "https://github.com/Koozali-SME-Server/smeserver-manager/pull/42", "title": "Improve logging", "body": "Please review.", "user": {"login": "octocat", "html_url": "https://github.com/octocat"}, "base": {"ref": "master", "sha": "9f8e7d6cafebabe0000deadbeef0000000000000"}, "head": {"ref": "feature/logs", "sha": "a1b2c3ddeeddbb0000deadbeef0000000000000", "repo": {"owner": {"login": "octocat"}}}, "created_at": "2025-09-17T12:34:56Z", "labels": [{"name": "enhancement"}], }, } def run_test(): body = json.dumps(payload("opened")).encode("utf-8") # Use the server's configured secret (or set one here) secret = srv.WEBHOOK_SECRET or "devsecret" headers = { "X-GitHub-Event": "pull_request", "X-Hub-Signature-256": sign(secret, body), "Content-Type": "application/json", } # If you run this without setting WEBHOOK_SECRET in env, also set it here: if not srv.WEBHOOK_SECRET: # monkeypatch the verify function to use our secret def verify_signature(secret_arg, *a, **k): return srv.verify_signature(secret, *a, **k) srv.verify_signature = verify_signature resp = client.post("/webhook/github", data=body, headers=headers) print("Response:", resp.status_code, resp.json()) print("Mirror calls recorded:", fake_mirror.calls) assert resp.status_code == 200 assert resp.json().get("status") in ("ok", "bugzilla_failed") # ok path returns "ok" assert any(c["pr_number"] == 42 for c in fake_mirror.calls), "Mirror was not invoked" if __name__ == "__main__": run_test()