Skip to content

Commit 3bef5b5

Browse files
Merge pull request #26 from gitautoai/wes
Listen forge app installation event (not uninstallation)
2 parents bd7f821 + b3e244f commit 3bef5b5

File tree

2 files changed

+83
-39
lines changed

2 files changed

+83
-39
lines changed

manifest.yml

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1+
# https://developer.atlassian.com/platform/forge/manifest-reference/#app
2+
app:
3+
id: ari:cloud:ecosystem::app/f434bcc5-834f-45e5-ba1d-62e2ee8952cd
4+
runtime:
5+
name: nodejs20.x # https://developer.atlassian.com/platform/forge/manifest-reference/#runtime
6+
licensing:
7+
enabled: false # https://developer.atlassian.com/platform/marketplace/listing-forge-apps/#enabling-licensing-for-your-app
8+
9+
# https://developer.atlassian.com/platform/forge/manifest-reference/resources/#resources
10+
resources:
11+
- key: main
12+
path: src/frontend/index.jsx
13+
114
modules:
215
# Trigger is used to invoke a function when a Jira issue event is fired.
316
# https://developer.atlassian.com/platform/forge/manifest-reference/modules/trigger/
4-
# trigger:
5-
# - key: issue-trigger
6-
# function: webhook
7-
# # https://developer.atlassian.com/platform/forge/events-reference/jira/#issue-events
8-
# events:
9-
# - avi:jira:created:issue
10-
# - avi:jira:updated:issue
11-
# filter:
12-
# ignoreSelf: true # Prevents infinite loops by ignoring self-generated events
13-
# # expression: event.issue.fields.issuetype.name == 'Bug' # Optional: example filter for bug issues only
14-
# onError: IGNORE_AND_LOG # Will invoke function and log errors
17+
trigger:
18+
- key: installation-trigger
19+
function: webhook
20+
events:
21+
# https://developer.atlassian.com/platform/forge/events-reference/life-cycle/
22+
- avi:forge:installed:app # Doesn't include un-installation
23+
- avi:forge:upgraded:app
1524

1625
# The jira module provides functionality for Jira products.
1726
jira:issuePanel:
@@ -27,18 +36,10 @@ modules:
2736
function:
2837
- key: resolver
2938
handler: index.handler
30-
# - key: webhook
31-
# handler: webhook.handler
32-
33-
resources:
34-
- key: main
35-
path: src/frontend/index.jsx
36-
app:
37-
runtime:
38-
name: nodejs20.x # Has to be 'sandbox', 'nodejs18.x', 'nodejs20.x'
39-
id: ari:cloud:ecosystem::app/f434bcc5-834f-45e5-ba1d-62e2ee8952cd
39+
- key: webhook
40+
handler: webhook.handler
4041

41-
# Environment variables are not supported in the manifest.yml file.
42+
# Environment variables are not supported in "permissions" section.
4243
# https://developer.atlassian.com/platform/forge/manifest-reference/permissions/
4344
# It takes a few hours to 1 day to update here: https://developer.atlassian.com/console/myapps/f434bcc5-834f-45e5-ba1d-62e2ee8952cd/manage/permissions
4445
permissions:

src/webhook.js

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,66 @@
1-
// Handle only webhook events
1+
import forge, { route } from "@forge/api";
2+
23
export const handler = async (event, context) => {
3-
console.log("Event: ", event);
4-
console.log("Context: ", context);
5-
const { changelog } = event;
6-
console.log("Changelog: ", changelog);
4+
// https://developer.atlassian.com/platform/forge/events-reference/life-cycle/
5+
console.log("Installation event payload:", event);
6+
console.log("Context:", context);
77

8-
if (event.type === "avi:jira:created:issue") {
9-
return handleIssueCreated(event);
10-
}
8+
if (event.eventType === "avi:forge:installed:app") {
9+
console.log("App was installed!");
1110

12-
if (event.type === "avi:jira:updated:issue") {
13-
return handleIssueUpdated(event);
14-
}
15-
};
11+
// Extract cloudId and contextToken
12+
const cloudId = event.context.cloudId;
13+
const contextToken = event.contextToken;
1614

17-
const handleIssueCreated = async (event) => {
18-
console.log("Issue created");
19-
};
15+
try {
16+
let startAt = 0;
17+
const maxResults = 50; // Number of results per page
18+
let allProjects = [];
19+
let isLastPage = false;
20+
21+
while (!isLastPage) {
22+
// https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-projects/#api-rest-api-3-project-search-get
23+
const url = route`/rest/api/3/project/search?startAt=${startAt}&maxResults=${maxResults}`;
24+
const response = await forge
25+
.asApp()
26+
.requestJira(url, { headers: { Accept: "application/json" } });
27+
28+
// Add status code checking and response logging
29+
if (!response.ok) {
30+
console.error("API request failed:", {
31+
status: response.status,
32+
statusText: response.statusText,
33+
body: await response.text(),
34+
});
35+
throw new Error(`API request failed with status ${response.status}`);
36+
}
37+
38+
const result = await response.json();
39+
// console.log("Raw API response:", JSON.stringify(result, null, 2));
40+
const { values, total, isLast } = result;
41+
42+
allProjects = [...allProjects, ...values];
43+
isLastPage = isLast;
44+
startAt += maxResults;
45+
46+
console.log(`Fetched ${values.length} projects. Total: ${total}. Page complete: ${isLast}`);
47+
}
48+
49+
console.log(
50+
"All projects found:",
51+
allProjects.map((p) => ({
52+
id: p.id,
53+
key: p.key,
54+
name: p.name,
55+
}))
56+
);
57+
} catch (error) {
58+
console.error("Error fetching projects:", error);
59+
}
60+
} else if (event.eventType === "avi:forge:upgraded:app") {
61+
console.log("App was upgraded!");
62+
// Handle upgrade logic here
63+
}
2064

21-
const handleIssueUpdated = async (event) => {
22-
console.log("Issue updated");
65+
return { status: 200, body: "Installation event processed" };
2366
};

0 commit comments

Comments
 (0)