Skip to content

Commit a68048d

Browse files
authored
Fall back to polling triggers if user is not a Linear admin (#14920)
* fallback to polling sources * pnpm-lock.yaml * version * update
1 parent 1006518 commit a68048d

File tree

11 files changed

+174
-95
lines changed

11 files changed

+174
-95
lines changed

components/linear/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/linear",
3-
"version": "0.5.6",
3+
"version": "0.5.7",
44
"description": "Pipedream Linear Components",
55
"main": "linear.app.mjs",
66
"keywords": [

components/linear/sources/comment-created-instant/comment-created-instant.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ export default {
99
...commentCreatedInstant,
1010
...utils.getAppProps(commentCreatedInstant),
1111
key: "linear-comment-created-instant",
12-
description: "Emit new event when a new comment is created (OAuth). See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
13-
version: "0.1.6",
12+
description: "Emit new event when a new comment is created (OAuth). [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
13+
version: "0.1.7",
1414
};

components/linear/sources/issue-created-instant/issue-created-instant.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ export default {
99
...issueCreatedInstant,
1010
...utils.getAppProps(issueCreatedInstant),
1111
key: "linear-issue-created-instant",
12-
description: "Emit new event when a new issue is created (OAuth). See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
13-
version: "0.3.6",
12+
description: "Emit new event when a new issue is created (OAuth). [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
13+
version: "0.3.7",
1414
};

components/linear/sources/issue-updated-instant/issue-updated-instant.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ export default {
99
...issueUpdatedInstant,
1010
...utils.getAppProps(issueUpdatedInstant),
1111
key: "linear-issue-updated-instant",
12-
description: "Emit new event when an issue is updated (OAuth). See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
13-
version: "0.3.6",
12+
description: "Emit new event when an issue is updated (OAuth). See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
13+
version: "0.3.7",
1414
};

components/linear/sources/new-issue-status-updated/new-issue-status-updated.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ export default {
99
...newIssueStatusUpdated,
1010
...utils.getAppProps(newIssueStatusUpdated),
1111
key: "linear-new-issue-status-updated",
12-
description: "Emit new event when the status of an issue is updated (OAuth). See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
13-
version: "0.1.6",
12+
description: "Emit new event when the status of an issue is updated (OAuth). [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
13+
version: "0.1.7",
1414
};

components/linear_app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/linear_app",
3-
"version": "0.5.6",
3+
"version": "0.5.7",
44
"description": "Pipedream Linear_app Components",
55
"main": "linear_app.app.mjs",
66
"keywords": [

components/linear_app/sources/comment-created-instant/comment-created-instant.mjs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export default {
55
...common,
66
key: "linear_app-comment-created-instant",
77
name: "New Created Comment (Instant)",
8-
description: "Emit new event when a new comment is created. See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
8+
description: "Emit new event when a new comment is created. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
99
type: "source",
10-
version: "0.1.6",
10+
version: "0.1.7",
1111
dedupe: "unique",
1212
methods: {
1313
...common.methods,
@@ -50,6 +50,11 @@ export default {
5050
},
5151
};
5252
},
53+
getResource(comment) {
54+
return this.linearApp.getComment({
55+
commentId: comment.id,
56+
});
57+
},
5358
getMetadata(resource) {
5459
const {
5560
delivery,
Lines changed: 90 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import linearApp from "../../linear_app.app.mjs";
22
import constants from "../../common/constants.mjs";
33
import utils from "../../common/utils.mjs";
4-
import { ConfigurationError } from "@pipedream/platform";
4+
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
55

66
export default {
77
props: {
@@ -21,18 +21,28 @@ export default {
2121
"projectId",
2222
],
2323
},
24-
http: "$.interface.http",
2524
db: "$.service.db",
2625
},
2726
async additionalProps() {
2827
const props = {};
29-
if (!(await this.isAdmin())) {
30-
props.alert = {
31-
type: "alert",
32-
alertType: "error",
33-
content: "You must have an admin role to create or manage webhooks. See the Linear [documentation](https://linear.app/docs/api-and-webhooks#webhooks) for details.",
28+
let msg;
29+
if (await this.isAdmin()) {
30+
msg = "Admin role detected. Trigger will be set up as a webhook.";
31+
props.http = "$.interface.http";
32+
} else {
33+
msg = "No admin role detected. Trigger will set up to use polling.";
34+
props.timer = {
35+
type: "$.interface.timer",
36+
default: {
37+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
38+
},
3439
};
3540
}
41+
props.alert = {
42+
type: "alert",
43+
alertType: "info",
44+
content: `${msg} See the Linear [documentation](https://linear.app/docs/api-and-webhooks#webhooks) for details.`,
45+
};
3646
return props;
3747
},
3848
methods: {
@@ -54,6 +64,9 @@ export default {
5464
useGraphQl() {
5565
return true;
5666
},
67+
getResource() {
68+
throw new Error("getResource is not implemented");
69+
},
5770
getResourceTypes() {
5871
throw new Error("getResourceTypes is not implemented");
5972
},
@@ -85,15 +98,7 @@ export default {
8598
});
8699
return data?.user?.admin;
87100
},
88-
},
89-
hooks: {
90-
async deploy() {
91-
if (!(await this.isAdmin())) {
92-
throw new ConfigurationError("You must have an admin role to create or manage webhooks. See the Linear [documentation](https://linear.app/docs/api-and-webhooks#webhooks) for details.");
93-
}
94-
95-
// Retrieve historical events
96-
console.log("Retrieving historical events...");
101+
async emitPolledResources() {
97102
const stream = this.linearApp.paginateResources({
98103
resourcesFn: this.getResourcesFn(),
99104
resourcesFnArgs: this.getResourcesFnArgs(),
@@ -107,73 +112,89 @@ export default {
107112
this.$emit(resource, this.getMetadata(resource));
108113
});
109114
},
115+
},
116+
hooks: {
117+
async deploy() {
118+
// Retrieve historical events
119+
console.log("Retrieving historical events...");
120+
await this.emitPolledResources();
121+
},
110122
async activate() {
111-
const args = {
112-
resourceTypes: this.getResourceTypes(),
113-
url: this.http.endpoint,
114-
label: this.getWebhookLabel(),
115-
};
116-
if (!this.teamIds && !this.teamId) {
117-
args.allPublicTeams = true;
118-
const { _webhook: webhook } = await this.linearApp.createWebhook(args);
119-
this.setWebhookId("1", webhook.id);
120-
return;
121-
}
122-
const teamIds = this.teamIds || [
123-
this.teamId,
124-
];
125-
for (const teamId of teamIds) {
126-
const { _webhook: webhook } =
127-
await this.linearApp.createWebhook({
128-
teamId,
129-
...args,
130-
});
131-
this.setWebhookId(teamId, webhook.id);
123+
if (await this.isAdmin()) {
124+
const args = {
125+
resourceTypes: this.getResourceTypes(),
126+
url: this.http.endpoint,
127+
label: this.getWebhookLabel(),
128+
};
129+
if (!this.teamIds && !this.teamId) {
130+
args.allPublicTeams = true;
131+
const { _webhook: webhook } = await this.linearApp.createWebhook(args);
132+
this.setWebhookId("1", webhook.id);
133+
return;
134+
}
135+
const teamIds = this.teamIds || [
136+
this.teamId,
137+
];
138+
for (const teamId of teamIds) {
139+
const { _webhook: webhook } =
140+
await this.linearApp.createWebhook({
141+
teamId,
142+
...args,
143+
});
144+
this.setWebhookId(teamId, webhook.id);
145+
}
132146
}
133147
},
134148
async deactivate() {
135-
if (!this.teamIds && !this.teamId) {
136-
const webhookId = this.getWebhookId("1");
137-
if (webhookId) {
138-
await this.linearApp.deleteWebhook(webhookId);
149+
if (await this.isAdmin()) {
150+
if (!this.teamIds && !this.teamId) {
151+
const webhookId = this.getWebhookId("1");
152+
if (webhookId) {
153+
await this.linearApp.deleteWebhook(webhookId);
154+
}
155+
return;
139156
}
140-
return;
141-
}
142-
const teamIds = this.teamIds || [
143-
this.teamId,
144-
];
145-
for (const teamId of teamIds) {
146-
const webhookId = this.getWebhookId(teamId);
147-
if (webhookId) {
148-
await this.linearApp.deleteWebhook(webhookId);
157+
const teamIds = this.teamIds || [
158+
this.teamId,
159+
];
160+
for (const teamId of teamIds) {
161+
const webhookId = this.getWebhookId(teamId);
162+
if (webhookId) {
163+
await this.linearApp.deleteWebhook(webhookId);
164+
}
149165
}
150166
}
151167
},
152168
},
153169
async run(event) {
154-
const {
155-
client_ip: clientIp,
156-
body,
157-
headers,
158-
} = event;
170+
if (!(await this.isAdmin())) {
171+
await this.emitPolledResources();
172+
} else {
173+
const {
174+
client_ip: clientIp,
175+
body,
176+
headers,
177+
} = event;
159178

160-
const { [constants.LINEAR_DELIVERY_HEADER]: delivery } = headers;
179+
const { [constants.LINEAR_DELIVERY_HEADER]: delivery } = headers;
161180

162-
const resource = {
163-
...body,
164-
delivery,
165-
};
181+
const resource = {
182+
...body,
183+
delivery,
184+
};
166185

167-
if (!this.isWebhookValid(clientIp)) {
168-
console.log("Webhook is not valid");
169-
return;
170-
}
186+
if (!this.isWebhookValid(clientIp)) {
187+
console.log("Webhook is not valid");
188+
return;
189+
}
171190

172-
if (!(await this.isFromProject(body)) || !this.isRelevant(body)) {
173-
return;
174-
}
191+
if (!(await this.isFromProject(body)) || !this.isRelevant(body)) {
192+
return;
193+
}
175194

176-
const meta = this.getMetadata(resource);
177-
this.$emit(body, meta);
195+
const meta = this.getMetadata(resource);
196+
const item = await this.getResource(body.data);
197+
this.$emit(item, meta);
198+
}
178199
},
179200
};

components/linear_app/sources/issue-created-instant/issue-created-instant.mjs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export default {
55
...common,
66
key: "linear_app-issue-created-instant",
77
name: "New Created Issue (Instant)",
8-
description: "Emit new event when a new issue is created. See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
8+
description: "Emit new event when a new issue is created. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
99
type: "source",
10-
version: "0.3.6",
10+
version: "0.3.7",
1111
dedupe: "unique",
1212
methods: {
1313
...common.methods,
@@ -42,6 +42,11 @@ export default {
4242
isRelevant(body) {
4343
return body?.action === "create";
4444
},
45+
getResource(issue) {
46+
return this.linearApp.getIssue({
47+
issueId: issue.id,
48+
});
49+
},
4550
getMetadata(resource) {
4651
const {
4752
delivery,

components/linear_app/sources/issue-updated-instant/issue-updated-instant.mjs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export default {
55
...common,
66
key: "linear_app-issue-updated-instant",
77
name: "New Updated Issue (Instant)",
8-
description: "Emit new event when an issue is updated. See the docs [here](https://developers.linear.app/docs/graphql/webhooks)",
8+
description: "Emit new event when an issue is updated. [See the documentation](https://developers.linear.app/docs/graphql/webhooks)",
99
type: "source",
10-
version: "0.3.6",
10+
version: "0.3.7",
1111
dedupe: "unique",
1212
methods: {
1313
...common.methods,
@@ -39,17 +39,22 @@ export default {
3939
},
4040
};
4141
},
42+
getResource(issue) {
43+
return this.linearApp.getIssue({
44+
issueId: issue.id,
45+
});
46+
},
4247
getMetadata(resource) {
4348
const {
44-
delivery,
4549
title,
4650
data,
4751
updatedAt,
4852
} = resource;
53+
const ts = Date.parse(data?.updatedAt || updatedAt);
4954
return {
50-
id: delivery || resource.id,
55+
id: `${resource.id}-${ts}`,
5156
summary: `Issue Updated: ${data?.title || title}`,
52-
ts: Date.parse(updatedAt),
57+
ts,
5358
};
5459
},
5560
},

0 commit comments

Comments
 (0)