2024-11-12 09:12:42 +00:00
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"strconv"
)
2024-11-27 17:15:30 +00:00
func getEnv ( key , defaultVal string ) string {
if value , exists := os . LookupEnv ( key ) ; exists {
return value
}
return defaultVal
}
2024-11-12 09:12:42 +00:00
func main ( ) {
2024-11-27 17:15:30 +00:00
// Define command-line flags with environment variable defaults
2024-11-12 09:12:42 +00:00
var forgejoAPIURL string
2024-11-27 17:15:30 +00:00
flag . StringVar ( & forgejoAPIURL , "forgejo-api-url" , getEnv ( "FORGEJO_API_URL" , "https://code.252.no/api/v1" ) , "Forgejo API URL (default: https://code.252.no/api/v1 or $FORGEJO_API_URL)" )
2024-11-12 09:12:42 +00:00
var token string
2024-11-27 17:15:30 +00:00
flag . StringVar ( & token , "token" , os . Getenv ( "FORGEJO_TOKEN" ) , "Forgejo API token (required, or set $FORGEJO_TOKEN)" )
2024-11-12 09:12:42 +00:00
var repoOwner string
2024-11-27 17:15:30 +00:00
flag . StringVar ( & repoOwner , "repo-owner" , os . Getenv ( "REPO_OWNER" ) , "Repository owner (required, or set $REPO_OWNER)" )
2024-11-12 09:12:42 +00:00
var repoName string
2024-11-27 17:15:30 +00:00
flag . StringVar ( & repoName , "repo-name" , os . Getenv ( "REPO_NAME" ) , "Repository name (required, or set $REPO_NAME)" )
2024-11-12 09:12:42 +00:00
var issueId int
2024-11-27 17:15:30 +00:00
issueIdStr := os . Getenv ( "ISSUE_ID" )
if issueIdStr != "" {
var err error
issueId , err = strconv . Atoi ( issueIdStr )
if err != nil {
fmt . Println ( "Error: Invalid ISSUE_ID" )
os . Exit ( 1 )
}
}
flag . IntVar ( & issueId , "issue-id" , issueId , "Issue ID to comment on (cannot be used with --pull-id, or set $ISSUE_ID)" )
var pullId int
pullIdStr := os . Getenv ( "PULL_ID" )
if pullIdStr != "" {
var err error
pullId , err = strconv . Atoi ( pullIdStr )
if err != nil {
fmt . Println ( "Error: Invalid PULL_ID" )
os . Exit ( 1 )
}
}
flag . IntVar ( & pullId , "pull-id" , pullId , "Pull Request ID to comment on (cannot be used with --issue-id, or set $PULL_ID)" )
// Override the default usage message to be more helpful
flag . Usage = func ( ) {
fmt . Fprintf ( flag . CommandLine . Output ( ) , "Usage: %s [options] <diff-file>\n" , os . Args [ 0 ] )
fmt . Fprintln ( flag . CommandLine . Output ( ) , "\nOptions:" )
flag . PrintDefaults ( )
fmt . Fprintln ( flag . CommandLine . Output ( ) , "\nExample:" )
fmt . Fprintf ( flag . CommandLine . Output ( ) , " %s --pull-id=123 --token=YOUR_TOKEN --repo-owner=owner --repo-name=repo diff.txt\n" , os . Args [ 0 ] )
}
2024-11-12 09:12:42 +00:00
flag . Parse ( )
// Get the diff file from the positional arguments
args := flag . Args ( )
if len ( args ) < 1 {
2024-11-27 17:15:30 +00:00
fmt . Println ( "Error: Missing diff file." )
flag . Usage ( )
2024-11-12 09:12:42 +00:00
os . Exit ( 1 )
}
diffFile := args [ 0 ]
2024-11-27 17:15:30 +00:00
// Check for required parameters
2024-11-12 09:12:42 +00:00
if token == "" {
2024-11-27 17:15:30 +00:00
fmt . Println ( "Error: Forgejo API token is not set. Use the --token flag or set FORGEJO_TOKEN environment variable." )
flag . Usage ( )
os . Exit ( 1 )
2024-11-12 09:12:42 +00:00
}
if repoOwner == "" {
2024-11-27 17:15:30 +00:00
fmt . Println ( "Error: Repository owner is not set. Use the --repo-owner flag or set REPO_OWNER environment variable." )
flag . Usage ( )
os . Exit ( 1 )
2024-11-12 09:12:42 +00:00
}
if repoName == "" {
2024-11-27 17:15:30 +00:00
fmt . Println ( "Error: Repository name is not set. Use the --repo-name flag or set REPO_NAME environment variable." )
flag . Usage ( )
os . Exit ( 1 )
2024-11-12 09:12:42 +00:00
}
2024-11-27 17:15:30 +00:00
// Ensure that only one of issueId or pullId is set
if ( issueId == 0 && pullId == 0 ) || ( issueId != 0 && pullId != 0 ) {
fmt . Println ( "Error: You must specify either --issue-id or --pull-id, but not both." )
flag . Usage ( )
os . Exit ( 1 )
}
// Determine which ID to use
var itemId int
var itemType string
if issueId != 0 {
itemId = issueId
itemType = "issue"
} else {
itemId = pullId
itemType = "pull"
2024-11-12 09:12:42 +00:00
}
// Read the diff file
diffContentBytes , err := os . ReadFile ( diffFile )
if err != nil {
2024-11-27 17:15:30 +00:00
fmt . Printf ( "Error reading diff file '%s': %v\n" , diffFile , err )
2024-11-12 09:12:42 +00:00
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
2024-11-27 17:15:30 +00:00
apiURL := fmt . Sprintf ( "%s/repos/%s/%s/issues/%d/comments" , forgejoAPIURL , repoOwner , repoName , itemId )
2024-11-12 09:12:42 +00:00
// 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 {
2024-11-27 17:15:30 +00:00
fmt . Printf ( "Posted diff to Forgejo %s #%d\n" , itemType , itemId )
2024-11-12 09:12:42 +00:00
}
}