Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d4b4865
docs: add detailed MCP server implementation plan
claude Mar 5, 2026
1b5e7ad
docs: update MCP plan with Issues backfill, metrics consolidation, an…
claude Mar 5, 2026
240e55e
Add Phase 1 progress tracker to implementation plan
claude Mar 5, 2026
6f5494b
Phase 1 Part 1: Issues CLI backfill — complete
claude Mar 5, 2026
6f438e1
Add acceptance tests for issue commands
claude Mar 5, 2026
7d0298a
test(acceptance): consolidate issue tests, skip flaky real-data tests
leggetter Mar 5, 2026
130bf23
Add acceptance test requirements for CLI changes to implementation plan
claude Mar 6, 2026
5cc6c1d
Expand Part 2 to cover all 4 metrics subcommands, not just events
claude Mar 6, 2026
ba1f7b1
Consolidate metrics CLI from 7 subcommands to 4 resource-aligned ones
claude Mar 6, 2026
06913a7
fix(metrics): help text, pending API measure, per-issue validation; e…
leggetter Mar 6, 2026
0b07e2b
Update plan: mark Parts 1 and 2 as complete
claude Mar 6, 2026
489dd22
Add MCP server skeleton (Part 3): command, server, tools, error trans…
claude Mar 9, 2026
b990401
Update plan: mark Part 3 as complete
claude Mar 9, 2026
5b7db32
fix(mcp): add required input schema for all tools
leggetter Mar 9, 2026
c7f3afa
docs: update MCP plan with current status and next steps
claude Mar 9, 2026
20e866c
feat(mcp): implement all 11 tool handlers with real API calls (Part 4)
claude Mar 9, 2026
24ed1d9
docs(mcp): add Section 1.7 — MCP authentication & login flow design
claude Mar 9, 2026
105d41c
feat(mcp): implement hookdeck_login tool for in-band browser auth
claude Mar 9, 2026
ee4bbe7
Fix metrics measures requirement and help topic error message
claude Mar 9, 2026
aa3f103
Document auth design decision: no API key param on hookdeck_login
claude Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/hookdeck/hookdeck-cli

go 1.24.9
go 1.24.7

require (
github.com/AlecAivazis/survey/v2 v2.3.7
Expand All @@ -15,6 +15,7 @@ require (
github.com/hookdeck/hookdeck-go-sdk v0.7.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/mitchellh/go-homedir v1.1.0
github.com/modelcontextprotocol/go-sdk v1.4.0
github.com/sirupsen/logrus v1.9.4
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
Expand All @@ -41,6 +42,7 @@ require (
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/jsonschema-go v0.4.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand All @@ -60,12 +62,16 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/segmentio/asm v1.1.3 // indirect
github.com/segmentio/encoding v0.5.3 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/oauth2 v0.34.0 // indirect
golang.org/x/text v0.30.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
28 changes: 18 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/briandowns/spinner v1.23.2 h1:Zc6ecUnI+YzLmJniCfDNaMbW0Wid1d5+qcTq4L2FW8w=
github.com/briandowns/spinner v1.23.2/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
github.com/charmbracelet/bubbles v0.21.1 h1:nj0decPiixaZeL9diI4uzzQTkkz1kYY8+jgzCZXSmW0=
github.com/charmbracelet/bubbles v0.21.1/go.mod h1:HHvIYRCpbkCJw2yo0vNX1O5loCwSr9/mWS8GYSg50Sk=
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
Expand All @@ -18,8 +16,6 @@ github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.11.5 h1:NBWeBpj/lJPE3Q5l+Lusa4+mH6v7487OP8K0r1IhRg4=
github.com/charmbracelet/x/ansi v0.11.5/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
Expand Down Expand Up @@ -50,6 +46,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
Expand All @@ -61,13 +59,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
Expand Down Expand Up @@ -111,6 +111,8 @@ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQ
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/modelcontextprotocol/go-sdk v1.4.0 h1:u0kr8lbJc1oBcawK7Df+/ajNMpIDFE41OEPxdeTLOn8=
github.com/modelcontextprotocol/go-sdk v1.4.0/go.mod h1:Nxc2n+n/GdCebUaqCOhTetptS17SXXNu9IfNTaLDi1E=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
Expand All @@ -137,6 +139,10 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
github.com/segmentio/encoding v0.5.3 h1:OjMgICtcSFuNvQCdwqMCv9Tg7lEOXGwm1J5RPQccx6w=
github.com/segmentio/encoding v0.5.3/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
Expand All @@ -162,6 +168,8 @@ github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJ
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
Expand All @@ -181,6 +189,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -199,14 +209,10 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -219,6 +225,8 @@ golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
9 changes: 7 additions & 2 deletions pkg/cmd/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func newGatewayCmd() *gatewayCmd {
Args: validators.NoArgs,
Short: "Manage Hookdeck Event Gateway resources",
Long: `Commands for managing Event Gateway sources, destinations, connections,
transformations, events, requests, and metrics.
transformations, events, requests, metrics, and MCP server.

The gateway command group provides full access to all Event Gateway resources.`,
Example: ` # List connections
Expand All @@ -28,7 +28,10 @@ The gateway command group provides full access to all Event Gateway resources.`,
hookdeck gateway source create --name my-source --type WEBHOOK

# Query event metrics
hookdeck gateway metrics events --start 2026-01-01T00:00:00Z --end 2026-02-01T00:00:00Z`,
hookdeck gateway metrics events --start 2026-01-01T00:00:00Z --end 2026-02-01T00:00:00Z

# Start the MCP server for AI agent access
hookdeck gateway mcp`,
}

// Register resource subcommands (same factory as root backward-compat registration)
Expand All @@ -40,6 +43,8 @@ The gateway command group provides full access to all Event Gateway resources.`,
addRequestCmdTo(g.cmd)
addAttemptCmdTo(g.cmd)
addMetricsCmdTo(g.cmd)
addIssueCmdTo(g.cmd)
addMCPCmdTo(g.cmd)

return g
}
1 change: 1 addition & 0 deletions pkg/cmd/helptext.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
ResourceEvent = "event"
ResourceRequest = "request"
ResourceAttempt = "attempt"
ResourceIssue = "issue"
)

// Short help (one line) for common commands. Use when the only difference is the resource name.
Expand Down
40 changes: 40 additions & 0 deletions pkg/cmd/issue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/hookdeck/hookdeck-cli/pkg/validators"
)

type issueCmd struct {
cmd *cobra.Command
}

func newIssueCmd() *issueCmd {
ic := &issueCmd{}

ic.cmd = &cobra.Command{
Use: "issue",
Aliases: []string{"issues"},
Args: validators.NoArgs,
Short: ShortBeta("Manage your issues"),
Long: LongBeta(`Manage Hookdeck issues.

Issues are automatically created when delivery failures, transformation errors,
or backpressure conditions are detected. Use these commands to list, inspect,
update the status of, or dismiss issues.`),
}

ic.cmd.AddCommand(newIssueListCmd().cmd)
ic.cmd.AddCommand(newIssueGetCmd().cmd)
ic.cmd.AddCommand(newIssueUpdateCmd().cmd)
ic.cmd.AddCommand(newIssueDismissCmd().cmd)
ic.cmd.AddCommand(newIssueCountCmd().cmd)

return ic
}

// addIssueCmdTo registers the issue command tree on the given parent.
func addIssueCmdTo(parent *cobra.Command) {
parent.AddCommand(newIssueCmd().cmd)
}
69 changes: 69 additions & 0 deletions pkg/cmd/issue_count.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package cmd

import (
"context"
"fmt"
"strconv"

"github.com/spf13/cobra"

"github.com/hookdeck/hookdeck-cli/pkg/validators"
)

type issueCountCmd struct {
cmd *cobra.Command

issueType string
status string
issueTriggerID string
}

func newIssueCountCmd() *issueCountCmd {
ic := &issueCountCmd{}

ic.cmd = &cobra.Command{
Use: "count",
Args: validators.NoArgs,
Short: "Count issues",
Long: `Count issues matching optional filters.

Examples:
hookdeck gateway issue count
hookdeck gateway issue count --type delivery
hookdeck gateway issue count --status OPENED`,
RunE: ic.runIssueCountCmd,
}

ic.cmd.Flags().StringVar(&ic.issueType, "type", "", "Filter by issue type (delivery, transformation, backpressure)")
ic.cmd.Flags().StringVar(&ic.status, "status", "", "Filter by status (OPENED, IGNORED, ACKNOWLEDGED, RESOLVED)")
ic.cmd.Flags().StringVar(&ic.issueTriggerID, "issue-trigger-id", "", "Filter by issue trigger ID")

return ic
}

func (ic *issueCountCmd) runIssueCountCmd(cmd *cobra.Command, args []string) error {
if err := Config.Profile.ValidateAPIKey(); err != nil {
return err
}

client := Config.GetAPIClient()
params := make(map[string]string)

if ic.issueType != "" {
params["type"] = ic.issueType
}
if ic.status != "" {
params["status"] = ic.status
}
if ic.issueTriggerID != "" {
params["issue_trigger_id"] = ic.issueTriggerID
}

resp, err := client.CountIssues(context.Background(), params)
if err != nil {
return fmt.Errorf("failed to count issues: %w", err)
}

fmt.Println(strconv.Itoa(resp.Count))
return nil
}
76 changes: 76 additions & 0 deletions pkg/cmd/issue_dismiss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package cmd

import (
"context"
"encoding/json"
"fmt"

"github.com/spf13/cobra"

"github.com/hookdeck/hookdeck-cli/pkg/validators"
)

type issueDismissCmd struct {
cmd *cobra.Command
force bool
output string
}

func newIssueDismissCmd() *issueDismissCmd {
ic := &issueDismissCmd{}

ic.cmd = &cobra.Command{
Use: "dismiss <issue-id>",
Args: validators.ExactArgs(1),
Short: "Dismiss an issue",
Long: `Dismiss an issue. This sends a DELETE request to the API.

Examples:
hookdeck gateway issue dismiss iss_abc123
hookdeck gateway issue dismiss iss_abc123 --force`,
PreRunE: ic.validateFlags,
RunE: ic.runIssueDismissCmd,
}

ic.cmd.Flags().BoolVar(&ic.force, "force", false, "Dismiss without confirmation")
ic.cmd.Flags().StringVar(&ic.output, "output", "", "Output format (json)")

return ic
}

func (ic *issueDismissCmd) validateFlags(cmd *cobra.Command, args []string) error {
return Config.Profile.ValidateAPIKey()
}

func (ic *issueDismissCmd) runIssueDismissCmd(cmd *cobra.Command, args []string) error {
issueID := args[0]
client := Config.GetAPIClient()
ctx := context.Background()

if !ic.force {
fmt.Printf("Are you sure you want to dismiss issue %s? [y/N]: ", issueID)
var response string
fmt.Scanln(&response)
if response != "y" && response != "Y" {
fmt.Println("Dismiss cancelled.")
return nil
}
}

iss, err := client.DismissIssue(ctx, issueID)
if err != nil {
return fmt.Errorf("failed to dismiss issue: %w", err)
}

if ic.output == "json" {
jsonBytes, err := json.MarshalIndent(iss, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal issue to json: %w", err)
}
fmt.Println(string(jsonBytes))
return nil
}

fmt.Printf(SuccessCheck+" Issue dismissed: %s\n", issueID)
return nil
}
Loading
Loading