feat: initial version of the project
This commit is contained in:
commit
5b67d39aba
13 changed files with 1538 additions and 0 deletions
301
cmd/issue.go
Normal file
301
cmd/issue.go
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/spf13/cobra"
|
||||
"codeberg.org/romaintb/fgj/internal/api"
|
||||
"codeberg.org/romaintb/fgj/internal/config"
|
||||
)
|
||||
|
||||
var issueCmd = &cobra.Command{
|
||||
Use: "issue",
|
||||
Short: "Manage issues",
|
||||
Long: "Create, view, list, and manage issues.",
|
||||
}
|
||||
|
||||
var issueListCmd = &cobra.Command{
|
||||
Use: "list [flags]",
|
||||
Short: "List issues",
|
||||
Long: "List issues in a repository.",
|
||||
RunE: runIssueList,
|
||||
}
|
||||
|
||||
var issueViewCmd = &cobra.Command{
|
||||
Use: "view <number>",
|
||||
Short: "View an issue",
|
||||
Long: "Display detailed information about an issue.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runIssueView,
|
||||
}
|
||||
|
||||
var issueCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create an issue",
|
||||
Long: "Create a new issue.",
|
||||
RunE: runIssueCreate,
|
||||
}
|
||||
|
||||
var issueCommentCmd = &cobra.Command{
|
||||
Use: "comment <number>",
|
||||
Short: "Add a comment to an issue",
|
||||
Long: "Add a comment to an existing issue.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runIssueComment,
|
||||
}
|
||||
|
||||
var issueCloseCmd = &cobra.Command{
|
||||
Use: "close <number>",
|
||||
Short: "Close an issue",
|
||||
Long: "Close an existing issue.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runIssueClose,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(issueCmd)
|
||||
issueCmd.AddCommand(issueListCmd)
|
||||
issueCmd.AddCommand(issueViewCmd)
|
||||
issueCmd.AddCommand(issueCreateCmd)
|
||||
issueCmd.AddCommand(issueCommentCmd)
|
||||
issueCmd.AddCommand(issueCloseCmd)
|
||||
|
||||
issueListCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
||||
issueListCmd.Flags().StringP("state", "s", "open", "Filter by state: open, closed, all")
|
||||
|
||||
issueViewCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
||||
|
||||
issueCreateCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
||||
issueCreateCmd.Flags().StringP("title", "t", "", "Title for the issue")
|
||||
issueCreateCmd.Flags().StringP("body", "b", "", "Body for the issue")
|
||||
|
||||
issueCommentCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
||||
issueCommentCmd.Flags().StringP("body", "b", "", "Comment body")
|
||||
|
||||
issueCloseCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
||||
}
|
||||
|
||||
func runIssueList(cmd *cobra.Command, args []string) error {
|
||||
repo, _ := cmd.Flags().GetString("repo")
|
||||
state, _ := cmd.Flags().GetString("state")
|
||||
|
||||
owner, name, err := parseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := api.NewClientFromConfig(cfg, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var stateType gitea.StateType
|
||||
switch strings.ToLower(state) {
|
||||
case "open":
|
||||
stateType = gitea.StateOpen
|
||||
case "closed":
|
||||
stateType = gitea.StateClosed
|
||||
case "all":
|
||||
stateType = gitea.StateAll
|
||||
default:
|
||||
return fmt.Errorf("invalid state: %s", state)
|
||||
}
|
||||
|
||||
issues, _, err := client.ListRepoIssues(owner, name, gitea.ListIssueOption{
|
||||
State: stateType,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list issues: %w", err)
|
||||
}
|
||||
|
||||
if len(issues) == 0 {
|
||||
fmt.Printf("No %s issues in %s/%s\n", state, owner, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintf(w, "NUMBER\tTITLE\tSTATE\n")
|
||||
for _, issue := range issues {
|
||||
if issue.PullRequest == nil {
|
||||
fmt.Fprintf(w, "#%d\t%s\t%s\n", issue.Index, issue.Title, issue.State)
|
||||
}
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runIssueView(cmd *cobra.Command, args []string) error {
|
||||
repo, _ := cmd.Flags().GetString("repo")
|
||||
issueNumber, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid issue number: %w", err)
|
||||
}
|
||||
|
||||
owner, name, err := parseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := api.NewClientFromConfig(cfg, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
issue, _, err := client.GetIssue(owner, name, issueNumber)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get issue: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Issue #%d\n", issue.Index)
|
||||
fmt.Printf("Title: %s\n", issue.Title)
|
||||
fmt.Printf("State: %s\n", issue.State)
|
||||
fmt.Printf("Author: %s\n", issue.Poster.UserName)
|
||||
fmt.Printf("Created: %s\n", issue.Created.Format("2006-01-02 15:04:05"))
|
||||
fmt.Printf("Updated: %s\n", issue.Updated.Format("2006-01-02 15:04:05"))
|
||||
if issue.Body != "" {
|
||||
fmt.Printf("\n%s\n", issue.Body)
|
||||
}
|
||||
|
||||
comments, _, err := client.ListIssueComments(owner, name, issueNumber, gitea.ListIssueCommentOptions{})
|
||||
if err == nil && len(comments) > 0 {
|
||||
fmt.Printf("\nComments (%d):\n", len(comments))
|
||||
for _, comment := range comments {
|
||||
fmt.Printf("\n---\n%s (@%s) - %s\n%s\n",
|
||||
comment.Poster.FullName,
|
||||
comment.Poster.UserName,
|
||||
comment.Created.Format("2006-01-02 15:04:05"),
|
||||
comment.Body)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runIssueCreate(cmd *cobra.Command, args []string) error {
|
||||
repo, _ := cmd.Flags().GetString("repo")
|
||||
title, _ := cmd.Flags().GetString("title")
|
||||
body, _ := cmd.Flags().GetString("body")
|
||||
|
||||
owner, name, err := parseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if title == "" {
|
||||
return fmt.Errorf("title is required")
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := api.NewClientFromConfig(cfg, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
issue, _, err := client.CreateIssue(owner, name, gitea.CreateIssueOption{
|
||||
Title: title,
|
||||
Body: body,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create issue: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Issue created: #%d\n", issue.Index)
|
||||
fmt.Printf("View at: %s\n", issue.HTMLURL)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runIssueComment(cmd *cobra.Command, args []string) error {
|
||||
repo, _ := cmd.Flags().GetString("repo")
|
||||
body, _ := cmd.Flags().GetString("body")
|
||||
issueNumber, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid issue number: %w", err)
|
||||
}
|
||||
|
||||
owner, name, err := parseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if body == "" {
|
||||
return fmt.Errorf("comment body is required")
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := api.NewClientFromConfig(cfg, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
comment, _, err := client.CreateIssueComment(owner, name, issueNumber, gitea.CreateIssueCommentOption{
|
||||
Body: body,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create comment: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Comment added to issue #%d\n", issueNumber)
|
||||
fmt.Printf("View at: %s\n", comment.HTMLURL)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runIssueClose(cmd *cobra.Command, args []string) error {
|
||||
repo, _ := cmd.Flags().GetString("repo")
|
||||
issueNumber, err := strconv.ParseInt(args[0], 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid issue number: %w", err)
|
||||
}
|
||||
|
||||
owner, name, err := parseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := api.NewClientFromConfig(cfg, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stateClosed := gitea.StateClosed
|
||||
_, _, err = client.EditIssue(owner, name, issueNumber, gitea.EditIssueOption{
|
||||
State: &stateClosed,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to close issue: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Issue #%d closed\n", issueNumber)
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue