Skip to content

Commit 8325f17

Browse files
uik/signals: add sendSignal mutation to directly schedule signal messages (#4501)
* graphql: add SendSignal mutation and input type * graphql: add feature flag check to SendSignal mutation * test: add TestSendSignal for builtin-slack-channel mutation * test: update TestSearchTemplate_Only_SQLGeneration to handle 'only' parameter correctly * graphql: fix indentation for sendSignal mutation definition
1 parent 39a30d4 commit 8325f17

7 files changed

Lines changed: 242 additions & 5 deletions

File tree

graphql2/generated.go

Lines changed: 135 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

graphql2/graph/signals.graphqls

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extend type Mutation {
2+
sendSignal(input: SendSignalInput!): Boolean!
3+
}
4+
5+
input SendSignalInput {
6+
dest: DestinationInput!
7+
serviceID: ID!
8+
params: StringMap
9+
}

graphql2/graphqlapp/mutation.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ package graphqlapp
33
import (
44
context "context"
55
"database/sql"
6+
"encoding/json"
67
"time"
78

89
"github.com/target/goalert/assignment"
10+
"github.com/target/goalert/expflag"
11+
"github.com/target/goalert/gadb"
912
"github.com/target/goalert/graphql2"
1013
"github.com/target/goalert/keyring"
1114
"github.com/target/goalert/permission"
@@ -14,6 +17,7 @@ import (
1417
"github.com/target/goalert/user"
1518
"github.com/target/goalert/util/sqlutil"
1619
"github.com/target/goalert/validation"
20+
"github.com/target/goalert/validation/validate"
1721

1822
"github.com/pkg/errors"
1923
)
@@ -36,6 +40,43 @@ func (a *Mutation) ReEncryptKeyringsAndConfig(ctx context.Context) (bool, error)
3640
return true, nil
3741
}
3842

43+
func (a *Mutation) SendSignal(ctx context.Context, input graphql2.SendSignalInput) (bool, error) {
44+
err := permission.LimitCheckAny(ctx, permission.User)
45+
if err != nil {
46+
return false, err
47+
}
48+
49+
if !expflag.ContextHas(ctx, expflag.UnivKeys) {
50+
return false, errors.New("feature not enabled")
51+
}
52+
53+
svcID, err := validate.ParseUUID("ServiceID", input.ServiceID)
54+
if err != nil {
55+
return false, err
56+
}
57+
58+
destID, err := a.NCStore.MapDestToID(ctx, a.DB, *input.Dest)
59+
if err != nil {
60+
return false, err
61+
}
62+
63+
data, err := json.Marshal(input.Params)
64+
if err != nil {
65+
return false, err
66+
}
67+
68+
err = gadb.New(a.DB).IntKeyInsertSignalMessage(ctx, gadb.IntKeyInsertSignalMessageParams{
69+
DestID: destID,
70+
ServiceID: svcID,
71+
Params: data,
72+
})
73+
if err != nil {
74+
return false, err
75+
}
76+
77+
return true, nil
78+
}
79+
3980
func (a *Mutation) SetFavorite(ctx context.Context, input graphql2.SetFavoriteInput) (bool, error) {
4081
var err error
4182
if input.Favorite {

graphql2/models_gen.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

service/service_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,22 @@ func TestSearchTemplate_Only_SQLGeneration(t *testing.T) {
182182
// Verify that our QueryArgs include the only parameter
183183
args := data.QueryArgs()
184184

185-
var onlyArg *interface{}
185+
var onlyArg interface{}
186+
found := false
186187
for _, arg := range args {
187188
if arg.Name == "only" {
188-
onlyArg = &arg.Value
189+
onlyArg = arg.Value
190+
found = true
189191
break
190192
}
191193
}
192194

193-
if onlyArg == nil {
195+
if !found {
194196
t.Fatal("QueryArgs() should include 'only' parameter")
195197
}
196198

197199
// Verify the argument is not nil (UUIDArray should convert the slice)
198-
if *onlyArg == nil {
200+
if onlyArg == nil {
199201
t.Error("'only' parameter should not be nil when Only slice is provided")
200202
}
201203
}

test/smoke/sendsignal_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package smoke
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
"github.com/target/goalert/expflag"
9+
"github.com/target/goalert/test/smoke/harness"
10+
)
11+
12+
// TestSendSignal tests the sendSignal mutation with a builtin-slack-channel destination.
13+
func TestSendSignal(t *testing.T) {
14+
t.Parallel()
15+
16+
const sql = `
17+
insert into escalation_policies (id, name) values
18+
({{uuid "ep"}}, 'esc policy');
19+
insert into services (id, name, escalation_policy_id) values
20+
({{uuid "svc"}}, 'service', {{uuid "ep"}});
21+
`
22+
23+
h := harness.NewHarnessWithFlags(t, sql, "nc-duplicate-table", expflag.FlagSet{expflag.UnivKeys})
24+
defer h.Close()
25+
26+
chanID := h.Slack().Channel("chan1").ID()
27+
28+
resp := h.GraphQLQuery2(fmt.Sprintf(`mutation {
29+
sendSignal(input: {
30+
serviceID: "%s",
31+
dest: {type: "builtin-slack-channel", args: {slack_channel_id: "%s"}},
32+
params: {message: "test-signal-message"}
33+
})
34+
}`, h.UUID("svc"), chanID))
35+
require.Empty(t, resp.Errors)
36+
37+
h.Slack().Channel("chan1").ExpectMessage("test-signal-message")
38+
}

web/src/schema.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ export interface Mutation {
786786
promoteSecondaryToken: boolean
787787
reEncryptKeyringsAndConfig: boolean
788788
sendContactMethodVerification: boolean
789+
sendSignal: boolean
789790
setAlertNoiseReason: boolean
790791
setConfig: boolean
791792
setFavorite: boolean
@@ -1065,6 +1066,12 @@ export interface SendContactMethodVerificationInput {
10651066
contactMethodID: string
10661067
}
10671068

1069+
export interface SendSignalInput {
1070+
dest: DestinationInput
1071+
params?: null | StringMap
1072+
serviceID: string
1073+
}
1074+
10681075
export interface Service {
10691076
alertStats: AlertStats
10701077
alertsByStatus: AlertsByStatus

0 commit comments

Comments
 (0)