Skip to content

Commit bc4d548

Browse files
authored
Merge pull request #5 from telexintegrations:feat/fastapi-configuration
feat(core): configure router for forwarding github commits to telex
2 parents 3f2e6f7 + cfc4e6e commit bc4d548

File tree

7 files changed

+97
-7
lines changed

7 files changed

+97
-7
lines changed

.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ ALLOWED_ORIGINS=https://github.com,http://127.0.0.1:8000,http://0.0.0.0:8000,htt
44
ALLOWED_HOSTS=github.com,127.0.0.1,0.0.0.0,localhost,ping.telex.im
55
HOST=0.0.0.0
66
PORT=8000
7-
RELOAD_VALUE=True
7+
RELOAD_VALUE=True
8+
TELEX_WEBHOOK_URL=https://ping.telex.im/v1/webhooks
9+
CURL_COMMAND=curl

main.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from fastapi import FastAPI
2-
import uvicorn
3-
from src.config.config import settings
42
from src.config.middleware import middleware
3+
from src.routers.router import webhook_router
4+
from src.config.config import settings
5+
import uvicorn
56

67

78
app = FastAPI(docs_url="/", middleware=middleware)
9+
app.include_router(webhook_router)
810

911
if __name__ == "__main__":
1012
reload_value = settings.reload_value.lower() == "true"
11-
uvicorn.run("main:app", host=settings.host, port=settings.port, reload=reload_value)
13+
uvicorn.run("main:app", host=settings.host, port=settings.port, reload=reload_value)

requirements.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
annotated-types==0.7.0
22
anyio==4.8.0
3+
black==25.1.0
34
certifi==2025.1.31
45
click==8.1.8
56
dnspython==2.7.0
@@ -11,20 +12,27 @@ httpcore==1.0.7
1112
httptools==0.6.4
1213
httpx==0.28.1
1314
idna==3.10
15+
iniconfig==2.0.0
1416
itsdangerous==2.2.0
1517
Jinja2==3.1.5
1618
joblib==1.4.2
1719
markdown-it-py==3.0.0
1820
MarkupSafe==3.0.2
1921
mdurl==0.1.2
22+
mypy-extensions==1.0.0
2023
nltk==3.9.1
2124
numpy==2.2.3
2225
orjson==3.10.15
26+
packaging==24.2
27+
pathspec==0.12.1
28+
platformdirs==4.3.6
29+
pluggy==1.5.0
2330
pydantic==2.10.6
2431
pydantic-extra-types==2.10.2
2532
pydantic-settings==2.7.1
2633
pydantic_core==2.27.2
2734
Pygments==2.19.1
35+
pytest==8.3.4
2836
python-dotenv==1.0.1
2937
python-multipart==0.0.20
3038
PyYAML==6.0.2

src/config/config.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ class Settings(BaseSettings):
77
allowed_hosts: str
88
host: str
99
port: int
10-
reload_value: str
11-
10+
reload_value: str
11+
telex_webhook_url: str
12+
curl_command: str | None = "curl" # might require path/to/curl e.g. `/usr/bin/curl`
13+
1214
model_config = SettingsConfigDict(env_file=".env")
1315

1416

1517
@lru_cache
1618
def get_settings() -> Settings:
1719
return Settings()
1820

19-
settings = get_settings()
21+
22+
settings = get_settings()

src/routers/github.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from fastapi.routing import APIRouter
2+
from ..core.models import GitHubPayload, TelexWebhookPayload
3+
from ..config.config import settings
4+
from ..utils.telex_utils import send_payload_to_telex
5+
from fastapi.responses import JSONResponse
6+
from fastapi import status, HTTPException
7+
import json
8+
9+
10+
router = APIRouter(prefix="/github")
11+
12+
13+
@router.post("/{telex_channel_id}", status_code=status.HTTP_200_OK)
14+
async def github_webhook(telex_channel_id: str, payload: GitHubPayload):
15+
"""Endpoint to receive GitHub webhook events and forward the commits to Telex"""
16+
# Payload in format required by Telex channels' webhooks
17+
telex_payload = TelexWebhookPayload(
18+
event_name="pushed_commits",
19+
message=str(payload.commits),
20+
status="success",
21+
username=payload.pusher["name"],
22+
).model_dump_json()
23+
24+
# Telex channel webhook URL
25+
telex_url = f"{settings.telex_webhook_url}/{telex_channel_id}"
26+
27+
try:
28+
# Send payload to Telex
29+
response = await send_payload_to_telex(telex_payload, telex_url)
30+
response_data = json.loads(response.decode().strip())
31+
except Exception as e:
32+
raise HTTPException(
33+
status_code=status.HTTP_400_BAD_REQUEST,
34+
detail=f"Telex payload sending failed: {str(e)}",
35+
)
36+
37+
return JSONResponse(content={"data": response_data})

src/routers/router.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from fastapi.routing import APIRouter
2+
from .github import router as github_router
3+
4+
5+
webhook_router = APIRouter(prefix="/api/v1/webhook")
6+
webhook_router.include_router(github_router)

src/utils/telex_utils.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import asyncio
2+
from ..config.config import settings
3+
from fastapi import HTTPException, status
4+
5+
6+
async def send_payload_to_telex(telex_payload: str, telex_url: str):
7+
"""Sends payload through an asynchronous curl subprocess"""
8+
curl_command = [
9+
settings.curl_command,
10+
"-X",
11+
"POST",
12+
telex_url,
13+
"-H",
14+
"Accept: application/json",
15+
"-H",
16+
"Content-Type: application/json",
17+
"-d",
18+
telex_payload,
19+
]
20+
process = await asyncio.create_subprocess_exec(
21+
*curl_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
22+
)
23+
stdout, stderr = await process.communicate()
24+
25+
# Check for exit on error
26+
if process.returncode != 0:
27+
raise HTTPException(
28+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
29+
detail=f"Subprocess exception: {stderr.decode().strip()}",
30+
)
31+
32+
return stdout

0 commit comments

Comments
 (0)