Skip to content

Instantly share code, notes, and snippets.

@Sdy603
Created August 30, 2024 21:15
Show Gist options
  • Save Sdy603/44278c769ba0ef54f44b2c0a0e20e590 to your computer and use it in GitHub Desktop.
Save Sdy603/44278c769ba0ef54f44b2c0a0e20e590 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"time"
)
// Struct for the DX Pipelines API payload
type DXPipelinesAPIPayload struct {
PipelineName string `json:"pipeline_name"`
PipelineSource string `json:"pipeline_source"`
ReferenceID string `json:"reference_id"`
StartedAt string `json:"started_at"`
Status string `json:"status,omitempty"`
FinishedAt string `json:"finished_at,omitempty"`
Repository string `json:"repository,omitempty"`
CommitSha string `json:"commit_sha,omitempty"`
PRNumber int `json:"pr_number,omitempty"`
SourceURL string `json:"source_url,omitempty"`
HeadBranch string `json:"head_branch,omitempty"`
Email string `json:"email,omitempty"`
GitHubUsername string `json:"github_username,omitempty"`
}
func main() {
http.HandleFunc("/webhook", handleWebhook)
log.Println("Starting server on :8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleWebhook(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Could not read request body", http.StatusInternalServerError)
return
}
var data map[string]interface{}
if err := json.Unmarshal(body, &data); err != nil {
http.Error(w, "Could not parse webhook data", http.StatusBadRequest)
return
}
dxPayload := transformToDXPayload(data)
err = sendToDXPipelineAPI(dxPayload)
if err != nil {
log.Printf("Error sending data to DX Pipelines API: %v\n", err)
http.Error(w, "Failed to forward payload to DX Pipelines API", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Webhook received, processed, and forwarded to DX Pipelines API"))
}
func transformToDXPayload(data map[string]interface{}) DXPipelinesAPIPayload {
objectAttributes := data["object_attributes"].(map[string]interface{})
project := data["project"].(map[string]interface{})
user := data["user"].(map[string]interface{})
// Convert created_at and finished_at to Unix timestamp if present
startedAt := convertToUnixTimestamp(objectAttributes["created_at"].(string))
finishedAt := convertToUnixTimestamp(objectAttributes["finished_at"].(string))
return DXPipelinesAPIPayload{
PipelineName: project["name"].(string),
PipelineSource: "GitLab",
ReferenceID: fmt.Sprintf("%v", objectAttributes["id"]),
StartedAt: startedAt,
Status: mapStatus(objectAttributes["status"].(string)),
FinishedAt: finishedAt,
Repository: project["path_with_namespace"].(string),
CommitSha: objectAttributes["sha"].(string),
SourceURL: objectAttributes["url"].(string),
HeadBranch: objectAttributes["ref"].(string),
Email: user["email"].(string),
GitHubUsername: user["username"].(string), // If GitHubUsername is equivalent to GitLab username
}
}
func convertToUnixTimestamp(timeStr string) string {
if timeStr == "" {
return ""
}
t, err := time.Parse(time.RFC3339, timeStr)
if err != nil {
return ""
}
return fmt.Sprintf("%d", t.Unix())
}
func mapStatus(status string) string {
switch status {
case "success":
return "success"
case "failed":
return "failure"
case "running":
return "running"
case "canceled":
return "cancelled"
default:
return "unknown"
}
}
func sendToDXPipelineAPI(payload DXPipelinesAPIPayload) error {
dxAPIURL := "https://young-test.getdx.net/api/pipelineRuns.sync"
authToken := "ZtKBJPuD21XGYjM46L4PPSf1VBPYQfFE" // Replace with your actual token
payloadBytes, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("error marshaling payload to JSON: %w", err)
}
req, err := http.NewRequest("POST", dxAPIURL, bytes.NewBuffer(payloadBytes))
if err != nil {
return fmt.Errorf("error creating HTTP request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+authToken)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("error sending request to DX Pipelines API: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
bodyBytes, _ := io.ReadAll(resp.Body)
return fmt.Errorf("received non-200 response from DX Pipelines API: %d - %s", resp.StatusCode, string(bodyBytes))
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment