Add Github Webhook data

Change-Id: I69417685de1264b10f60fc4c74e290890cdb0a67
diff --git a/server/git/webhook_test.go b/server/git/webhook_test.go
new file mode 100644
index 0000000..d19b27f
--- /dev/null
+++ b/server/git/webhook_test.go
@@ -0,0 +1,189 @@
+package git
+
+import (
+	"encoding/json"
+	"testing"
+	"time"
+)
+
+func TestProcessMergeWebhook(t *testing.T) {
+	// Create a sample GitHub webhook payload for a merged PR
+	webhookPayload := GitHubWebhook{
+		Action: "closed",
+		Number: 123,
+		PullRequest: &GitHubPullRequest{
+			ID:     456,
+			Number: 123,
+			State:  "closed",
+			Title:  "Add solution for task-123",
+			Merged: true,
+			MergedAt: func() *time.Time {
+				t := time.Now()
+				return &t
+			}(),
+			MergedBy: &User{
+				Login: "testuser",
+				ID:    789,
+			},
+			Head: &PullRequestBranch{
+				Ref: "solution/task-123",
+				SHA: "abc123def456",
+			},
+			Base: &PullRequestBranch{
+				Ref: "main",
+				SHA: "def456ghi789",
+			},
+		},
+		Repository: &Repository{
+			Name:     "test-repo",
+			FullName: "testuser/test-repo",
+		},
+		Sender: &User{
+			Login: "testuser",
+			ID:    789,
+		},
+	}
+
+	// Convert to JSON
+	payload, err := json.Marshal(webhookPayload)
+	if err != nil {
+		t.Fatalf("Failed to marshal webhook payload: %v", err)
+	}
+
+	// Test signature validation (this will fail without proper secret)
+	_, err = ProcessMergeWebhook(payload, "sha256=invalid", "test-secret")
+	if err == nil {
+		t.Error("Expected signature validation to fail with invalid signature")
+	}
+
+	// Test with valid signature (you would need to generate this properly in a real test)
+	// For now, we'll test the parsing and validation logic separately
+	webhook, err := ParseWebhook(payload)
+	if err != nil {
+		t.Fatalf("Failed to parse webhook: %v", err)
+	}
+
+	if !IsValidMergeEvent(webhook) {
+		t.Error("Expected webhook to be a valid merge event")
+	}
+
+	taskID, err := ExtractTaskID(webhook.PullRequest.Head.Ref)
+	if err != nil {
+		t.Fatalf("Failed to extract task ID: %v", err)
+	}
+
+	if taskID != "task-123" {
+		t.Errorf("Expected task ID 'task-123', got '%s'", taskID)
+	}
+
+	// Test GetWebhookInfo function
+	info := GetWebhookInfo(webhook)
+	if info["action"] != "closed" {
+		t.Errorf("Expected action 'closed', got '%v'", info["action"])
+	}
+	if info["pr_title"] != "Add solution for task-123" {
+		t.Errorf("Expected title 'Add solution for task-123', got '%v'", info["pr_title"])
+	}
+	if info["head_ref"] != "solution/task-123" {
+		t.Errorf("Expected head_ref 'solution/task-123', got '%v'", info["head_ref"])
+	}
+}
+
+func TestExtractTaskID(t *testing.T) {
+	tests := []struct {
+		branchName string
+		expected   string
+		shouldErr  bool
+	}{
+		{"solution/task-123", "task-123", false},
+		{"subtasks/task-456", "task-456", false},
+		{"feature/new-feature", "", true},
+		{"main", "", true},
+		{"solution/", "", true},
+		{"subtasks/", "", true},
+	}
+
+	for _, test := range tests {
+		taskID, err := ExtractTaskID(test.branchName)
+		if test.shouldErr {
+			if err == nil {
+				t.Errorf("Expected error for branch '%s', but got none", test.branchName)
+			}
+		} else {
+			if err != nil {
+				t.Errorf("Unexpected error for branch '%s': %v", test.branchName, err)
+			}
+			if taskID != test.expected {
+				t.Errorf("Expected task ID '%s' for branch '%s', got '%s'", test.expected, test.branchName, taskID)
+			}
+		}
+	}
+}
+
+func TestIsValidMergeEvent(t *testing.T) {
+	tests := []struct {
+		name     string
+		webhook  *GitHubWebhook
+		expected bool
+	}{
+		{
+			name: "valid merge event",
+			webhook: &GitHubWebhook{
+				Action: "closed",
+				PullRequest: &GitHubPullRequest{
+					Merged: true,
+					Head:   &PullRequestBranch{Ref: "solution/task-123"},
+				},
+			},
+			expected: true,
+		},
+		{
+			name: "not closed",
+			webhook: &GitHubWebhook{
+				Action: "opened",
+				PullRequest: &GitHubPullRequest{
+					Merged: true,
+					Head:   &PullRequestBranch{Ref: "solution/task-123"},
+				},
+			},
+			expected: false,
+		},
+		{
+			name: "not merged",
+			webhook: &GitHubWebhook{
+				Action: "closed",
+				PullRequest: &GitHubPullRequest{
+					Merged: false,
+					Head:   &PullRequestBranch{Ref: "solution/task-123"},
+				},
+			},
+			expected: false,
+		},
+		{
+			name: "no pull request",
+			webhook: &GitHubWebhook{
+				Action: "closed",
+			},
+			expected: false,
+		},
+		{
+			name: "no head branch",
+			webhook: &GitHubWebhook{
+				Action: "closed",
+				PullRequest: &GitHubPullRequest{
+					Merged: true,
+				},
+			},
+			expected: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			result := IsValidMergeEvent(test.webhook)
+			if result != test.expected {
+				t.Errorf("Expected %v, got %v", test.expected, result)
+			}
+		})
+	}
+}