Skip to content

Commit 5da10fb

Browse files
committed
Add webhook create and update commands
1 parent d8d3bb2 commit 5da10fb

File tree

5 files changed

+410
-1
lines changed

5 files changed

+410
-1
lines changed

internal/cmd/webhook/create.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package webhook
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/planetscale/cli/internal/cmdutil"
7+
"github.com/planetscale/cli/internal/printer"
8+
"github.com/planetscale/planetscale-go/planetscale"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func CreateCmd(ch *cmdutil.Helper) *cobra.Command {
13+
var flags struct {
14+
url string
15+
events []string
16+
enabled bool
17+
}
18+
19+
cmd := &cobra.Command{
20+
Use: "create <database>",
21+
Short: "Create a webhook for a database",
22+
Args: cmdutil.RequiredArgs("database"),
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
ctx := cmd.Context()
25+
database := args[0]
26+
27+
client, err := ch.Client()
28+
if err != nil {
29+
return err
30+
}
31+
32+
req := &planetscale.CreateWebhookRequest{
33+
Organization: ch.Config.Organization,
34+
Database: database,
35+
URL: flags.url,
36+
Events: flags.events,
37+
}
38+
39+
if cmd.Flags().Changed("enabled") {
40+
req.Enabled = &flags.enabled
41+
}
42+
43+
end := ch.Printer.PrintProgress(fmt.Sprintf("Creating webhook for %s", printer.BoldBlue(database)))
44+
defer end()
45+
46+
webhook, err := client.Webhooks.Create(ctx, req)
47+
if err != nil {
48+
switch cmdutil.ErrCode(err) {
49+
case planetscale.ErrNotFound:
50+
return fmt.Errorf("database %s does not exist in organization %s",
51+
printer.BoldBlue(database), printer.BoldBlue(ch.Config.Organization))
52+
default:
53+
return cmdutil.HandleError(err)
54+
}
55+
}
56+
57+
end()
58+
59+
return ch.Printer.PrintResource(toWebhook(webhook))
60+
},
61+
}
62+
63+
cmd.Flags().StringVar(&flags.url, "url", "", "The URL to send webhook events to (required)")
64+
cmd.Flags().StringSliceVar(&flags.events, "events", nil, "Comma-separated list of events to subscribe to")
65+
cmd.Flags().BoolVar(&flags.enabled, "enabled", true, "Whether the webhook is enabled")
66+
67+
cmd.MarkFlagRequired("url") // nolint:errcheck
68+
69+
return cmd
70+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package webhook
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"testing"
7+
"time"
8+
9+
qt "github.com/frankban/quicktest"
10+
"github.com/planetscale/cli/internal/cmdutil"
11+
"github.com/planetscale/cli/internal/config"
12+
"github.com/planetscale/cli/internal/mock"
13+
"github.com/planetscale/cli/internal/printer"
14+
ps "github.com/planetscale/planetscale-go/planetscale"
15+
)
16+
17+
func TestWebhook_CreateCmd(t *testing.T) {
18+
c := qt.New(t)
19+
20+
var buf bytes.Buffer
21+
format := printer.JSON
22+
p := printer.NewPrinter(&format)
23+
p.SetResourceOutput(&buf)
24+
25+
org := "planetscale"
26+
db := "mydb"
27+
url := "https://example.com/webhook"
28+
events := []string{"branch.created", "branch.deleted"}
29+
createdAt := time.Date(2025, 1, 15, 10, 30, 0, 0, time.UTC)
30+
31+
webhook := &ps.Webhook{
32+
ID: "webhook-123",
33+
URL: url,
34+
Enabled: true,
35+
Events: events,
36+
CreatedAt: createdAt,
37+
}
38+
39+
svc := &mock.WebhooksService{
40+
CreateFn: func(ctx context.Context, req *ps.CreateWebhookRequest) (*ps.Webhook, error) {
41+
c.Assert(req.Organization, qt.Equals, org)
42+
c.Assert(req.Database, qt.Equals, db)
43+
c.Assert(req.URL, qt.Equals, url)
44+
c.Assert(req.Events, qt.DeepEquals, events)
45+
return webhook, nil
46+
},
47+
}
48+
49+
ch := &cmdutil.Helper{
50+
Printer: p,
51+
Config: &config.Config{
52+
Organization: org,
53+
},
54+
Client: func() (*ps.Client, error) {
55+
return &ps.Client{
56+
Webhooks: svc,
57+
}, nil
58+
},
59+
}
60+
61+
cmd := CreateCmd(ch)
62+
cmd.SetArgs([]string{db, "--url", url, "--events", "branch.created,branch.deleted"})
63+
err := cmd.Execute()
64+
65+
c.Assert(err, qt.IsNil)
66+
c.Assert(svc.CreateFnInvoked, qt.IsTrue)
67+
68+
res := &Webhook{orig: webhook}
69+
c.Assert(buf.String(), qt.JSONEquals, res)
70+
}
71+
72+
func TestWebhook_CreateCmd_RequiresURL(t *testing.T) {
73+
c := qt.New(t)
74+
75+
var buf bytes.Buffer
76+
format := printer.Human
77+
p := printer.NewPrinter(&format)
78+
p.SetHumanOutput(&buf)
79+
80+
org := "planetscale"
81+
db := "mydb"
82+
83+
ch := &cmdutil.Helper{
84+
Printer: p,
85+
Config: &config.Config{
86+
Organization: org,
87+
},
88+
Client: func() (*ps.Client, error) {
89+
return &ps.Client{}, nil
90+
},
91+
}
92+
93+
cmd := CreateCmd(ch)
94+
cmd.SetArgs([]string{db})
95+
err := cmd.Execute()
96+
97+
c.Assert(err, qt.IsNotNil)
98+
c.Assert(err.Error(), qt.Contains, "required flag")
99+
}

internal/cmd/webhook/update.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package webhook
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/planetscale/cli/internal/cmdutil"
7+
"github.com/planetscale/cli/internal/printer"
8+
"github.com/planetscale/planetscale-go/planetscale"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func UpdateCmd(ch *cmdutil.Helper) *cobra.Command {
13+
var flags struct {
14+
url string
15+
events []string
16+
enabled bool
17+
}
18+
19+
cmd := &cobra.Command{
20+
Use: "update <database> <webhook-id>",
21+
Short: "Update a webhook for a database",
22+
Args: cmdutil.RequiredArgs("database", "webhook-id"),
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
ctx := cmd.Context()
25+
database := args[0]
26+
webhookID := args[1]
27+
28+
client, err := ch.Client()
29+
if err != nil {
30+
return err
31+
}
32+
33+
req := &planetscale.UpdateWebhookRequest{
34+
Organization: ch.Config.Organization,
35+
Database: database,
36+
ID: webhookID,
37+
}
38+
39+
changed := false
40+
41+
if cmd.Flags().Changed("url") {
42+
req.URL = &flags.url
43+
changed = true
44+
}
45+
46+
if cmd.Flags().Changed("events") {
47+
req.Events = flags.events
48+
changed = true
49+
}
50+
51+
if cmd.Flags().Changed("enabled") {
52+
req.Enabled = &flags.enabled
53+
changed = true
54+
}
55+
56+
if !changed {
57+
return fmt.Errorf("at least one of --url, --events, or --enabled must be provided")
58+
}
59+
60+
end := ch.Printer.PrintProgress(fmt.Sprintf("Updating webhook %s for %s", printer.BoldBlue(webhookID), printer.BoldBlue(database)))
61+
defer end()
62+
63+
webhook, err := client.Webhooks.Update(ctx, req)
64+
if err != nil {
65+
switch cmdutil.ErrCode(err) {
66+
case planetscale.ErrNotFound:
67+
return fmt.Errorf("webhook %s does not exist in database %s (organization: %s)",
68+
printer.BoldBlue(webhookID), printer.BoldBlue(database), printer.BoldBlue(ch.Config.Organization))
69+
default:
70+
return cmdutil.HandleError(err)
71+
}
72+
}
73+
74+
end()
75+
76+
return ch.Printer.PrintResource(toWebhook(webhook))
77+
},
78+
}
79+
80+
cmd.Flags().StringVar(&flags.url, "url", "", "The URL to send webhook events to")
81+
cmd.Flags().StringSliceVar(&flags.events, "events", nil, "Comma-separated list of events to subscribe to")
82+
cmd.Flags().BoolVar(&flags.enabled, "enabled", true, "Whether the webhook is enabled")
83+
84+
return cmd
85+
}

0 commit comments

Comments
 (0)