241 lines
7.3 KiB
Go
241 lines
7.3 KiB
Go
// src/main.go
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
// Define command-line flags
|
|
baseURL := flag.String("base-url", "https://code.252.no/api/v1", "Base URL of the Forgejo API")
|
|
token := flag.String("token", "", "API token for authentication")
|
|
|
|
action := flag.String("action", "", "Action to perform: get, create, get-single, update, delete, apply, sync")
|
|
owner := flag.String("owner", "", "Owner of the repository")
|
|
repo := flag.String("repo", "", "Name of the repository")
|
|
id := flag.Int64("id", 0, "ID of the issue or pull request")
|
|
name := flag.String("name", "", "Name of the label")
|
|
color := flag.String("color", "", "Color of the label")
|
|
description := flag.String("description", "", "Description of the label")
|
|
|
|
// Define exclusive and isArchived as regular boolean flags
|
|
exclusive := flag.Bool("exclusive", false, "Exclusive flag for the label (true/false)")
|
|
isArchived := flag.Bool("is-archived", false, "Archived flag for the label (true/false)")
|
|
|
|
// Define paths to configuration files
|
|
labelerConfigPath := flag.String("labeler-config", ".forgejo/labeler.yaml", "Path to labeler.yaml configuration file")
|
|
labelsConfigPath := flag.String("labels-config", ".forgejo/labels.yaml", "Path to labels.yaml configuration file")
|
|
|
|
// Define changed files (comma-separated list)
|
|
changedFilesInput := flag.String("changed-files", "", "Comma-separated list of changed file paths")
|
|
|
|
// Define deleteOtherLabels flag
|
|
deleteOtherLabels := flag.Bool("delete-other-labels", false, "Delete labels not defined in the config file")
|
|
|
|
// Define dryRun flag
|
|
dryRun := flag.Bool("dry-run", false, "Simulate the sync without making any changes")
|
|
|
|
page := flag.Int("page", 1, "Page number for listing labels")
|
|
limit := flag.Int("limit", 30, "Number of labels per page")
|
|
|
|
flag.Parse()
|
|
|
|
// Validate required flags
|
|
if *action == "" || *owner == "" || *repo == "" {
|
|
fmt.Println("Error: action, owner, and repo are required.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Initialize the Forgejo client
|
|
client := NewForgejoClient(*baseURL, *token)
|
|
|
|
switch *action {
|
|
case "get":
|
|
labels, err := client.GetLabels(*owner, *repo, *page, *limit)
|
|
if err != nil {
|
|
log.Fatalf("Error getting labels: %v", err)
|
|
}
|
|
for _, label := range labels {
|
|
fmt.Printf("ID: %d, Name: %s, Color: %s, Description: %s\n", label.ID, label.Name, label.Color, label.Description)
|
|
}
|
|
|
|
case "create":
|
|
if *name == "" || *color == "" {
|
|
fmt.Println("Error: name and color are required for creating a label.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
option := CreateLabelOption{
|
|
Name: *name,
|
|
Color: *color,
|
|
Description: *description,
|
|
Exclusive: *exclusive,
|
|
IsArchived: *isArchived,
|
|
}
|
|
label, err := client.CreateLabel(*owner, *repo, option)
|
|
if err != nil {
|
|
log.Fatalf("Error creating label: %v", err)
|
|
}
|
|
fmt.Printf("Created Label: ID=%d, Name=%s\n", label.ID, label.Name)
|
|
|
|
case "get-single":
|
|
if *id == 0 {
|
|
fmt.Println("Error: id is required for getting a single label.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
label, err := client.GetLabel(*owner, *repo, *id)
|
|
if err != nil {
|
|
log.Fatalf("Error getting label: %v", err)
|
|
}
|
|
fmt.Printf("Label: ID=%d, Name=%s, Color=%s, Description: %s\n", label.ID, label.Name, label.Color, label.Description)
|
|
|
|
case "update":
|
|
if *id == 0 {
|
|
fmt.Println("Error: id is required for updating a label.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
option := EditLabelOption{
|
|
Name: *name,
|
|
Color: *color,
|
|
Description: *description,
|
|
}
|
|
if *exclusive {
|
|
option.Exclusive = exclusive
|
|
}
|
|
if *isArchived {
|
|
option.IsArchived = isArchived
|
|
}
|
|
err := client.UpdateLabel(*owner, *repo, *id, option)
|
|
if err != nil {
|
|
log.Fatalf("Error updating label: %v", err)
|
|
}
|
|
fmt.Printf("Updated Label: Name=%s\n", option.Name)
|
|
|
|
case "delete":
|
|
if *id == 0 {
|
|
fmt.Println("Error: id is required for deleting a label.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
err := client.DeleteLabel(*owner, *repo, *id)
|
|
if err != nil {
|
|
log.Fatalf("Error deleting label: %v", err)
|
|
}
|
|
fmt.Println("Label deleted successfully.")
|
|
|
|
case "apply":
|
|
// Action to apply labels based on configuration and changed files
|
|
if *changedFilesInput == "" {
|
|
fmt.Println("Error: changed-files are required for the apply action.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Parse changed files
|
|
changedFiles := parseChangedFiles(*changedFilesInput)
|
|
|
|
// Load configuration files
|
|
labelerConfig, err := LoadLabelerConfig(*labelerConfigPath)
|
|
if err != nil {
|
|
log.Fatalf("Error loading labeler config: %v", err)
|
|
}
|
|
|
|
labelsConfig, err := LoadLabelsConfig(*labelsConfigPath)
|
|
if err != nil {
|
|
log.Fatalf("Error loading labels config: %v", err)
|
|
}
|
|
|
|
// Validate configurations
|
|
if err := ValidateLabelerConfig(labelerConfig); err != nil {
|
|
log.Fatalf("Invalid labeler config: %v", err)
|
|
}
|
|
if err := ValidateLabelsConfig(labelsConfig); err != nil {
|
|
log.Fatalf("Invalid labels config: %v", err)
|
|
}
|
|
|
|
// Ensure all labels exist, optionally deleting others, with dryRun
|
|
err = EnsureLabelsExist(client, *owner, *repo, labelsConfig, *deleteOtherLabels, *dryRun)
|
|
if err != nil {
|
|
log.Fatalf("Error ensuring labels exist: %v", err)
|
|
}
|
|
|
|
// Determine labels to apply based on changed files
|
|
labelsToApply, err := DetermineLabels(labelerConfig, changedFiles)
|
|
if err != nil {
|
|
log.Fatalf("Error determining labels to apply: %v", err)
|
|
}
|
|
|
|
if len(labelsToApply) == 0 {
|
|
fmt.Println("No labels to apply based on the changed files.")
|
|
return
|
|
}
|
|
|
|
// Apply labels to an issue or pull request
|
|
// For demonstration, assume applying to a specific issue ID passed via the `id` flag
|
|
if *id == 0 {
|
|
fmt.Println("Error: id (issue or PR ID) is required to apply labels.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Apply labels using SetLabelsOnIssue
|
|
err = client.SetLabelsOnIssue(*owner, *repo, *id, labelsToApply)
|
|
if err != nil {
|
|
log.Fatalf("Error applying labels: %v", err)
|
|
}
|
|
fmt.Printf("Labels applied successfully: %v\n", labelsToApply)
|
|
|
|
case "sync":
|
|
// New "sync" action
|
|
// Sync labels based on labels.yaml, optionally deleting other labels
|
|
// This action doesn't require changed-files or issue ID
|
|
|
|
// Load configuration files
|
|
labelsConfig, err := LoadLabelsConfig(*labelsConfigPath)
|
|
if err != nil {
|
|
log.Fatalf("Error loading labels config: %v", err)
|
|
}
|
|
|
|
// Validate labels configuration
|
|
if err := ValidateLabelsConfig(labelsConfig); err != nil {
|
|
log.Fatalf("Invalid labels config: %v", err)
|
|
}
|
|
|
|
// Ensure all labels exist, optionally deleting others, with dryRun
|
|
err = EnsureLabelsExist(client, *owner, *repo, labelsConfig, *deleteOtherLabels, *dryRun)
|
|
if err != nil {
|
|
log.Fatalf("Error ensuring labels exist: %v", err)
|
|
}
|
|
|
|
if *dryRun {
|
|
fmt.Println("Dry-run completed successfully. No changes were made.")
|
|
} else {
|
|
fmt.Println("Label synchronization completed successfully.")
|
|
}
|
|
|
|
default:
|
|
fmt.Println("Error: Invalid action. Available actions: get, create, get-single, update, delete, apply, sync.")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// parseChangedFiles parses a comma-separated list of file paths into a slice.
|
|
func parseChangedFiles(input string) []string {
|
|
var files []string
|
|
for _, file := range strings.Split(input, ",") {
|
|
trimmed := filepath.Clean(strings.TrimSpace(file))
|
|
if trimmed != "" {
|
|
files = append(files, trimmed)
|
|
}
|
|
}
|
|
return files
|
|
}
|