Borg/cmd/collect_github_repos.go
google-labs-jules[bot] 503890cd0a feat: Add progress events and webhooks
This commit introduces a progress event and webhook system to the `borg collect` commands.

- A new `pkg/events` package has been created to handle event emission.
- The `collect github repos` command now has `--events`, `--webhook`, and `--event-log` flags to control event output.
- The command emits `collection_started`, `item_started`, `item_completed`, and `collection_completed` events during the collection process.
- Unit tests have been added to verify the new functionality.

Co-authored-by: Snider <631881+Snider@users.noreply.github.com>
2026-02-02 00:47:16 +00:00

90 lines
2.3 KiB
Go

package cmd
import (
"fmt"
"io"
"time"
"github.com/Snider/Borg/pkg/events"
"github.com/Snider/Borg/pkg/github"
"github.com/spf13/cobra"
)
var (
// GithubClient is the github client used by the command. It can be replaced for testing.
GithubClient = github.NewGithubClient()
eventsFlag bool
webhook string
eventLog string
)
var collectGithubReposCmd = &cobra.Command{
Use: "repos [user-or-org]",
Short: "Collects all public repositories for a user or organization",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var stdout io.Writer
if eventsFlag {
stdout = cmd.OutOrStdout()
}
emitter, err := events.NewEventEmitter(stdout, webhook, eventLog)
if err != nil {
return err
}
defer emitter.Close()
repos, err := GithubClient.GetPublicRepos(cmd.Context(), args[0])
if err != nil {
return err
}
if err := emitter.Emit(events.CollectionStarted, events.CollectionStartedData{
Source: args[0],
EstimatedItems: len(repos),
}); err != nil {
return err
}
startTime := time.Now()
for i, repo := range repos {
itemStartTime := time.Now()
if err := emitter.Emit(events.ItemStarted, events.ItemStartedData{
URL: repo,
Index: i + 1,
Total: len(repos),
}); err != nil {
return err
}
if !eventsFlag {
fmt.Fprintln(cmd.OutOrStdout(), repo)
}
if err := emitter.Emit(events.ItemCompleted, events.ItemCompletedData{
URL: repo,
Size: 0, // Not applicable here
DurationMs: time.Since(itemStartTime).Milliseconds(),
Index: i + 1,
Total: len(repos),
}); err != nil {
return err
}
}
if err := emitter.Emit(events.CollectionCompleted, events.CollectionCompletedData{
Stats: map[string]interface{}{"repos": len(repos)},
DurationMs: time.Since(startTime).Milliseconds(),
}); err != nil {
return err
}
return nil
},
}
func init() {
collectGithubCmd.AddCommand(collectGithubReposCmd)
collectGithubReposCmd.Flags().BoolVar(&eventsFlag, "events", false, "Output JSON events to stdout")
collectGithubReposCmd.Flags().StringVar(&webhook, "webhook", "", "Webhook URL to send event notifications")
collectGithubReposCmd.Flags().StringVar(&eventLog, "event-log", "", "Log file for events")
}