Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Config/context overridden by another webhook #801

Draft
wants to merge 13 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 8 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
11 changes: 6 additions & 5 deletions src/adapters/supabase/helpers/log.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getAdapters, getBotContext, Logger } from "../../../bindings";
import { Payload, LogLevel } from "../../../types";
import { getAdapters, Logger } from "../../../bindings";
import { Payload, LogLevel, BotContext } from "../../../types";
import { getOrgAndRepoFromPath } from "../../../utils/private";

interface Log {
Expand Down Expand Up @@ -43,13 +43,15 @@ export class GitHubLogger implements Logger {
private retryDelay = 1000; // Delay between retries in milliseconds
private throttleCount = 0;
private retryLimit = 0; // Retries disabled by default
private context;

constructor(app: string, logEnvironment: string, maxLevel: LogLevel, retryLimit: number) {
constructor(context: BotContext, app: string, logEnvironment: string, maxLevel: LogLevel, retryLimit: number) {
this.app = app;
this.logEnvironment = logEnvironment;
this.maxLevel = getNumericLevel(maxLevel);
this.retryLimit = retryLimit;
this.supabase = getAdapters().supabase;
this.context = context;
}

async sendLogsToSupabase({ repo, org, commentId, issueNumber, logMessage, level, timestamp }: Log) {
Expand Down Expand Up @@ -132,8 +134,7 @@ export class GitHubLogger implements Logger {
private save(logMessage: string | object, level: LogLevel, errorPayload?: string | object) {
if (getNumericLevel(level) > this.maxLevel) return; // only return errors lower than max level

const context = getBotContext();
const payload = context.payload as Payload;
const payload = this.context.payload as Payload;
const timestamp = new Date().toUTCString();

const { comment, issue, repository } = payload;
Expand Down
11 changes: 6 additions & 5 deletions src/adapters/telegram/helpers/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Input } from "telegraf";
import { getAdapters, getBotConfig } from "../../../bindings";
import { getAdapters } from "../../../bindings";
import { BotContext } from "../../../types";
import { TLMessageFormattedPayload, TLMessagePayload, TLPhotoPayload } from "../types/payload";

export function messageFormatter(messagePayload: TLMessagePayload) {
Expand All @@ -14,10 +15,10 @@ export function messageFormatter(messagePayload: TLMessagePayload) {
return msgObj;
}

export async function telegramFormattedNotifier(messagePayload: TLMessageFormattedPayload) {
export async function telegramFormattedNotifier(context: BotContext, messagePayload: TLMessageFormattedPayload) {
const {
telegram: { delay },
} = getBotConfig();
} = context.botConfig;
const { telegram } = getAdapters();
const { chatIds, text, parseMode } = messagePayload;

Expand All @@ -40,14 +41,14 @@ export async function telegramFormattedNotifier(messagePayload: TLMessageFormatt
sendHandler();
}

export async function telegramNotifier(messagePayload: TLMessagePayload) {
export async function telegramNotifier(context: BotContext, messagePayload: TLMessagePayload) {
const messageString = messageFormatter(messagePayload);
const messageObj: TLMessageFormattedPayload = {
chatIds: messagePayload.chatIds,
text: messageString,
parseMode: "HTML",
};
await telegramFormattedNotifier(messageObj);
await telegramFormattedNotifier(context, messageObj);
}

export async function telegramPhotoNotifier(messagePayload: TLPhotoPayload) {
Expand Down
45 changes: 19 additions & 26 deletions src/bindings/event.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Context } from "probot";
import { createAdapters } from "../adapters";
import { processors, wildcardProcessors } from "../handlers/processors";
import { shouldSkip } from "../helpers";
import { BotConfig, GithubEvent, Payload, PayloadSchema, LogLevel } from "../types";
import { BotContext, GithubEvent, Payload, PayloadSchema, LogLevel } from "../types";
Sadaf-A marked this conversation as resolved.
Show resolved Hide resolved
import { Adapters } from "../types/adapters";
import { ajv } from "../utils";
import { loadConfig } from "./config";
import { GitHubLogger } from "../adapters/supabase";
import { validateConfigChange } from "../handlers/push";

let botContext: Context = {} as Context;
export const getBotContext = () => botContext;

let botConfig: BotConfig = {} as BotConfig;
export const getBotConfig = () => botConfig;

let adapters: Adapters = {} as Adapters;
export const getAdapters = () => adapters;

Expand All @@ -30,32 +23,32 @@ export const getLogger = (): Logger => logger;

const NO_VALIDATION = [GithubEvent.INSTALLATION_ADDED_EVENT as string, GithubEvent.PUSH_EVENT as string];

export const bindEvents = async (context: Context): Promise<void> => {
export const bindEvents = async (context: BotContext): Promise<void> => {
Sadaf-A marked this conversation as resolved.
Show resolved Hide resolved
const { id, name } = context;
botContext = context;
const payload = context.payload as Payload;
const allowedEvents = Object.values(GithubEvent) as string[];
const eventName = payload.action ? `${name}.${payload.action}` : name; // some events wont have actions as this grows

let botConfigError;
try {
botConfig = await loadConfig(context);
context.botConfig = await loadConfig(context);
} catch (err) {
botConfigError = err;
}

adapters = createAdapters(botConfig);
adapters = createAdapters(context.botConfig);

const options = {
app: "UbiquiBot",
// level: botConfig.log.level,
};

logger = new GitHubLogger(
context,
options.app,
botConfig?.log?.logEnvironment ?? "development",
botConfig?.log?.level ?? LogLevel.DEBUG,
botConfig?.log?.retryLimit ?? 0
context.botConfig?.log?.logEnvironment ?? "development",
context.botConfig?.log?.level ?? LogLevel.DEBUG,
context.botConfig?.log?.retryLimit ?? 0
); // contributors will see logs in console while on development env
if (!logger) {
return;
Expand All @@ -64,7 +57,7 @@ export const bindEvents = async (context: Context): Promise<void> => {
if (botConfigError) {
logger.error(botConfigError.toString());
if (eventName === GithubEvent.PUSH_EVENT) {
await validateConfigChange();
await validateConfigChange(context);
}
return;
}
Expand All @@ -74,11 +67,11 @@ export const bindEvents = async (context: Context): Promise<void> => {

logger.info(
`Config loaded! config: ${JSON.stringify({
price: botConfig.price,
unassign: botConfig.unassign,
mode: botConfig.mode,
log: botConfig.log,
wallet: botConfig.wallet,
price: context.botConfig.price,
unassign: context.botConfig.unassign,
mode: context.botConfig.mode,
log: context.botConfig.log,
wallet: context.botConfig.wallet,
})}`
);

Expand All @@ -102,7 +95,7 @@ export const bindEvents = async (context: Context): Promise<void> => {
}

// Check if we should skip the event
const { skip, reason } = shouldSkip();
const { skip, reason } = shouldSkip(context);
if (skip) {
logger.info(`Skipping the event. reason: ${reason}`);
return;
Expand All @@ -120,26 +113,26 @@ export const bindEvents = async (context: Context): Promise<void> => {
// Run pre-handlers
logger.info(`Running pre handlers: ${pre.map((fn) => fn.name)}, event: ${eventName}`);
for (const preAction of pre) {
await preAction();
await preAction(context);
}
// Run main handlers
logger.info(`Running main handlers: ${action.map((fn) => fn.name)}, event: ${eventName}`);
for (const mainAction of action) {
await mainAction();
await mainAction(context);
}

// Run post-handlers
logger.info(`Running post handlers: ${post.map((fn) => fn.name)}, event: ${eventName}`);
for (const postAction of post) {
await postAction();
await postAction(context);
}

// Skip wildcard handlers for installation event and push event
if (eventName !== GithubEvent.INSTALLATION_ADDED_EVENT && eventName !== GithubEvent.PUSH_EVENT) {
// Run wildcard handlers
logger.info(`Running wildcard handlers: ${wildcardProcessors.map((fn) => fn.name)}`);
for (const wildcardProcessor of wildcardProcessors) {
await wildcardProcessor();
await wildcardProcessor(context);
}
}
};
15 changes: 7 additions & 8 deletions src/handlers/access/labels-access.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { getAccessLevel } from "../../adapters/supabase";
import { getBotConfig, getBotContext, getLogger } from "../../bindings";
import { getLogger } from "../../bindings";
import { addCommentToIssue, getUserPermission, removeLabel, addLabelToIssue } from "../../helpers";
import { Payload } from "../../types";
import { BotContext, Payload } from "../../types";

export const handleLabelsAccess = async () => {
const { accessControl } = getBotConfig();
export const handleLabelsAccess = async (context: BotContext) => {
const { accessControl } = context.botConfig;
if (!accessControl.label) return true;

const context = getBotContext();
const logger = getLogger();
const payload = context.payload as Payload;
if (!payload.issue) return;
Expand All @@ -34,12 +33,12 @@ export const handleLabelsAccess = async () => {

if (payload.action === "labeled") {
// remove the label
await removeLabel(labelName);
await removeLabel(context, labelName);
} else if (payload.action === "unlabeled") {
// add the label
await addLabelToIssue(labelName);
await addLabelToIssue(context, labelName);
}
await addCommentToIssue(`@${sender}, You are not allowed to ${eventName} ${labelName}`, payload.issue.number);
await addCommentToIssue(context, `@${sender}, You are not allowed to ${eventName} ${labelName}`, payload.issue.number);
logger.info(`@${sender} is not allowed to ${eventName} ${labelName}`);
return false;
}
Expand Down
18 changes: 8 additions & 10 deletions src/handlers/assign/action.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { getBotConfig, getBotContext, getLogger } from "../../bindings";
import { getLogger } from "../../bindings";
import { addCommentToIssue, closePullRequest, calculateWeight, calculateDuration } from "../../helpers";
import { gitLinkedPrParser } from "../../helpers/parser";
import { Payload, LabelItem } from "../../types";
import { Payload, LabelItem, BotContext } from "../../types";
import { deadLinePrefix } from "../shared";

const exclude_accounts: string[] = [];
export const commentWithAssignMessage = async (): Promise<void> => {
const context = getBotContext();
const config = getBotConfig();
export const commentWithAssignMessage = async (context: BotContext): Promise<void> => {
const config = context.botConfig;
const logger = getLogger();
const payload = context.payload as Payload;
if (!payload.issue) {
Expand Down Expand Up @@ -64,11 +63,10 @@ export const commentWithAssignMessage = async (): Promise<void> => {
const commit_msg = `${flattened_assignees} ${deadLinePrefix} ${endDate.toUTCString().replace("GMT", "UTC")}`;
logger.debug(`Creating an issue comment, commit_msg: ${commit_msg}`);

await addCommentToIssue(commit_msg, payload.issue?.number);
await addCommentToIssue(context, commit_msg, payload.issue?.number);
};

export const closePullRequestForAnIssue = async (): Promise<void> => {
const context = getBotContext();
export const closePullRequestForAnIssue = async (context: BotContext): Promise<void> => {
const logger = getLogger();
const payload = context.payload as Payload;
if (!payload.issue?.number) return;
Expand All @@ -84,8 +82,8 @@ export const closePullRequestForAnIssue = async (): Promise<void> => {
logger.info(`Opened prs for this issue: ${JSON.stringify(prs)}`);
let comment = `These linked pull requests are closed: `;
for (let i = 0; i < prs.length; i++) {
await closePullRequest(prs[i].prNumber);
await closePullRequest(context, prs[i].prNumber);
comment += ` <a href="${prs[i].prHref}">#${prs[i].prNumber}</a> `;
}
await addCommentToIssue(comment, payload.issue.number);
await addCommentToIssue(context, comment, payload.issue.number);
};
9 changes: 4 additions & 5 deletions src/handlers/assign/auto.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { getBotContext, getLogger } from "../../bindings";
import { getLogger } from "../../bindings";
import { addAssignees, getAllPullRequests, getIssueByNumber, getPullByNumber } from "../../helpers";
import { gitLinkedIssueParser } from "../../helpers/parser";
import { Payload } from "../../types";
import { BotContext, Payload } from "../../types";

// Check for pull requests linked to their respective issues but not assigned to them
export const checkPullRequests = async () => {
const context = getBotContext();
export const checkPullRequests = async (context: BotContext) => {
const logger = getLogger();
const pulls = await getAllPullRequests(context);

Expand Down Expand Up @@ -53,7 +52,7 @@ export const checkPullRequests = async () => {

const assignedUsernames = issue.assignees.map((assignee) => assignee.login);
if (!assignedUsernames.includes(opener)) {
await addAssignees(+linkedIssueNumber, [opener]);
await addAssignees(context, +linkedIssueNumber, [opener]);
logger.debug(`Assigned pull request #${pull.number} opener to issue ${linkedIssueNumber}.`);
}
}
Expand Down
25 changes: 12 additions & 13 deletions src/handlers/comment/action.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { getBotConfig, getBotContext, getLogger } from "../../bindings";
import { Payload } from "../../types";
import { getLogger } from "../../bindings";
import { BotContext, Payload } from "../../types";
import { ErrorDiff } from "../../utils/helpers";
import { IssueCommentCommands } from "./commands";
import { commentParser, userCommands } from "./handlers";
import { verifyFirstCheck } from "./handlers/first";

export const handleComment = async (): Promise<void> => {
const context = getBotContext();
const config = getBotConfig();
export const handleComment = async (context: BotContext): Promise<void> => {
const config = context.botConfig;
const logger = getLogger();
const payload = context.payload as Payload;

Expand All @@ -22,40 +21,40 @@ export const handleComment = async (): Promise<void> => {
const commentedCommands = commentParser(body);

if (commentedCommands.length === 0) {
await verifyFirstCheck();
await verifyFirstCheck(context);
return;
}

const allCommands = userCommands();
const allCommands = userCommands(context);
for (const command of commentedCommands) {
const userCommand = allCommands.find((i) => i.id == command);

if (userCommand) {
const { id, handler, callback, successComment, failureComment } = userCommand;
logger.info(`Running a comment handler: ${handler.name}`);

const { payload: _payload } = getBotContext();
const { payload: _payload } = context;
const issue = (_payload as Payload).issue;
if (!issue) continue;

const feature = config.command.find((e) => e.name === id.split("/")[1]);

if (!feature?.enabled && id !== IssueCommentCommands.HELP) {
logger.info(`Skipping '${id}' because it is disabled on this repo.`);
await callback(issue.number, `Skipping \`${id}\` because it is disabled on this repo.`, payload.action, payload.comment);
await callback(context, issue.number, `Skipping \`${id}\` because it is disabled on this repo.`, payload.action, payload.comment);
continue;
}

try {
const response = await handler(body);
const response = await handler(context, body);
const callbackComment = response ?? successComment ?? "";
if (callbackComment) await callback(issue.number, callbackComment, payload.action, payload.comment);
if (callbackComment) await callback(context, issue.number, callbackComment, payload.action, payload.comment);
} catch (err: unknown) {
// Use failureComment for failed command if it is available
if (failureComment) {
await callback(issue.number, failureComment, payload.action, payload.comment);
await callback(context, issue.number, failureComment, payload.action, payload.comment);
}
await callback(issue.number, ErrorDiff(err), payload.action, payload.comment);
await callback(context, issue.number, ErrorDiff(err), payload.action, payload.comment);
}
} else {
logger.info(`Skipping for a command: ${command}`);
Expand Down
7 changes: 3 additions & 4 deletions src/handlers/comment/handlers/allow.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { upsertAccessControl } from "../../../adapters/supabase";
import { getBotContext, getLogger } from "../../../bindings";
import { getLogger } from "../../../bindings";
import { getUserPermission } from "../../../helpers";
import { Payload } from "../../../types";
import { BotContext, Payload } from "../../../types";

export const setAccess = async (body: string) => {
const context = getBotContext();
export const setAccess = async (context: BotContext, body: string) => {
const logger = getLogger();
const payload = context.payload as Payload;
const sender = payload.sender.login;
Expand Down
Loading