Skip to content

Commit 14b6abd

Browse files
author
Rasha Moumneh
committed
Update Zendesk when Linear issue changes
When a support blocker linear issue is updated with a new comment, an internal comment is posted on its associated zendesk ticket and the ticket status is changed to "Open".
1 parent 47772de commit 14b6abd

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

lib/Synergy/Reactor/LinearNotification.pm

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,53 @@ has name => (
8080
default => 'lin',
8181
);
8282

83+
has zendesk => (
84+
is => 'ro',
85+
isa => 'Zendesk::Client',
86+
default => sub ($self) {
87+
return Synergy::Reactor::Zendesk->zendesk_client;
88+
},
89+
lazy => 1,
90+
);
91+
92+
sub linear_update_zendesk ($payload) {
93+
my $issue_id = $payload->{data}{issueId};
94+
my $issue = $self->linear->do_query(
95+
q[ query Issue {
96+
issue(id: $issue_id) {
97+
attachments { nodes { url } }
98+
labels { nodes { name } }
99+
}
100+
}])->get;
101+
102+
my $has_escalation_label = grep {
103+
lc $_{name} eq lc $self->escalation_label_name
104+
} $issue->{data}{issue}{labels}{nodes}->@*;
105+
106+
my @zendesk_url = grep {
107+
$_{url} =~ /.*fastmail\.help\/agent\/tickets\/\d*/
108+
} $issue->{data}{issue}{attachments}{nodes}->@*;
109+
110+
if ($has_escalation_label && @zendesk_url) {
111+
$zendesk_url[0] =~ /.*\/(\d*)/;
112+
113+
$self->zendesk->ticket_api->add_comment_to_ticket_f($1, {
114+
body => "Issue updated with a comment: $payload->{url}",
115+
public => \0,
116+
})->else(sub ($err, @) {
117+
$Logger->log([ "something went wrong posting to Zendesk: %s", $err ]);
118+
return Future->done;
119+
})->retain;
120+
121+
$self->zendesk->ticket_api->update_by_zendesk_id_f($1, {
122+
status => "open",
123+
})->else(sub ($err, @) {
124+
$Logger->log([ "something went wrong changing the zendesk ticket status: %s", $err ]);
125+
return Future->done;
126+
})->retain;
127+
}
128+
}
129+
83130
sub http_app ($self, $env) {
84131
my $req = Plack::Request->new($env);
85132

@@ -104,6 +151,7 @@ sub http_app ($self, $env) {
104151
return [ "200", [], [ '{"bad":"json"}' ] ];
105152
}
106153

154+
# Notify in slack if issue is escalated
107155
if ($self->escalation_channel_name && $self->escalation_address) {
108156
if (my $channel = $self->hub->channel_named($self->escalation_channel_name)) {
109157

@@ -171,6 +219,14 @@ sub http_app ($self, $env) {
171219
}
172220
}
173221

222+
# Action Zendesk ticket if comments are made on linear issues
223+
my $made_comment = $payload->{type} eq 'Issue comments'
224+
&& $payload->{action} eq 'create';
225+
226+
if ($made_comment) {
227+
linear_update_zendesk($payload);
228+
}
229+
174230
return [ "200", [], [ '{"o":"k"}' ] ];
175231
}
176232

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
use v.5.28.0;
2+
use warnings;
3+
package Synergy::Reactor::LinearZendeskIntegration;
4+
5+
use Moose;
6+
7+
with 'Synergy::Role::Reactor::EasyListening';
8+
with 'Synergy::Role::HTTPEndpoint';
9+
10+
use Synergy::Reactor::Linear;
11+
use Synergy::Reactor::Zendesk;
12+
use Synergy::Logger '$Logger';
13+
use experimental qw(signatures postderef);
14+
15+
has +http_path => (
16+
default => '/linearzendeskintegration',
17+
);
18+
19+
has escalation_label_name => (
20+
is => 'ro',
21+
isa => 'Str',
22+
default => 'support blocker',
23+
);
24+
25+
my %allowed = (
26+
'35.231.147.226' => 1,
27+
'35.243.134.228' => 1,
28+
);
29+
30+
has confirm_remote_ips => (
31+
is => 'ro',
32+
isa => 'Bool',
33+
default => 1,
34+
);
35+
36+
has linear_token => (
37+
is => 'ro',
38+
required => 1,
39+
);
40+
41+
has linear => (
42+
is => 'ro',
43+
isa => 'Linear::Client',
44+
default => sub ($self) {
45+
Linear::Client->new({
46+
auth_token => $self->linear_token,
47+
helper => Synergy::Reactor::Linear::LinearHelper->new_for_reactor($self),
48+
});
49+
},
50+
lazy => 1,
51+
);
52+
53+
has zendesk => (
54+
is => 'ro',
55+
isa => 'Zendesk::Client',
56+
default => sub ($self) {
57+
return Synergy::Reactor::Zendesk->zendesk_client;
58+
},
59+
lazy => 1,
60+
);
61+
62+
sub http_app ($self, $env) {
63+
my $req = Plack::Request->new($env);
64+
65+
if ($self->confirm_remote_ips) {
66+
unless ($allowed{$req->address}) {
67+
warn "ADDRESS " . $req->address . " not allowed\n";
68+
return [ "200", [], ['{"go":"away"}'] ];
69+
}
70+
}
71+
72+
my $err;
73+
74+
my $payload = try {
75+
decode_json( $req->raw_body );
76+
} catch {
77+
$err = $_;
78+
};
79+
80+
if ($err) {
81+
warn "Failed to parse json: $err\n";
82+
83+
return [ "200", [], [ '{"bad":"json"}' ] ];
84+
}
85+
86+
my $made_comment = $payload->{type} eq 'Issue comments'
87+
&& $payload->{action} eq 'create';
88+
89+
if ($made_comment) {
90+
my $issue_id = $payload->{data}{issueId};
91+
my $issue = $self->linear->do_query(
92+
q[ query Issue {
93+
issue(id: $issue_id) {
94+
attachments { nodes { url } }
95+
labels { nodes { name } }
96+
}
97+
}])->get;
98+
99+
my $has_escalation_label = grep {
100+
lc $_{name} eq lc $self->escalation_label_name
101+
} $issue->{data}{issue}{labels}{nodes}->@*;
102+
103+
my @zendesk_url = grep {
104+
$_{url} =~ /.*fastmail\.help\/agent\/tickets\/\d*/
105+
} $issue->{data}{issue}{attachments}{nodes}->@*;
106+
107+
if ($has_escalation_label && @zendesk_url) {
108+
$zendesk_url[0] =~ /.*\/(\d*)/;
109+
110+
$self->zendesk->ticket_api->add_comment_to_ticket_f($1, {
111+
body => "Issue updated with a comment: $payload->{url}",
112+
public => \0,
113+
})->else(sub ($err, @) {
114+
$Logger->log([ "something went wrong posting to Zendesk: %s", $err ]);
115+
return Future->done;
116+
})->retain;
117+
118+
$self->zendesk->ticket_api->update_by_zendesk_id_f($1, {
119+
status => "open",
120+
})->else(sub ($err, @) {
121+
$Logger->log([ "something went wrong changing the zendesk ticket status: %s", $err ]);
122+
return Future->done;
123+
})->retain;
124+
}
125+
}
126+
return [ "200", [], [ '{"o":"k"}' ] ];
127+
}
128+
129+
sub listener_specs {
130+
return {
131+
name => 'linear_zendesk_notification',
132+
method => 'linear_zendesk_notification',
133+
predicate => sub ($, $e) { 0 },
134+
};
135+
}
136+
137+
no Moose;
138+
1;

0 commit comments

Comments
 (0)