package main import ( "bytes" "encoding/json" "flag" "fmt" "io" "net/http" "os" "strconv" ) func main() { // Define command-line flags var forgejoAPIURL string var token string var repoOwner string var repoName string var issueId int flag.StringVar(&forgejoAPIURL, "forgejo-api-url", "https://code.252.no/api/v1", "Forgejo API URL") flag.StringVar(&token, "token", "", "Forgejo API token") flag.StringVar(&repoOwner, "repo-owner", "", "Repository owner") flag.StringVar(&repoName, "repo-name", "", "Repository name") flag.IntVar(&issueId, "issue-id", 0, "Issue id") flag.Parse() // Get the diff file from the positional arguments args := flag.Args() if len(args) < 1 { fmt.Println("Usage: forgejo-comment ") os.Exit(1) } diffFile := args[0] // Read environment variables if flags are not set if forgejoAPIURL == "" { forgejoAPIURL = os.Getenv("FORGEJO_API_URL") if forgejoAPIURL == "" { fmt.Println("Error: FORGEJO_API_URL is not set") os.Exit(1) } } if token == "" { token = os.Getenv("FORGEJO_TOKEN") if token == "" { fmt.Println("Error: FORGEJO_TOKEN is not set") os.Exit(1) } } if repoOwner == "" { repoOwner = os.Getenv("REPO_OWNER") if repoOwner == "" { fmt.Println("Error: REPO_OWNER is not set") os.Exit(1) } } if repoName == "" { repoName = os.Getenv("REPO_NAME") if repoName == "" { fmt.Println("Error: REPO_NAME is not set") os.Exit(1) } } if issueId == 0 { issueIdEnv := os.Getenv("ISSUE_ID") if issueIdEnv == "" { fmt.Println("Error: ISSUE_ID is not set") os.Exit(1) } var err error issueId, err = strconv.Atoi(issueIdEnv) if err != nil { fmt.Println("Error: Invalid ISSUE_ID") os.Exit(1) } } // Read the diff file diffContentBytes, err := os.ReadFile(diffFile) if err != nil { fmt.Printf("Error reading diff file: %v\n", err) os.Exit(1) } // Prepare the comment content diffContent := string(diffContentBytes) commentBody := fmt.Sprintf("```diff\n%s\n```", diffContent) // Prepare the request payload payload := map[string]string{ "body": commentBody, } payloadBytes, err := json.Marshal(payload) if err != nil { fmt.Printf("Error marshaling payload: %v\n", err) os.Exit(1) } // Construct the API URL apiURL := fmt.Sprintf("%s/repos/%s/%s/issues/%d/comments", forgejoAPIURL, repoOwner, repoName, issueId) // Create the HTTP request req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(payloadBytes)) if err != nil { fmt.Printf("Error creating request: %v\n", err) os.Exit(1) } req.Header.Set("Authorization", fmt.Sprintf("token %s", token)) req.Header.Set("Content-Type", "application/json") // Send the request client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error sending request: %v\n", err) os.Exit(1) } defer resp.Body.Close() // Read the response body respBody, err := io.ReadAll(resp.Body) if err != nil { fmt.Printf("Error reading response: %v\n", err) os.Exit(1) } // Check the response status code if resp.StatusCode != 201 { fmt.Printf("Failed to post comment. HTTP status: %d\n", resp.StatusCode) fmt.Printf("Response body: %s\n", string(respBody)) os.Exit(1) } else { fmt.Printf("Posted diff to Forgejo issue #%d\n", issueId) } }