Skip to content

Listen forge app installation event (not uninstallation) #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 23 additions & 22 deletions manifest.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
# https://developer.atlassian.com/platform/forge/manifest-reference/#app
app:
id: ari:cloud:ecosystem::app/f434bcc5-834f-45e5-ba1d-62e2ee8952cd
runtime:
name: nodejs20.x # https://developer.atlassian.com/platform/forge/manifest-reference/#runtime
licensing:
enabled: false # https://developer.atlassian.com/platform/marketplace/listing-forge-apps/#enabling-licensing-for-your-app

# https://developer.atlassian.com/platform/forge/manifest-reference/resources/#resources
resources:
- key: main
path: src/frontend/index.jsx

modules:
# Trigger is used to invoke a function when a Jira issue event is fired.
# https://developer.atlassian.com/platform/forge/manifest-reference/modules/trigger/
# trigger:
# - key: issue-trigger
# function: webhook
# # https://developer.atlassian.com/platform/forge/events-reference/jira/#issue-events
# events:
# - avi:jira:created:issue
# - avi:jira:updated:issue
# filter:
# ignoreSelf: true # Prevents infinite loops by ignoring self-generated events
# # expression: event.issue.fields.issuetype.name == 'Bug' # Optional: example filter for bug issues only
# onError: IGNORE_AND_LOG # Will invoke function and log errors
trigger:
- key: installation-trigger
function: webhook
events:
# https://developer.atlassian.com/platform/forge/events-reference/life-cycle/
- avi:forge:installed:app # Doesn't include un-installation
- avi:forge:upgraded:app

# The jira module provides functionality for Jira products.
jira:issuePanel:
Expand All @@ -27,18 +36,10 @@ modules:
function:
- key: resolver
handler: index.handler
# - key: webhook
# handler: webhook.handler

resources:
- key: main
path: src/frontend/index.jsx
app:
runtime:
name: nodejs20.x # Has to be 'sandbox', 'nodejs18.x', 'nodejs20.x'
id: ari:cloud:ecosystem::app/f434bcc5-834f-45e5-ba1d-62e2ee8952cd
- key: webhook
handler: webhook.handler

# Environment variables are not supported in the manifest.yml file.
# Environment variables are not supported in "permissions" section.
# https://developer.atlassian.com/platform/forge/manifest-reference/permissions/
# It takes a few hours to 1 day to update here: https://developer.atlassian.com/console/myapps/f434bcc5-834f-45e5-ba1d-62e2ee8952cd/manage/permissions
permissions:
Expand Down
77 changes: 60 additions & 17 deletions src/webhook.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,66 @@
// Handle only webhook events
import forge, { route } from "@forge/api";

export const handler = async (event, context) => {
console.log("Event: ", event);
console.log("Context: ", context);
const { changelog } = event;
console.log("Changelog: ", changelog);
// https://developer.atlassian.com/platform/forge/events-reference/life-cycle/
console.log("Installation event payload:", event);
console.log("Context:", context);

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

if (event.type === "avi:jira:updated:issue") {
return handleIssueUpdated(event);
}
};
// Extract cloudId and contextToken
const cloudId = event.context.cloudId;
const contextToken = event.contextToken;

const handleIssueCreated = async (event) => {
console.log("Issue created");
};
try {
let startAt = 0;
const maxResults = 50; // Number of results per page
let allProjects = [];
let isLastPage = false;

while (!isLastPage) {
// https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-projects/#api-rest-api-3-project-search-get
const url = route`/rest/api/3/project/search?startAt=${startAt}&maxResults=${maxResults}`;
const response = await forge
.asApp()
.requestJira(url, { headers: { Accept: "application/json" } });

// Add status code checking and response logging
if (!response.ok) {
console.error("API request failed:", {
status: response.status,
statusText: response.statusText,
body: await response.text(),
});
throw new Error(`API request failed with status ${response.status}`);
}

const result = await response.json();
// console.log("Raw API response:", JSON.stringify(result, null, 2));
const { values, total, isLast } = result;

allProjects = [...allProjects, ...values];
isLastPage = isLast;
startAt += maxResults;

console.log(`Fetched ${values.length} projects. Total: ${total}. Page complete: ${isLast}`);
}

console.log(
"All projects found:",
allProjects.map((p) => ({
id: p.id,
key: p.key,
name: p.name,
}))
);
} catch (error) {
console.error("Error fetching projects:", error);
}
} else if (event.eventType === "avi:forge:upgraded:app") {
console.log("App was upgraded!");
// Handle upgrade logic here
}

const handleIssueUpdated = async (event) => {
console.log("Issue updated");
return { status: 200, body: "Installation event processed" };
};
Loading