-
Notifications
You must be signed in to change notification settings - Fork 666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Improved server, security and commands #529
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import json | ||
import os | ||
|
||
import uvicorn | ||
from fastapi import APIRouter, FastAPI | ||
|
@@ -13,35 +14,55 @@ | |
from pr_agent.agent.pr_agent import PRAgent | ||
from pr_agent.config_loader import get_settings | ||
from pr_agent.log import get_logger | ||
from pr_agent.servers.utils import verify_signature | ||
|
||
router = APIRouter() | ||
|
||
|
||
def handle_request(background_tasks: BackgroundTasks, url: str, body: str, log_context: dict): | ||
def handle_request( | ||
background_tasks: BackgroundTasks, url: str, body: str, log_context: dict | ||
): | ||
log_context["action"] = body | ||
log_context["event"] = "pull_request" if body == "review" else "comment" | ||
log_context["api_url"] = url | ||
with get_logger().contextualize(**log_context): | ||
background_tasks.add_task(PRAgent().handle_request, url, body) | ||
|
||
|
||
@router.post("/webhook") | ||
@router.post("/") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you change the webhook endpoint to /? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
async def handle_webhook(background_tasks: BackgroundTasks, request: Request): | ||
log_context = {"server_type": "bitbucket_server"} | ||
data = await request.json() | ||
get_logger().info(json.dumps(data)) | ||
|
||
pr_id = data['pullRequest']['id'] | ||
repository_name = data['pullRequest']['toRef']['repository']['slug'] | ||
project_name = data['pullRequest']['toRef']['repository']['project']['key'] | ||
webhook_secret = get_settings().get("BITBUCKET_SERVER.WEBHOOK_SECRET", None) | ||
if webhook_secret: | ||
body_bytes = await request.body() | ||
signature_header = request.headers.get("x-hub-signature", None) | ||
verify_signature(body_bytes, webhook_secret, signature_header) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you verify that it works as expected? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes it works... the HMAC method is the same as GitHub just the header has a slightly different name (without -256) |
||
|
||
pr_id = data["pullRequest"]["id"] | ||
repository_name = data["pullRequest"]["toRef"]["repository"]["slug"] | ||
project_name = data["pullRequest"]["toRef"]["repository"]["project"]["key"] | ||
bitbucket_server = get_settings().get("BITBUCKET_SERVER.URL") | ||
pr_url = f"{bitbucket_server}/projects/{project_name}/repos/{repository_name}/pull-requests/{pr_id}" | ||
|
||
log_context["api_url"] = pr_url | ||
log_context["event"] = "pull_request" | ||
|
||
handle_request(background_tasks, pr_url, "review", log_context) | ||
return JSONResponse(status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"})) | ||
if data["eventKey"] == "pr:opened": | ||
body = "review" | ||
elif data["eventKey"] == "pr:comment:added": | ||
body = data["comment"]["text"] | ||
else: | ||
return JSONResponse( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should return 200 in this case, this is not an error, unless you know differently? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well we can, but you have to configure which events you want to be pushed as webhook. If you push some events that are not supported it could be a bad request, or could be a 200 and who cares or, could also be a 501 not implemented which makes also sense. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm asking before in some cases, after a certain threshold of errors the webhook is disabled. |
||
status_code=status.HTTP_400_BAD_REQUEST, | ||
content=json.dumps({"message": "Unsupported event"}), | ||
) | ||
|
||
handle_request(background_tasks, pr_url, body, log_context) | ||
return JSONResponse( | ||
status_code=status.HTTP_200_OK, content=jsonable_encoder({"message": "success"}) | ||
) | ||
|
||
|
||
@router.get("/") | ||
|
@@ -50,15 +71,10 @@ async def root(): | |
|
||
|
||
def start(): | ||
bitbucket_server_url = get_settings().get("BITBUCKET_SERVER.URL", None) | ||
if not bitbucket_server_url: | ||
raise ValueError("BITBUCKET_SERVER.URL is not set") | ||
get_settings().config.git_provider = "bitbucket_server" | ||
middleware = [Middleware(RawContextMiddleware)] | ||
app = FastAPI(middleware=middleware) | ||
app = FastAPI(middleware=[Middleware(RawContextMiddleware)]) | ||
app.include_router(router) | ||
uvicorn.run(app, host="0.0.0.0", port=3000) | ||
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", "3000"))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please change this to BITBUCKET_SERVER.PORT, use get_settings().get(), add to configuration file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's like this because some cloud providers uses an environment variable PORT to bind the ingress... also in https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/servers/bitbucket_app.py#L162 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can't complain on my own code :( |
||
|
||
|
||
if __name__ == '__main__': | ||
if __name__ == "__main__": | ||
start() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you change the parenthesis styling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Black... I linted and formatted with black