Skip to content

Commit 52160a0

Browse files
authored
Merge pull request #8 from topcoder-platform/feat/github-webhook
Github webhook implementation
2 parents f295d7c + 97adfa5 commit 52160a0

File tree

13 files changed

+847
-0
lines changed

13 files changed

+847
-0
lines changed

.env.sample

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
POSTGRES_SCHEMA="public"
22
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=${POSTGRES_SCHEMA}"
33

4+
5+
# Gitea Webhook Configuration
6+
GITEA_WEBHOOK_SECRET="your_webhook_secret_here"
7+
48
# Kafka Configuration
59
KAFKA_BROKERS=localhost:9092
610
KAFKA_CLIENT_ID=tc-review-api

docs/GITEA_WEBHOOK_SETUP.md

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
# Gitea Webhook Integration Setup and Testing Guide
2+
3+
## Overview
4+
5+
The Topcoder Review API includes a secure Gitea webhook integration that receives webhook events from Gitea repositories, validates them using HMAC-SHA256 signature verification, and stores them in the database for audit and future processing.
6+
7+
## Table of Contents
8+
9+
1. [Quick Start](#quick-start)
10+
2. [Environment Setup](#environment-setup)
11+
3. [Gitea Repository Configuration](#Gitea-repository-configuration)
12+
4. [Local Development Setup](#local-development-setup)
13+
5. [Testing the Integration](#testing-the-integration)
14+
6. [API Endpoint Reference](#api-endpoint-reference)
15+
7. [Database Schema](#database-schema)
16+
8. [Security Considerations](#security-considerations)
17+
9. [Troubleshooting](#troubleshooting)
18+
10. [Monitoring and Maintenance](#monitoring-and-maintenance)
19+
20+
## Quick Start
21+
22+
For immediate setup, follow these steps:
23+
24+
1. Generate a secure webhook secret
25+
2. Configure environment variables
26+
3. Set up Gitea webhook in repository settings
27+
4. Test with a sample event
28+
29+
## Environment Setup
30+
31+
### Required Environment Variables
32+
33+
Add the following environment variable to your application configuration:
34+
35+
```bash
36+
# .env file
37+
GITEA_WEBHOOK_SECRET=your_generated_secret_here
38+
```
39+
40+
### Generate Webhook Secret
41+
42+
**Using OpenSSL:**
43+
44+
```bash
45+
openssl rand -hex 32
46+
```
47+
48+
**Example Output:**
49+
50+
```
51+
a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
52+
```
53+
54+
⚠️ **Important:** Store this secret securely and use the same value in both your application environment and Gitea webhook configuration.
55+
56+
### Database Setup
57+
58+
The webhook integration requires the `gitWebhookLog` table. If not already created, run the database migration:
59+
60+
```bash
61+
npx prisma migrate dev
62+
```
63+
64+
## Gitea Repository Configuration
65+
66+
### Step 1: Access Repository Settings
67+
68+
1. Navigate to your Gitea repository
69+
2. Click on the **Settings** tab (requires admin permissions)
70+
3. In the left sidebar, click **Webhooks**
71+
4. Click **Add webhook**
72+
73+
### Step 2: Configure Webhook Settings
74+
75+
#### Payload URL
76+
77+
**Production/Staging Environment:**
78+
79+
```
80+
https://your-api-domain.com/v6/review/webhooks/gitea
81+
```
82+
83+
**Development Environment:**
84+
85+
```
86+
https://your-dev-domain.com/webhooks/gitea
87+
```
88+
89+
Note: The `/v6/review` prefix is only added in production when `NODE_ENV=production`.
90+
91+
#### Content Type
92+
93+
- Select `application/json`
94+
95+
#### Secret
96+
97+
- Enter the webhook secret you generated earlier
98+
- This must exactly match your `GITEA_WEBHOOK_SECRET` environment variable
99+
100+
#### SSL Verification
101+
102+
- Keep **Enable SSL verification** checked (recommended for production)
103+
- For development with proper HTTPS setup, this should remain enabled
104+
105+
### Step 3: Select Events
106+
107+
Choose one of the following options:
108+
109+
**Option A: Send Everything (Recommended for Testing)**
110+
111+
- Select "Send me everything" to receive all Gitea event types
112+
113+
**Option B: Select Individual Events**
114+
Common events for development workflows:
115+
116+
- **Pushes** - Code pushes to repository
117+
- **Pull requests** - PR creation, updates, merges
118+
- **Issues** - Issue creation, updates, comments
119+
- **Issue comments** - Comments on issues and PRs
120+
- **Releases** - Release creation and updates
121+
- **Create** - Branch or tag creation
122+
- **Delete** - Branch or tag deletion
123+
124+
### Step 4: Activate and Create
125+
126+
1. Ensure **Active** checkbox is checked
127+
2. Click **Add webhook**
128+
3. Gitea will automatically send a `ping` event to test the webhook
129+
130+
## Local Development Setup
131+
132+
Since Gitea webhooks require a publicly accessible URL, local development requires exposing your local server to the internet.
133+
134+
**Install ngrok:**
135+
136+
```bash
137+
npm install -g ngrok
138+
```
139+
140+
**Setup process:**
141+
142+
```bash
143+
# 1. Start your local API server
144+
pnpm run start:dev
145+
146+
# 2. In another terminal, expose your local server
147+
ngrok http 3000
148+
149+
# 3. Copy the HTTPS URL from ngrok output
150+
# Example: https://abc123.ngrok.io
151+
152+
# 4. Use this URL in Gitea webhook settings
153+
# https://abc123.ngrok.io/webhooks/gitea
154+
```
155+
156+
## Testing the Integration
157+
158+
### Manual Testing
159+
160+
#### 1. Verify Initial Setup
161+
162+
After creating the webhook, Gitea automatically sends a `ping` event:
163+
164+
1. Go to your repository's webhook settings
165+
2. Click on your webhook
166+
3. Check **Recent Deliveries** section
167+
4. Look for the `ping` event with status 200 OK
168+
169+
#### 2. Trigger Test Events
170+
171+
**Create a Push Event:**
172+
173+
```bash
174+
# Make a small change
175+
echo "webhook test" >> test-webhook.txt
176+
git add test-webhook.txt
177+
git commit -m "Test webhook integration"
178+
git push origin main
179+
```
180+
181+
**Create an Issue:**
182+
183+
1. Go to your repository on Gitea
184+
2. Click **Issues** tab
185+
3. Click **New issue**
186+
4. Create a test issue
187+
188+
**Create a Pull Request:**
189+
190+
1. Create a new branch: `git checkout -b test-webhook`
191+
2. Make changes and commit
192+
3. Push branch: `git push origin test-webhook`
193+
4. Open pull request on Gitea
194+
195+
### Testing with curl
196+
197+
You can test the webhook endpoint directly using curl with proper signature generation:
198+
199+
```bash
200+
#!/bin/bash
201+
202+
# Configuration
203+
WEBHOOK_URL="http://localhost:3000/webhooks/gitea" # Adjust for your environment
204+
WEBHOOK_SECRET="your_webhook_secret_here"
205+
PAYLOAD='{"test": "data", "repository": {"name": "test-repo"}}'
206+
DELIVERY_ID="test-delivery-$(date +%s)"
207+
EVENT_TYPE="push"
208+
209+
# Generate signature
210+
SIGNATURE="sha256=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | sed 's/^.* //')"
211+
212+
# Send test webhook
213+
curl -X POST "$WEBHOOK_URL" \
214+
-H "Content-Type: application/json" \
215+
-H "X-Gitea-Event: $EVENT_TYPE" \
216+
-H "X-Gitea-Delivery: $DELIVERY_ID" \
217+
-H "X-Hub-Signature-256: $SIGNATURE" \
218+
-d "$PAYLOAD"
219+
```
220+
221+
## API Endpoint Reference
222+
223+
### Webhook Endpoint
224+
225+
**URL:** `POST /webhooks/gitea` (development) or `POST /v6/review/webhooks/gitea` (production)
226+
227+
**Required Headers:**
228+
229+
- `Content-Type: application/json`
230+
- `X-Gitea-Event: {event_type}` - Gitea event type (push, pull_request, etc.)
231+
- `X-Gitea-Delivery: {delivery_id}` - Unique delivery identifier from Gitea
232+
- `X-Hub-Signature-256: sha256={signature}` - HMAC-SHA256 signature for verification
233+
234+
**Request Body:**
235+
236+
- Gitea webhook payload (varies by event type)
237+
238+
**Response Codes:**
239+
240+
- `200 OK` - Webhook processed successfully
241+
- `400 Bad Request` - Missing required headers or invalid payload
242+
- `403 Forbidden` - Invalid signature verification
243+
- `500 Internal Server Error` - Processing error or configuration issue
244+
245+
**Success Response:**
246+
247+
```json
248+
{
249+
"success": true,
250+
"message": "Webhook processed successfully"
251+
}
252+
```
253+
254+
**Error Response:**
255+
256+
```json
257+
{
258+
"statusCode": 403,
259+
"message": "Invalid signature",
260+
"error": "Forbidden",
261+
"timestamp": "2024-01-01T00:00:00.000Z",
262+
"path": "/webhooks/gitea"
263+
}
264+
```
265+
266+
## Database Schema
267+
268+
Webhook events are stored in the `gitWebhookLog` table:
269+
270+
```sql
271+
CREATE TABLE "gitWebhookLog" (
272+
"id" VARCHAR(14) NOT NULL DEFAULT nanoid(),
273+
"eventId" TEXT NOT NULL,
274+
"event" TEXT NOT NULL,
275+
"eventPayload" JSONB NOT NULL,
276+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
277+
278+
CONSTRAINT "gitWebhookLog_pkey" PRIMARY KEY ("id")
279+
);
280+
281+
-- Indexes for efficient querying
282+
CREATE INDEX "gitWebhookLog_eventId_idx" ON "gitWebhookLog"("eventId");
283+
CREATE INDEX "gitWebhookLog_event_idx" ON "gitWebhookLog"("event");
284+
CREATE INDEX "gitWebhookLog_createdAt_idx" ON "gitWebhookLog"("createdAt");
285+
```
286+
287+
### Query Examples
288+
289+
**View recent webhook events:**
290+
291+
```sql
292+
SELECT
293+
id,
294+
"eventId",
295+
event,
296+
"createdAt"
297+
FROM "gitWebhookLog"
298+
ORDER BY "createdAt" DESC
299+
LIMIT 10;
300+
```
301+
302+
**Filter by event type:**
303+
304+
```sql
305+
SELECT * FROM "gitWebhookLog"
306+
WHERE event = 'push'
307+
ORDER BY "createdAt" DESC;
308+
```
309+
310+
**View specific webhook payload:**
311+
312+
```sql
313+
SELECT
314+
event,
315+
"eventPayload"
316+
FROM "gitWebhookLog"
317+
WHERE "eventId" = 'your-delivery-id';
318+
```
319+
320+
## Security Considerations
321+
322+
### Signature Verification
323+
324+
The webhook implementation uses Gitea's recommended security practices:
325+
326+
1. **HMAC-SHA256 Signature:** All incoming webhooks are verified using HMAC-SHA256
327+
2. **Timing-Safe Comparison:** Uses `crypto.timingSafeEqual()` to prevent timing attacks
328+
3. **Secret Protection:** Webhook secrets are stored as environment variables
329+
4. **Header Validation:** Validates all required Gitea headers
330+
331+
### Best Practices
332+
333+
1. **Use HTTPS:** Always use HTTPS URLs for production webhooks
334+
2. **Rotate Secrets:** Periodically rotate webhook secrets
335+
3. **Monitor Access:** Regularly review webhook delivery logs
336+
4. **Limit Events:** Only subscribe to events you actually need
337+
5. **Access Control:** Restrict webhook configuration to repository administrators
338+
339+
### Environment Security
340+
341+
- Store `GITEA_WEBHOOK_SECRET` securely using your deployment platform's secret management
342+
- Never commit secrets to version control
343+
- Use different secrets for different environments
344+
- Implement proper secret rotation procedures
345+
346+
### Log Analysis
347+
348+
Key log messages to monitor:
349+
350+
```
351+
# Successful webhook processing
352+
[WebhookController] Successfully processed Gitea webhook
353+
354+
# Signature validation failures
355+
[GiteaSignatureGuard] Invalid webhook signature for delivery
356+
357+
# Configuration errors
358+
[GiteaSignatureGuard] Gitea_WEBHOOK_SECRET environment variable is not configured
359+
```
File renamed without changes.
File renamed without changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- CreateTable
2+
CREATE TABLE "gitWebhookLog" (
3+
"id" VARCHAR(14) NOT NULL DEFAULT nanoid(),
4+
"eventId" TEXT NOT NULL,
5+
"event" TEXT NOT NULL,
6+
"eventPayload" JSONB NOT NULL,
7+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
8+
9+
CONSTRAINT "gitWebhookLog_pkey" PRIMARY KEY ("id")
10+
);
11+
12+
-- CreateIndex
13+
CREATE INDEX "gitWebhookLog_eventId_idx" ON "gitWebhookLog"("eventId");
14+
15+
-- CreateIndex
16+
CREATE INDEX "gitWebhookLog_event_idx" ON "gitWebhookLog"("event");
17+
18+
-- CreateIndex
19+
CREATE INDEX "gitWebhookLog_createdAt_idx" ON "gitWebhookLog"("createdAt");

0 commit comments

Comments
 (0)