feat: add webhook, repo delete/search, admin, pr clean/resolve/review-comments
Second pass of tea-parity work:
- fgj webhook {list,create,update,delete}: full CRUD over repo webhooks.
Create supports all standard hook types (gitea, slack, discord, etc.),
event selection, content type, secret, branch filter, auth header.
Update is partial — flags you omit leave existing config unchanged.
- fgj repo delete: type-to-confirm deletion; --yes skips for scripts;
refuses without a TTY unless --yes is passed.
- fgj repo search: SDK SearchRepos with query, topic/description,
private/archived, --type (source/fork/mirror), owner, sort/order.
- fgj admin user list: admin-gated user enumeration.
- fgj pr clean: delete the local branch from 'pr checkout'. Refuses
if the PR is still open (use --force) or if the branch is currently
checked out.
- fgj pr review-comments: list inline review comments across every
review on a PR (ListPullReviews + ListPullReviewComments per review).
- fgj pr resolve / unresolve: mark review comments as (un)resolved.
Uses raw POST since SDK v0.22.1 predates these endpoints; requires
Forgejo 8.x+ / Gitea 1.22+ server-side.
All share the standard parseRepo + config.Load + NewClientFromConfig
pattern; list commands support --json / --jq.
This commit is contained in:
parent
17ca49d0c5
commit
adccd6f6f7
6 changed files with 871 additions and 0 deletions
78
cmd/repo_delete.go
Normal file
78
cmd/repo_delete.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"forgejo.zerova.net/public/fgj-sid/internal/api"
|
||||
"forgejo.zerova.net/public/fgj-sid/internal/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var repoDeleteCmd = &cobra.Command{
|
||||
Use: "delete [owner/name]",
|
||||
Aliases: []string{"rm"},
|
||||
Short: "Delete a repository",
|
||||
Long: `Delete a repository. This is irreversible and removes all issues, PRs,
|
||||
wikis, and release artifacts.
|
||||
|
||||
For safety, you must either pass -y/--yes, or type the full owner/name
|
||||
string when prompted.`,
|
||||
Example: ` # Delete a repository (prompted confirmation)
|
||||
fgj repo delete owner/name
|
||||
|
||||
# Delete without confirmation (scripts)
|
||||
fgj repo delete owner/name --yes`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: runRepoDelete,
|
||||
}
|
||||
|
||||
func init() {
|
||||
repoCmd.AddCommand(repoDeleteCmd)
|
||||
repoDeleteCmd.Flags().BoolP("yes", "y", false, "Skip the type-to-confirm prompt")
|
||||
}
|
||||
|
||||
func runRepoDelete(cmd *cobra.Command, args []string) error {
|
||||
var target string
|
||||
if len(args) == 1 {
|
||||
target = args[0]
|
||||
}
|
||||
owner, name, err := parseRepo(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost(), getCwd())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
slug := fmt.Sprintf("%s/%s", owner, name)
|
||||
skipConfirm, _ := cmd.Flags().GetBool("yes")
|
||||
|
||||
if !skipConfirm {
|
||||
if !ios.IsStdinTTY() {
|
||||
return fmt.Errorf("refusing to delete %s without a TTY; pass --yes to confirm non-interactively", slug)
|
||||
}
|
||||
prompt := fmt.Sprintf("Type the full repo slug to confirm deletion (%s): ", slug)
|
||||
answer, err := promptLine(prompt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if answer != slug {
|
||||
fmt.Fprintln(ios.ErrOut, "Confirmation mismatch; aborting.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := client.DeleteRepo(owner, name); err != nil {
|
||||
return fmt.Errorf("failed to delete %s: %w", slug, err)
|
||||
}
|
||||
|
||||
cs := ios.ColorScheme()
|
||||
fmt.Fprintf(ios.Out, "%s Deleted %s\n", cs.SuccessIcon(), slug)
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue