-
Notifications
You must be signed in to change notification settings - Fork 5
Github webhook implementation #8
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,359 @@ | ||
# Gitea Webhook Integration Setup and Testing Guide | ||
|
||
## Overview | ||
|
||
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. | ||
|
||
## Table of Contents | ||
|
||
1. [Quick Start](#quick-start) | ||
2. [Environment Setup](#environment-setup) | ||
3. [Gitea Repository Configuration](#Gitea-repository-configuration) | ||
4. [Local Development Setup](#local-development-setup) | ||
5. [Testing the Integration](#testing-the-integration) | ||
6. [API Endpoint Reference](#api-endpoint-reference) | ||
7. [Database Schema](#database-schema) | ||
8. [Security Considerations](#security-considerations) | ||
9. [Troubleshooting](#troubleshooting) | ||
10. [Monitoring and Maintenance](#monitoring-and-maintenance) | ||
|
||
## Quick Start | ||
|
||
For immediate setup, follow these steps: | ||
|
||
1. Generate a secure webhook secret | ||
2. Configure environment variables | ||
3. Set up Gitea webhook in repository settings | ||
4. Test with a sample event | ||
|
||
## Environment Setup | ||
|
||
### Required Environment Variables | ||
|
||
Add the following environment variable to your application configuration: | ||
|
||
```bash | ||
# .env file | ||
GITEA_WEBHOOK_SECRET=your_generated_secret_here | ||
``` | ||
|
||
### Generate Webhook Secret | ||
|
||
**Using OpenSSL:** | ||
|
||
```bash | ||
openssl rand -hex 32 | ||
``` | ||
|
||
**Example Output:** | ||
|
||
``` | ||
a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456 | ||
``` | ||
|
||
⚠️ **Important:** Store this secret securely and use the same value in both your application environment and Gitea webhook configuration. | ||
|
||
### Database Setup | ||
|
||
The webhook integration requires the `gitWebhookLog` table. If not already created, run the database migration: | ||
|
||
```bash | ||
npx prisma migrate dev | ||
``` | ||
|
||
## Gitea Repository Configuration | ||
|
||
### Step 1: Access Repository Settings | ||
|
||
1. Navigate to your Gitea repository | ||
2. Click on the **Settings** tab (requires admin permissions) | ||
3. In the left sidebar, click **Webhooks** | ||
4. Click **Add webhook** | ||
|
||
### Step 2: Configure Webhook Settings | ||
|
||
#### Payload URL | ||
|
||
**Production/Staging Environment:** | ||
|
||
``` | ||
https://your-api-domain.com/v6/review/webhooks/gitea | ||
``` | ||
|
||
**Development Environment:** | ||
|
||
``` | ||
https://your-dev-domain.com/webhooks/gitea | ||
``` | ||
|
||
Note: The `/v6/review` prefix is only added in production when `NODE_ENV=production`. | ||
|
||
#### Content Type | ||
|
||
- Select `application/json` | ||
|
||
#### Secret | ||
|
||
- Enter the webhook secret you generated earlier | ||
- This must exactly match your `GITEA_WEBHOOK_SECRET` environment variable | ||
|
||
#### SSL Verification | ||
|
||
- Keep **Enable SSL verification** checked (recommended for production) | ||
- For development with proper HTTPS setup, this should remain enabled | ||
|
||
### Step 3: Select Events | ||
|
||
Choose one of the following options: | ||
|
||
**Option A: Send Everything (Recommended for Testing)** | ||
|
||
- Select "Send me everything" to receive all Gitea event types | ||
|
||
**Option B: Select Individual Events** | ||
Common events for development workflows: | ||
|
||
- **Pushes** - Code pushes to repository | ||
- **Pull requests** - PR creation, updates, merges | ||
- **Issues** - Issue creation, updates, comments | ||
- **Issue comments** - Comments on issues and PRs | ||
- **Releases** - Release creation and updates | ||
- **Create** - Branch or tag creation | ||
- **Delete** - Branch or tag deletion | ||
|
||
### Step 4: Activate and Create | ||
|
||
1. Ensure **Active** checkbox is checked | ||
2. Click **Add webhook** | ||
3. Gitea will automatically send a `ping` event to test the webhook | ||
|
||
## Local Development Setup | ||
|
||
Since Gitea webhooks require a publicly accessible URL, local development requires exposing your local server to the internet. | ||
|
||
**Install ngrok:** | ||
|
||
```bash | ||
npm install -g ngrok | ||
``` | ||
|
||
**Setup process:** | ||
|
||
```bash | ||
# 1. Start your local API server | ||
pnpm run start:dev | ||
|
||
# 2. In another terminal, expose your local server | ||
ngrok http 3000 | ||
|
||
# 3. Copy the HTTPS URL from ngrok output | ||
# Example: https://abc123.ngrok.io | ||
|
||
# 4. Use this URL in Gitea webhook settings | ||
# https://abc123.ngrok.io/webhooks/gitea | ||
``` | ||
|
||
## Testing the Integration | ||
|
||
### Manual Testing | ||
|
||
#### 1. Verify Initial Setup | ||
|
||
After creating the webhook, Gitea automatically sends a `ping` event: | ||
|
||
1. Go to your repository's webhook settings | ||
2. Click on your webhook | ||
3. Check **Recent Deliveries** section | ||
4. Look for the `ping` event with status 200 OK | ||
|
||
#### 2. Trigger Test Events | ||
|
||
**Create a Push Event:** | ||
|
||
```bash | ||
# Make a small change | ||
echo "webhook test" >> test-webhook.txt | ||
git add test-webhook.txt | ||
git commit -m "Test webhook integration" | ||
git push origin main | ||
``` | ||
|
||
**Create an Issue:** | ||
|
||
1. Go to your repository on Gitea | ||
2. Click **Issues** tab | ||
3. Click **New issue** | ||
4. Create a test issue | ||
|
||
**Create a Pull Request:** | ||
|
||
1. Create a new branch: `git checkout -b test-webhook` | ||
2. Make changes and commit | ||
3. Push branch: `git push origin test-webhook` | ||
4. Open pull request on Gitea | ||
|
||
### Testing with curl | ||
|
||
You can test the webhook endpoint directly using curl with proper signature generation: | ||
|
||
```bash | ||
#!/bin/bash | ||
|
||
# Configuration | ||
WEBHOOK_URL="http://localhost:3000/webhooks/gitea" # Adjust for your environment | ||
WEBHOOK_SECRET="your_webhook_secret_here" | ||
PAYLOAD='{"test": "data", "repository": {"name": "test-repo"}}' | ||
DELIVERY_ID="test-delivery-$(date +%s)" | ||
EVENT_TYPE="push" | ||
|
||
# Generate signature | ||
SIGNATURE="sha256=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | sed 's/^.* //')" | ||
|
||
# Send test webhook | ||
curl -X POST "$WEBHOOK_URL" \ | ||
-H "Content-Type: application/json" \ | ||
-H "X-Gitea-Event: $EVENT_TYPE" \ | ||
-H "X-Gitea-Delivery: $DELIVERY_ID" \ | ||
-H "X-Hub-Signature-256: $SIGNATURE" \ | ||
-d "$PAYLOAD" | ||
``` | ||
|
||
## API Endpoint Reference | ||
|
||
### Webhook Endpoint | ||
|
||
**URL:** `POST /webhooks/gitea` (development) or `POST /v6/review/webhooks/gitea` (production) | ||
|
||
**Required Headers:** | ||
|
||
- `Content-Type: application/json` | ||
- `X-Gitea-Event: {event_type}` - Gitea event type (push, pull_request, etc.) | ||
- `X-Gitea-Delivery: {delivery_id}` - Unique delivery identifier from Gitea | ||
- `X-Hub-Signature-256: sha256={signature}` - HMAC-SHA256 signature for verification | ||
|
||
**Request Body:** | ||
|
||
- Gitea webhook payload (varies by event type) | ||
|
||
**Response Codes:** | ||
|
||
- `200 OK` - Webhook processed successfully | ||
- `400 Bad Request` - Missing required headers or invalid payload | ||
- `403 Forbidden` - Invalid signature verification | ||
- `500 Internal Server Error` - Processing error or configuration issue | ||
|
||
**Success Response:** | ||
|
||
```json | ||
{ | ||
"success": true, | ||
"message": "Webhook processed successfully" | ||
} | ||
``` | ||
|
||
**Error Response:** | ||
|
||
```json | ||
{ | ||
"statusCode": 403, | ||
"message": "Invalid signature", | ||
"error": "Forbidden", | ||
"timestamp": "2024-01-01T00:00:00.000Z", | ||
"path": "/webhooks/gitea" | ||
} | ||
``` | ||
|
||
## Database Schema | ||
|
||
Webhook events are stored in the `gitWebhookLog` table: | ||
|
||
```sql | ||
CREATE TABLE "gitWebhookLog" ( | ||
"id" VARCHAR(14) NOT NULL DEFAULT nanoid(), | ||
"eventId" TEXT NOT NULL, | ||
"event" TEXT NOT NULL, | ||
"eventPayload" JSONB NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
|
||
CONSTRAINT "gitWebhookLog_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- Indexes for efficient querying | ||
CREATE INDEX "gitWebhookLog_eventId_idx" ON "gitWebhookLog"("eventId"); | ||
CREATE INDEX "gitWebhookLog_event_idx" ON "gitWebhookLog"("event"); | ||
CREATE INDEX "gitWebhookLog_createdAt_idx" ON "gitWebhookLog"("createdAt"); | ||
``` | ||
|
||
### Query Examples | ||
|
||
**View recent webhook events:** | ||
|
||
```sql | ||
SELECT | ||
id, | ||
"eventId", | ||
event, | ||
"createdAt" | ||
FROM "gitWebhookLog" | ||
ORDER BY "createdAt" DESC | ||
LIMIT 10; | ||
``` | ||
|
||
**Filter by event type:** | ||
|
||
```sql | ||
SELECT * FROM "gitWebhookLog" | ||
WHERE event = 'push' | ||
ORDER BY "createdAt" DESC; | ||
``` | ||
|
||
**View specific webhook payload:** | ||
|
||
```sql | ||
SELECT | ||
event, | ||
"eventPayload" | ||
FROM "gitWebhookLog" | ||
WHERE "eventId" = 'your-delivery-id'; | ||
``` | ||
|
||
## Security Considerations | ||
|
||
### Signature Verification | ||
|
||
The webhook implementation uses Gitea's recommended security practices: | ||
|
||
1. **HMAC-SHA256 Signature:** All incoming webhooks are verified using HMAC-SHA256 | ||
2. **Timing-Safe Comparison:** Uses `crypto.timingSafeEqual()` to prevent timing attacks | ||
3. **Secret Protection:** Webhook secrets are stored as environment variables | ||
4. **Header Validation:** Validates all required Gitea headers | ||
|
||
### Best Practices | ||
|
||
1. **Use HTTPS:** Always use HTTPS URLs for production webhooks | ||
2. **Rotate Secrets:** Periodically rotate webhook secrets | ||
3. **Monitor Access:** Regularly review webhook delivery logs | ||
4. **Limit Events:** Only subscribe to events you actually need | ||
5. **Access Control:** Restrict webhook configuration to repository administrators | ||
|
||
### Environment Security | ||
|
||
- Store `GITEA_WEBHOOK_SECRET` securely using your deployment platform's secret management | ||
- Never commit secrets to version control | ||
- Use different secrets for different environments | ||
- Implement proper secret rotation procedures | ||
|
||
### Log Analysis | ||
|
||
Key log messages to monitor: | ||
|
||
``` | ||
# Successful webhook processing | ||
[WebhookController] Successfully processed Gitea webhook | ||
|
||
# Signature validation failures | ||
[GiteaSignatureGuard] Invalid webhook signature for delivery | ||
|
||
# Configuration errors | ||
[GiteaSignatureGuard] Gitea_WEBHOOK_SECRET environment variable is not configured | ||
``` |
File renamed without changes.
File renamed without changes.
19 changes: 19 additions & 0 deletions
19
prisma/migrations/20250802073602_gitea_webhook/migration.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
-- CreateTable | ||
CREATE TABLE "gitWebhookLog" ( | ||
"id" VARCHAR(14) NOT NULL DEFAULT nanoid(), | ||
"eventId" TEXT NOT NULL, | ||
"event" TEXT NOT NULL, | ||
"eventPayload" JSONB NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
|
||
CONSTRAINT "gitWebhookLog_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "gitWebhookLog_eventId_idx" ON "gitWebhookLog"("eventId"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "gitWebhookLog_event_idx" ON "gitWebhookLog"("event"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "gitWebhookLog_createdAt_idx" ON "gitWebhookLog"("createdAt"); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.