feat: Support GitLab webhooks in Lambda functions

This commit is contained in:
yoohya
2025-06-16 01:22:01 +09:00
parent cbea0380ec
commit 99904601ce
4 changed files with 70 additions and 12 deletions

View File

@ -1,4 +1,4 @@
FROM public.ecr.aws/lambda/python:3.12
FROM public.ecr.aws/lambda/python:3.12 AS base
RUN dnf update -y && \
dnf install -y gcc python3-devel git && \
@ -9,4 +9,10 @@ RUN pip install --no-cache-dir . && rm pyproject.toml
RUN pip install --no-cache-dir mangum==0.17.0
COPY pr_agent/ ${LAMBDA_TASK_ROOT}/pr_agent/
CMD ["pr_agent.servers.serverless.serverless"]
FROM base AS github_lambda
CMD ["pr_agent.servers.serverless.serverless_github"]
FROM base AS gitlab_lambda
CMD ["pr_agent.servers.serverless.serverless_gitlab"]
FROM github_lambda

View File

@ -187,7 +187,8 @@ For example: `GITHUB.WEBHOOK_SECRET` --> `GITHUB__WEBHOOK_SECRET`
2. Build a docker image that can be used as a lambda function
```shell
docker buildx build --platform=linux/amd64 . -t codiumai/pr-agent:serverless -f docker/Dockerfile.lambda
# Note: --target github_lambda is optional as it's the default target
docker buildx build --platform=linux/amd64 . -t codiumai/pr-agent:serverless --target github_lambda -f docker/Dockerfile.lambda
```
3. Push image to ECR

View File

@ -88,3 +88,50 @@ OPENAI__KEY=<your_openai_api_key>
8. Create a webhook in your GitLab project. Set the URL to `http[s]://<PR_AGENT_HOSTNAME>/webhook`, the secret token to the generated secret from step 3, and enable the triggers `push`, `comments` and `merge request events`.
9. Test your installation by opening a merge request or commenting on a merge request using one of PR Agent's commands.
## Deploy as a Lambda Function
Note that since AWS Lambda env vars cannot have "." in the name, you can replace each "." in an env variable with "__".<br>
For example: `GITLAB.PERSONAL_ACCESS_TOKEN` --> `GITLAB__PERSONAL_ACCESS_TOKEN`
1. Follow steps 1-5 from [Run a GitLab webhook server](#run-a-gitlab-webhook-server).
2. Build a docker image that can be used as a lambda function
```shell
docker buildx build --platform=linux/amd64 . -t codiumai/pr-agent:serverless --target gitlab_lambda -f docker/Dockerfile.lambda
```
3. Push image to ECR
```shell
docker tag codiumai/pr-agent:serverless <AWS_ACCOUNT>.dkr.ecr.<AWS_REGION>.amazonaws.com/codiumai/pr-agent:serverless
docker push <AWS_ACCOUNT>.dkr.ecr.<AWS_REGION>.amazonaws.com/codiumai/pr-agent:serverless
```
4. Create a lambda function that uses the uploaded image. Set the lambda timeout to be at least 3m.
5. Configure the lambda function to have a Function URL.
6. In the environment variables of the Lambda function, specify `AZURE_DEVOPS_CACHE_DIR` to a writable location such as /tmp. (see [link](https://github.com/Codium-ai/pr-agent/pull/450#issuecomment-1840242269))
7. Go back to steps 8-9 of [Run a GitLab webhook server](#run-a-gitlab-webhook-server) with the function url as your Webhook URL.
The Webhook URL would look like `https://<LAMBDA_FUNCTION_URL>/webhook`
### Using AWS Secrets Manager
For production Lambda deployments, use AWS Secrets Manager instead of environment variables:
1. Create a secret in AWS Secrets Manager with JSON format like this:
```json
{
"openai.key": "sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"gitlab.shared_secret": "your-shared-secret-from-step-3",
"gitlab.personal_access_token": "glpat-xxxxxxxxxxxxxxxxxxxxxxxx"
}
```
2. Add IAM permission `secretsmanager:GetSecretValue` to your Lambda execution role
3. Set these environment variables in your Lambda:
```bash
AWS_SECRETS_MANAGER__SECRET_ARN=arn:aws:secretsmanager:us-east-1:123456789012:secret:pr-agent-secrets-AbCdEf
CONFIG__SECRET_PROVIDER=aws_secrets_manager
```

View File

@ -3,8 +3,6 @@ from mangum import Mangum
from starlette.middleware import Middleware
from starlette_context.middleware import RawContextMiddleware
from pr_agent.servers.github_app import router
try:
from pr_agent.config_loader import apply_secrets_manager_config
apply_secrets_manager_config()
@ -16,12 +14,18 @@ except Exception as e:
# Fail completely silently if log module is not available
pass
middleware = [Middleware(RawContextMiddleware)]
app = FastAPI(middleware=middleware)
app.include_router(router)
def _create_handler(router):
middleware = [Middleware(RawContextMiddleware)]
app = FastAPI(middleware=middleware)
app.include_router(router)
return Mangum(app, lifespan="off")
handler = Mangum(app, lifespan="off")
def serverless(event, context):
def serverless_github(event, context):
from pr_agent.servers.github_app import router
handler = _create_handler(router)
return handler(event, context)
def serverless_gitlab(event, context):
from pr_agent.servers.gitlab_webhook import router
handler = _create_handler(router)
return handler(event, context)