From 4713afa718c1d0583cb4b8c9a869cddea0a056c0 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 20 Nov 2023 17:14:19 +0100 Subject: [PATCH] feat: logger inside context --- src/adapters/index.ts | 6 +- .../supabase/helpers/tables/access.ts | 4 +- src/adapters/supabase/helpers/tables/label.ts | 2 +- .../supabase/helpers/tables/locations.ts | 2 +- src/adapters/supabase/helpers/tables/logs.ts | 66 +++++++++-------- src/adapters/supabase/helpers/tables/user.ts | 2 +- .../supabase/helpers/tables/wallet.ts | 2 +- src/bindings/event.ts | 55 +++++++------- src/handlers/access/labels-access.ts | 11 ++- src/handlers/assign/action.ts | 27 ++++--- src/handlers/assign/auto.ts | 17 ++--- src/handlers/comment/action.ts | 16 ++--- src/handlers/comment/handlers/ask.ts | 12 ++-- .../assign/generate-assignment-comment.ts | 3 +- .../assign/get-time-labels-assigned.ts | 6 +- src/handlers/comment/handlers/assign/index.ts | 30 +++----- src/handlers/comment/handlers/authorize.ts | 15 ++-- src/handlers/comment/handlers/first.ts | 6 +- src/handlers/comment/handlers/help.ts | 13 ++-- .../handlers/issue/allCommentScoring.ts | 3 +- .../handlers/issue/assignee-scoring.ts | 5 +- .../handlers/issue/comment-scoring-rubric.ts | 5 +- .../issue/generate-permit-2-signature.ts | 20 +++--- .../handlers/issue/generate-permits.ts | 2 +- .../issue/get-collaborator-ids-for-repo.ts | 4 +- .../comment/handlers/issue/issue-closed.ts | 34 ++++----- .../handlers/issue/relevance-scoring.ts | 3 +- src/handlers/comment/handlers/labels.ts | 15 ++-- src/handlers/comment/handlers/multiplier.ts | 18 ++--- src/handlers/comment/handlers/payout.ts | 10 +-- src/handlers/comment/handlers/query.ts | 12 ++-- src/handlers/comment/handlers/unassign.ts | 18 +++-- src/handlers/comment/handlers/wallet.ts | 24 +++---- src/handlers/label/index.ts | 9 ++- src/handlers/pricing/action.ts | 4 +- src/handlers/pricing/pre.ts | 10 ++- src/handlers/pricing/pricing-label.ts | 31 ++++---- src/handlers/processors.ts | 2 +- .../pull-request/create-devpool-pr.ts | 12 ++-- src/handlers/push/check-modified-base-rate.ts | 10 ++- src/handlers/push/index.ts | 12 ++-- src/handlers/push/update-base-rate.ts | 13 ++-- src/handlers/shared/pricing.ts | 14 ++-- src/handlers/wildcard/unassign/unassign.ts | 31 +++----- src/helpers/file.ts | 7 +- src/helpers/gpt.ts | 14 ++-- src/helpers/issue.ts | 72 ++++++------------- src/helpers/label.ts | 13 ++-- src/helpers/parser.ts | 7 +- src/helpers/payout.ts | 5 +- src/types/context.ts | 8 ++- src/utils/check-github-rate-limit.ts | 2 +- src/utils/generate-configuration.ts | 6 +- 53 files changed, 314 insertions(+), 436 deletions(-) diff --git a/src/adapters/index.ts b/src/adapters/index.ts index d9d057c02..dafd5d807 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -10,7 +10,9 @@ import { Wallet } from "./supabase/helpers/tables/wallet"; import { Database } from "./supabase/types"; import { env } from "../bindings/env"; -const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY, { auth: { persistSession: false } }); +export const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY, { + auth: { persistSession: false }, +}); export function createAdapters() { return { @@ -21,7 +23,7 @@ export function createAdapters() { debit: new Settlement(supabaseClient), settlement: new Settlement(supabaseClient), label: new Label(supabaseClient), - logs: new Logs(supabaseClient, env.LOG_ENVIRONMENT, env.LOG_RETRY_LIMIT, env.LOG_LEVEL), + logs: new Logs(supabaseClient, null, env.LOG_ENVIRONMENT, env.LOG_RETRY_LIMIT, env.LOG_LEVEL), locations: new Locations(supabaseClient), super: new Super(supabaseClient), }, diff --git a/src/adapters/supabase/helpers/tables/access.ts b/src/adapters/supabase/helpers/tables/access.ts index 80e711536..73eb81025 100644 --- a/src/adapters/supabase/helpers/tables/access.ts +++ b/src/adapters/supabase/helpers/tables/access.ts @@ -26,7 +26,7 @@ export class Access extends Super { const { data, error } = await this.supabase.from("access").select("*, users(*)").filter("id", "eq", id); if (error) { - this.runtime.logger.error(null, error.message, error); + this.runtime.logger.error(error.message, error); throw new Error(error.message); } return data; @@ -35,7 +35,7 @@ export class Access extends Super { public async getAccess(id: number): Promise { const userWithAccess = await this._getUserWithAccess(id); if (userWithAccess[0]?.access === undefined) { - this.runtime.logger.debug(null, "Access is undefined"); + this.runtime.logger.debug("Access is undefined"); return null; } if (userWithAccess[0]?.access === null) throw new Error("Access is null"); diff --git a/src/adapters/supabase/helpers/tables/label.ts b/src/adapters/supabase/helpers/tables/label.ts index 17d713356..da1236213 100644 --- a/src/adapters/supabase/helpers/tables/label.ts +++ b/src/adapters/supabase/helpers/tables/label.ts @@ -74,7 +74,7 @@ export class Label extends Super { if (locationError) throw new Error(locationError.message); if (!locationData) { - runtime.logger.warn(null, "Repository location ID not found in database."); + runtime.logger.warn("Repository location ID not found in database."); return null; } diff --git a/src/adapters/supabase/helpers/tables/locations.ts b/src/adapters/supabase/helpers/tables/locations.ts index 94c093675..72438aeab 100644 --- a/src/adapters/supabase/helpers/tables/locations.ts +++ b/src/adapters/supabase/helpers/tables/locations.ts @@ -27,7 +27,7 @@ export class Locations extends Super { .select("id") .eq("repository_id", repositoryId); - if (error) throw this.runtime.logger.error(null, "Error getting location data", new Error(error.message)); + if (error) throw this.runtime.logger.error("Error getting location data", new Error(error.message)); return locationData; } diff --git a/src/adapters/supabase/helpers/tables/logs.ts b/src/adapters/supabase/helpers/tables/logs.ts index 997997247..d2fc1241a 100644 --- a/src/adapters/supabase/helpers/tables/logs.ts +++ b/src/adapters/supabase/helpers/tables/logs.ts @@ -10,12 +10,10 @@ import Runtime from "../../../../bindings/bot-runtime"; import { LogLevel } from "../../../../types/logs"; import { Database } from "../../types"; import { prettyLogs } from "../pretty-logs"; -import { Super } from "./super"; type LogFunction = (message: string, metadata?: any) => void; type LogInsert = Database["public"]["Tables"]["logs"]["Insert"]; type _LogParams = { - context: ProbotContext | null; level: LogLevel; consoleLog: LogFunction; logMessage: string; @@ -40,7 +38,10 @@ type PublicMethods = Exclude, "constructor" | keyof export type LogMessage = { raw: string; diff: string; level: LogLevel; type: PublicMethods }; -export class Logs extends Super { +export class Logs { + private supabase: SupabaseClient; + private context: ProbotContext | null = null; + private maxLevel = -1; private environment = "development"; private queue: LogInsert[] = []; // Your log queue @@ -49,7 +50,7 @@ export class Logs extends Super { private throttleCount = 0; private retryLimit = 0; // Retries disabled by default - private _log({ context, level, consoleLog, logMessage, metadata, postComment, type }: _LogParams): LogReturn | null { + private _log({ level, consoleLog, logMessage, metadata, postComment, type }: _LogParams): LogReturn | null { if (this._getNumericLevel(level) > this.maxLevel) return null; // filter out more verbose logs according to maxLevel set in config // needs to generate three versions of the information. @@ -60,13 +61,10 @@ export class Logs extends Super { consoleLog(logMessage, metadata || undefined); - if (context && postComment) { + if (this.context && postComment) { const colorizedCommentMessage = this._diffColorCommentMessage(type, logMessage); const commentMetaData = metadata ? Logs._commentMetaData(metadata, level) : null; - this._postComment( - context, - metadata ? [colorizedCommentMessage, commentMetaData].join("\n") : colorizedCommentMessage - ); + this._postComment(metadata ? [colorizedCommentMessage, commentMetaData].join("\n") : colorizedCommentMessage); } const toSupabase = { log: logMessage, level, metadata } as LogInsert; @@ -112,10 +110,10 @@ export class Logs extends Super { return metadata; } - public ok(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + + public ok(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.VERBOSE, consoleLog: prettyLogs.ok, logMessage: log, @@ -125,10 +123,9 @@ export class Logs extends Super { }); } - public info(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public info(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.INFO, consoleLog: prettyLogs.info, logMessage: log, @@ -138,10 +135,9 @@ export class Logs extends Super { }); } - public warn(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public warn(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.WARN, consoleLog: prettyLogs.warn, logMessage: log, @@ -151,10 +147,9 @@ export class Logs extends Super { }); } - public debug(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public debug(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.DEBUG, consoleLog: prettyLogs.debug, logMessage: log, @@ -164,7 +159,7 @@ export class Logs extends Super { }); } - public error(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public error(log: string, metadata?: any, postComment?: boolean): LogReturn | null { if (!metadata) { metadata = Logs.convertErrorsIntoObjects(new Error(log)); const stack = metadata.stack as string[]; @@ -180,7 +175,6 @@ export class Logs extends Super { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.ERROR, consoleLog: prettyLogs.error, logMessage: log, @@ -190,10 +184,9 @@ export class Logs extends Super { }); } - http(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + http(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.HTTP, consoleLog: prettyLogs.http, logMessage: log, @@ -203,10 +196,9 @@ export class Logs extends Super { }); } - verbose(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + verbose(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.VERBOSE, consoleLog: prettyLogs.verbose, logMessage: log, @@ -216,10 +208,9 @@ export class Logs extends Super { }); } - silly(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { + silly(log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ - context, level: LogLevel.SILLY, consoleLog: prettyLogs.silly, logMessage: log, @@ -229,9 +220,15 @@ export class Logs extends Super { }); } - constructor(supabase: SupabaseClient, environment: string, retryLimit: number, logLevel: LogLevel) { - super(supabase); - + constructor( + supabase: SupabaseClient, + context: ProbotContext | null, + environment: string, + retryLimit: number, + logLevel: LogLevel + ) { + this.supabase = supabase; + this.context = context; this.environment = environment; this.retryLimit = retryLimit; this.maxLevel = this._getNumericLevel(logLevel); @@ -311,7 +308,7 @@ export class Logs extends Super { } static _commentMetaData(metadata: any, level: LogLevel) { - Runtime.getState().logger.debug(null, "the main place that metadata is being serialized as an html comment"); + Runtime.getState().logger.debug("the main place that metadata is being serialized as an html comment"); const prettySerialized = JSON.stringify(metadata, null, 2); // first check if metadata is an error, then post it as a json comment // otherwise post it as an html comment @@ -366,13 +363,14 @@ export class Logs extends Super { return [diffHeader, message, diffFooter].join("\n"); } - private _postComment(context: ProbotContext, message: string) { + private _postComment(message: string) { // post on issue - context.octokit.issues + if (!this.context) return; + this.context.octokit.issues .createComment({ - owner: context.issue().owner, - repo: context.issue().repo, - issue_number: context.issue().issue_number, + owner: this.context.issue().owner, + repo: this.context.issue().repo, + issue_number: this.context.issue().issue_number, body: message, }) // .then((x) => console.trace(x)) diff --git a/src/adapters/supabase/helpers/tables/user.ts b/src/adapters/supabase/helpers/tables/user.ts index 7829ae420..7e7b02a32 100644 --- a/src/adapters/supabase/helpers/tables/user.ts +++ b/src/adapters/supabase/helpers/tables/user.ts @@ -38,7 +38,7 @@ export class User extends Super { .eq("user_id", userId) .order("id", { ascending: false }) // get the latest one .maybeSingle(); - if (accessError) throw this.runtime.logger.error(null, "Error getting access data", accessError); + if (accessError) throw this.runtime.logger.error("Error getting access data", accessError); return accessData; } } diff --git a/src/adapters/supabase/helpers/tables/wallet.ts b/src/adapters/supabase/helpers/tables/wallet.ts index 2e87b5353..dc055476e 100644 --- a/src/adapters/supabase/helpers/tables/wallet.ts +++ b/src/adapters/supabase/helpers/tables/wallet.ts @@ -183,7 +183,7 @@ export class Wallet extends Super { private async _enrichLocationMetaData(walletData: WalletRow, locationMetaData: LocationMetaData) { const runtime = Runtime.getState(); const logger = runtime.logger; - logger.ok(null, "Enriching wallet location metadata", locationMetaData); + logger.ok("Enriching wallet location metadata", locationMetaData); return await this.supabase.from("locations").update(locationMetaData).eq("id", walletData.location_id); } } diff --git a/src/bindings/event.ts b/src/bindings/event.ts index e09c6d186..fb10351e5 100644 --- a/src/bindings/event.ts +++ b/src/bindings/event.ts @@ -1,8 +1,8 @@ import OpenAI from "openai"; import { Context as ProbotContext } from "probot"; -import { createAdapters } from "../adapters"; +import { createAdapters, supabaseClient } from "../adapters"; import { LogReturn } from "../adapters/supabase"; -import { LogMessage } from "../adapters/supabase/helpers/tables/logs"; +import { LogMessage, Logs } from "../adapters/supabase/helpers/tables/logs"; import { processors, wildcardProcessors } from "../handlers/processors"; import { validateConfigChange } from "../handlers/push"; import structuredMetadata from "../handlers/shared/structured-metadata"; @@ -20,6 +20,7 @@ import { GitHubEvent, Payload, PayloadSchema } from "../types/payload"; import { ajv } from "../utils/ajv"; import { generateConfiguration } from "../utils/generate-configuration"; import Runtime from "./bot-runtime"; +import { env } from "./env"; const allowedEvents = Object.values(GitHubEvent) as string[]; @@ -40,12 +41,13 @@ runtime.logger = runtime.adapters.supabase.logs; export async function bindEvents(eventContext: ProbotContext) { const payload = eventContext.payload as Payload; const eventName = payload?.action ? `${eventContext.name}.${payload?.action}` : eventContext.name; // some events wont have actions as this grows + const logger = new Logs(supabaseClient, eventContext, env.LOG_ENVIRONMENT, env.LOG_RETRY_LIMIT, env.LOG_LEVEL); - runtime.logger.info(eventContext, "Event received", { id: eventContext.id, name: eventName }); + logger.info("Event received", { id: eventContext.id, name: eventName }); if (!allowedEvents.includes(eventName)) { // just check if its on the watch list - return runtime.logger.info(eventContext, `Skipping the event. reason: not configured`); + return logger.info(`Skipping the event. reason: not configured`); } // Skip validation for installation event and push @@ -53,13 +55,13 @@ export async function bindEvents(eventContext: ProbotContext) { // Validate payload const valid = validatePayload(payload); if (!valid && validatePayload.errors) { - return runtime.logger.error(eventContext, "Payload schema validation failed!", validatePayload.errors); + return logger.error("Payload schema validation failed!", validatePayload.errors); } // Check if we should skip the event const should = shouldSkip(eventContext); if (should.stop) { - return runtime.logger.info(eventContext, "Skipping the event.", { reason: should.reason }); + return logger.info("Skipping the event.", { reason: should.reason }); } } @@ -77,13 +79,16 @@ export async function bindEvents(eventContext: ProbotContext) { event: eventContext, config: botConfig, openAi: botConfig.keys.openAi ? new OpenAI({ apiKey: botConfig.keys.openAi }) : null, + logger: logger, + payload: payload, + octokit: eventContext.octokit, }; if (!context.config.keys.evmPrivateEncrypted) { - runtime.logger.warn(eventContext, "No EVM private key found"); + context.logger.warn("No EVM private key found"); } - if (!runtime.logger) { + if (!context.logger) { throw new Error("Failed to create logger"); } @@ -91,7 +96,7 @@ export async function bindEvents(eventContext: ProbotContext) { const handlers = processors[eventName]; if (!handlers) { - return runtime.logger.warn(eventContext, "No handler configured for event:", { eventName }); + return context.logger.warn("No handler configured for event:", { eventName }); } const { pre, action, post } = handlers; @@ -105,8 +110,7 @@ export async function bindEvents(eventContext: ProbotContext) { // List all the function names of handlerType.actions const functionNames = handlerWithType.actions.map((action) => action?.name); - runtime.logger.info( - eventContext, + context.logger.info( `Running "${handlerWithType.type}" \ for event: "${eventName}". \ handlers: "${functionNames.join(", ")}"` @@ -117,11 +121,11 @@ export async function bindEvents(eventContext: ProbotContext) { // Skip wildcard handlers for installation event and push event if (eventName == GitHubEvent.INSTALLATION_ADDED_EVENT || eventName == GitHubEvent.PUSH_EVENT) { - return runtime.logger.info(eventContext, "Skipping wildcard handlers for event:", eventName); + return context.logger.info("Skipping wildcard handlers for event:", eventName); } else { // Run wildcard handlers const functionNames = wildcardProcessors.map((action) => action?.name); - runtime.logger.info(eventContext, `Running wildcard handlers: "${functionNames.join(", ")}"`); + context.logger.info(`Running wildcard handlers: "${functionNames.join(", ")}"`); const wildCardHandlerType: WildCardHandlerWithType = { type: "wildcard", actions: wildcardProcessors }; await logAnyReturnFromHandlers(context, wildCardHandlerType); } @@ -138,8 +142,7 @@ async function logAnyReturnFromHandlers(context: Context, handlerType: AllHandle // only log main handler results await renderMainActionOutput(context, response, action); } else { - const runtime = Runtime.getState(); - runtime.logger.ok(context.event, "Completed", { action: action.name, type: handlerType.type }); + context.logger.ok("Completed", { action: action.name, type: handlerType.type }); } } catch (report: unknown) { await renderCatchAllWithContext(report); @@ -152,8 +155,7 @@ async function renderMainActionOutput( response: void | HandlerReturnValuesNoVoid, action: AllHandlers ) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; + const { payload, logger } = context; const issueNumber = payload.issue?.number; if (!issueNumber) { throw new Error("No issue number found"); @@ -174,10 +176,9 @@ async function renderMainActionOutput( } else if (typeof response == "string") { await addCommentToIssue(context, response, issueNumber); } else if (response === null) { - runtime.logger.debug(context.event, "null response", { action: action.name }); + logger.debug("null response", { action: action.name }); } else { - runtime.logger.error( - context.event, + logger.error( "No response from action. Ensure return of string, null, or LogReturn object", { action: action.name }, true @@ -187,11 +188,10 @@ async function renderMainActionOutput( function createRenderCatchAll(context: Context, handlerType: AllHandlersWithTypes, activeHandler: AllHandlers) { return async function renderCatchAll(report: LogReturn | Error | unknown) { - const runtime = Runtime.getState(); const payload = context.event.payload as Payload; const issue = payload.issue; if (!issue) { - return runtime.logger.error(context.event, "Issue is null. Skipping", { issue }); + return context.logger.error("Issue is null. Skipping", { issue }); } if (report instanceof LogReturn) { @@ -199,10 +199,7 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType const { logMessage } = report; if (report.metadata) { - runtime.logger.debug( - context.event, - "this is the second place that metadata is being serialized as an html comment" - ); + context.logger.debug("this is the second place that metadata is being serialized as an html comment"); let metadataSerialized; const prettySerialized = JSON.stringify(report.metadata, null, 2); // first check if metadata is an error, then post it as a json comment @@ -225,8 +222,7 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType stack: report.stack, }; - return runtime.logger.error( - context.event, + return context.logger.error( "action has an uncaught error", { logReturn: report, handlerType, activeHandler: activeHandler.name, error }, true @@ -242,8 +238,7 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType // report as SupabaseError - return runtime.logger.error( - context.event, + return context.logger.error( "action returned an unexpected value", { logReturn: report, handlerType, activeHandler: activeHandler.name }, true diff --git a/src/handlers/access/labels-access.ts b/src/handlers/access/labels-access.ts index 838e3868b..28b17d96d 100644 --- a/src/handlers/access/labels-access.ts +++ b/src/handlers/access/labels-access.ts @@ -1,16 +1,15 @@ import Runtime from "../../bindings/bot-runtime"; import { addCommentToIssue, isUserAdminOrBillingManager, removeLabel, addLabelToIssue } from "../../helpers"; -import { Context, Payload, UserType } from "../../types"; +import { Context, UserType } from "../../types"; export async function labelAccessPermissionsCheck(context: Context) { const runtime = Runtime.getState(); - const logger = runtime.logger; + const { logger, payload } = context; const { features: { publicAccessControl }, } = context.config; if (!publicAccessControl.setLabel) return true; - const payload = context.event.payload as Payload; if (!payload.issue) return; if (!payload.label?.name) return; if (payload.sender.type === UserType.Bot) return true; @@ -28,14 +27,14 @@ export async function labelAccessPermissionsCheck(context: Context) { const labelType = match[0].toLowerCase(); if (sufficientPrivileges) { - logger.info(context.event, "Admin and billing managers have full control over all labels", { + logger.info("Admin and billing managers have full control over all labels", { repo: repo.full_name, user: sender, labelType, }); return true; } else { - logger.info(context.event, "Checking access for labels", { repo: repo.full_name, user: sender, labelType }); + logger.info("Checking access for labels", { repo: repo.full_name, user: sender, labelType }); // check permission const { access, user } = runtime.adapters.supabase; const userId = await user.getUserId(context.event, sender); @@ -58,7 +57,7 @@ export async function labelAccessPermissionsCheck(context: Context) { `@${sender}, You are not allowed to ${eventName} ${labelName}`, payload.issue.number ); - logger.info(context.event, "No access to edit label", { sender, label: labelName }); + logger.info("No access to edit label", { sender, label: labelName }); return false; } } diff --git a/src/handlers/assign/action.ts b/src/handlers/assign/action.ts index 059b4841d..e5adc5dc5 100644 --- a/src/handlers/assign/action.ts +++ b/src/handlers/assign/action.ts @@ -1,22 +1,20 @@ -import Runtime from "../../bindings/bot-runtime"; import { calculateDurations, calculateLabelValue, closePullRequest } from "../../helpers"; import { getLinkedPullRequests } from "../../helpers/parser"; import { Context, Label, Payload } from "../../types"; export async function startCommandHandler(context: Context) { - const runtime = Runtime.getState(); const config = context.config; - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; if (!payload.issue) { - return logger.error(context.event, "Issue is not defined"); + return logger.error("Issue is not defined"); } const assignees = payload.issue.assignees; // If no valid assignees exist, log a debug message and return if (assignees.length === 0) { - return logger.warn(context.event, "No assignees"); + return logger.warn("No assignees"); } // Flatten assignees into a string @@ -27,7 +25,7 @@ export async function startCommandHandler(context: Context) { // If no labels exist, log a debug message and return if (!labels) { - return logger.warn(context.event, `No labels to calculate timeline`); + return logger.warn(`No labels to calculate timeline`); } // Filter out labels that match the time labels defined in the config @@ -38,7 +36,7 @@ export async function startCommandHandler(context: Context) { ); if (timeLabelsAssigned.length == 0) { - return logger.debug(context.event, "No labels to calculate timeline"); + return logger.debug("No labels to calculate timeline"); } // Sort labels by weight and select the one with the smallest weight @@ -68,19 +66,18 @@ export async function startCommandHandler(context: Context) { // Format the commit message const commitMessage = `${flattenedAssignees} the deadline is at ${endDate.toISOString()}`; - logger.debug(context.event, "Creating an issue comment", { commitMessage }); + logger.debug("Creating an issue comment", { commitMessage }); // Add the commit message as a comment to the issue // await addCommentToIssue(commitMessage, payload.issue?.number); - return logger.info(context.event, commitMessage); + return logger.info(commitMessage); } export async function closePullRequestForAnIssue(context: Context) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; if (!payload.issue?.number) { - throw logger.error(context.event, "Issue is not defined"); + throw logger.error("Issue is not defined"); } const linkedPullRequests = await getLinkedPullRequests(context, { @@ -90,15 +87,15 @@ export async function closePullRequestForAnIssue(context: Context) { }); if (!linkedPullRequests.length) { - return logger.info(context.event, `No linked pull requests to close`); + return logger.info(`No linked pull requests to close`); } - logger.info(context.event, `Opened prs`, linkedPullRequests); + logger.info(`Opened prs`, linkedPullRequests); let comment = `These linked pull requests are closed: `; for (let i = 0; i < linkedPullRequests.length; i++) { await closePullRequest(context, linkedPullRequests[i].number); comment += ` #${linkedPullRequests[i].number} `; } - return logger.info(context.event, comment); + return logger.info(comment); // await addCommentToIssue(comment, payload.issue.number); } diff --git a/src/handlers/assign/auto.ts b/src/handlers/assign/auto.ts index 3b8ed8147..828546d2c 100644 --- a/src/handlers/assign/auto.ts +++ b/src/handlers/assign/auto.ts @@ -1,19 +1,16 @@ -import Runtime from "../../bindings/bot-runtime"; import { addAssignees, getAllPullRequests, getIssueByNumber, getPullByNumber } from "../../helpers"; import { getLinkedIssues } from "../../helpers/parser"; -import { Context, Payload } from "../../types"; +import { Context } from "../../types"; // Check for pull requests linked to their respective issues but not assigned to them export async function checkPullRequests(context: Context) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const { logger, payload } = context; const pulls = await getAllPullRequests(context); if (pulls.length === 0) { - return logger.debug(context.event, `No pull requests found at this time`); + return logger.debug(`No pull requests found at this time`); } - const payload = context.event.payload as Payload; // Loop through the pull requests and assign them to their respective issues if needed for (const pull of pulls) { const linkedIssue = await getLinkedIssues({ @@ -31,7 +28,7 @@ export async function checkPullRequests(context: Context) { // Newly created PULL (draft or direct) pull does have same `created_at` and `updated_at`. if (connectedPull?.created_at !== connectedPull?.updated_at) { - logger.debug(context.event, "It's an updated Pull Request, reverting"); + logger.debug("It's an updated Pull Request, reverting"); continue; } @@ -45,19 +42,19 @@ export async function checkPullRequests(context: Context) { // if issue is already assigned, continue if (issue.assignees.length > 0) { - logger.debug(context.event, `Issue already assigned, ignoring...`); + logger.debug(`Issue already assigned, ignoring...`); continue; } const assignedUsernames = issue.assignees.map((assignee) => assignee.login); if (!assignedUsernames.includes(opener)) { await addAssignees(context, +linkedIssueNumber, [opener]); - logger.debug(context.event, "Assigned pull request opener to issue", { + logger.debug("Assigned pull request opener to issue", { pullRequest: pull.number, issue: linkedIssueNumber, opener, }); } } - return logger.debug(context.event, `Checking pull requests done!`); + return logger.debug(`Checking pull requests done!`); } diff --git a/src/handlers/comment/action.ts b/src/handlers/comment/action.ts index c1fa3729a..a4d962381 100644 --- a/src/handlers/comment/action.ts +++ b/src/handlers/comment/action.ts @@ -1,12 +1,10 @@ -import Runtime from "../../bindings/bot-runtime"; import { Comment, Payload, Context } from "../../types"; import { commentParser, userCommands } from "./handlers"; import { verifyFirstCommentInRepository } from "./handlers/first"; export async function commentCreatedOrEdited(context: Context) { - const runtime = Runtime.getState(), - config = context.config, - logger = runtime.logger, + const config = context.config, + logger = context.logger, payload = context.event.payload as Payload; const comment = payload.comment as Comment; @@ -15,11 +13,11 @@ export async function commentCreatedOrEdited(context: Context) { const commentedCommand = commentParser(body); if (!comment) { - logger.info(context.event, `Comment is null. Skipping`); + logger.info(`Comment is null. Skipping`); } const issue = payload.issue; if (!issue) { - throw logger.error(context.event, "Issue is null. Skipping", { issue }); + throw logger.error("Issue is null. Skipping", { issue }); } if (commentedCommand) { @@ -31,18 +29,18 @@ export async function commentCreatedOrEdited(context: Context) { if (userCommand) { const { id, handler } = userCommand; - logger.info(context.event, "Running a comment handler", { id, handler: handler.name }); + logger.info("Running a comment handler", { id, handler: handler.name }); const disabled = config.disabledCommands.some((command) => command === id.replace("/", "")); if (disabled && id !== "/help") { - return logger.warn(context.event, "Skipping because it is disabled on this repo.", { id }); + return logger.warn("Skipping because it is disabled on this repo.", { id }); } return await handler(context, body); } else { const sanitizedBody = body.replace(//g, ""); - return logger.verbose(context.event, "Comment event received without a recognized user command.", { + return logger.verbose("Comment event received without a recognized user command.", { sanitizedBody, }); } diff --git a/src/handlers/comment/handlers/ask.ts b/src/handlers/comment/handlers/ask.ts index bb5f28f1b..877909706 100644 --- a/src/handlers/comment/handlers/ask.ts +++ b/src/handlers/comment/handlers/ask.ts @@ -1,4 +1,3 @@ -import Runtime from "../../../bindings/bot-runtime"; import { Context, Payload, StreamlinedComment, UserType } from "../../../types"; import { getAllIssueComments, getAllLinkedIssuesAndPullsInBody } from "../../../helpers"; import { CreateChatCompletionRequestMessage } from "openai/resources/chat"; @@ -6,8 +5,7 @@ import { askGPT, decideContextGPT, sysMsg } from "../../../helpers/gpt"; export async function ask(context: Context, body: string) { // The question to ask - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const sender = payload.sender.login; @@ -38,7 +36,7 @@ export async function ask(context: Context, body: string) { const commentsRaw = await getAllIssueComments(context, issue.number, "raw"); if (!comments) { - throw logger.error(context.event, `Error getting issue comments`); + throw logger.error(`Error getting issue comments`); } // add the first comment of the issue/pull request @@ -61,7 +59,7 @@ export async function ask(context: Context, body: string) { const links = await getAllLinkedIssuesAndPullsInBody(context, issue.number); if (typeof links === "string") { - logger.info(context.event, "Error getting linked issues or prs: ", links); + logger.info("Error getting linked issues or prs: ", links); } else { linkedIssueStreamlined = links.linkedIssues; linkedPRStreamlined = links.linkedPrs; @@ -117,9 +115,9 @@ export async function ask(context: Context, body: string) { } else if (gptResponse.answer) { return gptResponse.answer; } else { - throw logger.error(context.event, "Error getting response from OpenAI"); + throw logger.error("Error getting response from OpenAI"); } } else { - return logger.warn(context.event, "Invalid syntax for ask. usage: '/ask What is pi?'"); + return logger.warn("Invalid syntax for ask. usage: '/ask What is pi?'"); } } diff --git a/src/handlers/comment/handlers/assign/generate-assignment-comment.ts b/src/handlers/comment/handlers/assign/generate-assignment-comment.ts index 3fc172c67..aa3e4751e 100644 --- a/src/handlers/comment/handlers/assign/generate-assignment-comment.ts +++ b/src/handlers/comment/handlers/assign/generate-assignment-comment.ts @@ -23,8 +23,7 @@ export async function generateAssignmentComment(context: Context, payload: Paylo const issueCreationTime = payload.issue?.created_at; if (!issueCreationTime) { - const logger = Runtime.getState().logger; - throw logger.error(context.event, "Issue creation time is not defined"); + throw context.logger.error("Issue creation time is not defined"); } return { diff --git a/src/handlers/comment/handlers/assign/get-time-labels-assigned.ts b/src/handlers/comment/handlers/assign/get-time-labels-assigned.ts index 450f24bd8..fde0dd8eb 100644 --- a/src/handlers/comment/handlers/assign/get-time-labels-assigned.ts +++ b/src/handlers/comment/handlers/assign/get-time-labels-assigned.ts @@ -1,12 +1,10 @@ -import Runtime from "../../../../bindings/bot-runtime"; import { BotConfig, Context, Label, Payload } from "../../../../types"; export function getTimeLabelsAssigned(context: Context, payload: Payload, config: BotConfig) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const labels = payload.issue?.labels; if (!labels?.length) { - logger.warn(context.event, "Skipping '/start' since no labels are set to calculate the timeline", { labels }); + logger.warn("Skipping '/start' since no labels are set to calculate the timeline", { labels }); return; } const timeLabelsDefined = config.labels.time; diff --git a/src/handlers/comment/handlers/assign/index.ts b/src/handlers/comment/handlers/assign/index.ts index 28828d493..d8bfa6673 100644 --- a/src/handlers/comment/handlers/assign/index.ts +++ b/src/handlers/comment/handlers/assign/index.ts @@ -1,4 +1,3 @@ -import Runtime from "../../../../bindings/bot-runtime"; import { addAssignees, calculateDurations, @@ -15,8 +14,7 @@ import { getMultiplierInfoToDisplay } from "./get-multiplier-info-to-display"; import { getTimeLabelsAssigned } from "./get-time-labels-assigned"; export async function assign(context: Context, body: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const config = context.config; const payload = context.event.payload as Payload; const issue = payload.issue; @@ -28,48 +26,46 @@ export async function assign(context: Context, body: string) { const startDisabled = disabledCommands.some((command) => command === "start"); - logger.info(context.event, "Received '/start' command", { sender: payload.sender.login, body }); + logger.info("Received '/start' command", { sender: payload.sender.login, body }); if (!issue) { - throw logger.warn(context.event, `Skipping '/start' because of no issue instance`); + throw logger.warn(`Skipping '/start' because of no issue instance`); } if (startDisabled) { - throw logger.warn(context.event, "The `/assign` command is disabled for this repository."); + throw logger.warn("The `/assign` command is disabled for this repository."); } if (issue.body && isParentIssue(issue.body)) { throw logger.warn( - context.event, "Please select a child issue from the specification checklist to work on. The '/start' command is disabled on parent issues." ); } const openedPullRequests = await getAvailableOpenedPullRequests(context, payload.sender.login); logger.info( - context.event, `Opened Pull Requests with approved reviews or with no reviews but over 24 hours have passed: ${JSON.stringify( openedPullRequests )}` ); const assignedIssues = await getAssignedIssues(context, payload.sender.login); - logger.info(context.event, "Max issue allowed is", maxConcurrentTasks); + logger.info("Max issue allowed is", maxConcurrentTasks); // check for max and enforce max if (assignedIssues.length - openedPullRequests.length >= maxConcurrentTasks) { - throw logger.warn(context.event, "Too many assigned issues, you have reached your max limit", { + throw logger.warn("Too many assigned issues, you have reached your max limit", { maxConcurrentTasks, }); } if (issue.state == IssueType.CLOSED) { - throw logger.warn(context.event, "Skipping '/start' since the issue is closed"); + throw logger.warn("Skipping '/start' since the issue is closed"); } const assignees: User[] = (payload.issue?.assignees ?? []).filter(Boolean) as User[]; if (assignees.length !== 0) { - throw logger.warn(context.event, "Skipping '/start' since the issue is already assigned"); + throw logger.warn("Skipping '/start' since the issue is already assigned"); } // ==== preamble checks completed ==== // @@ -79,11 +75,7 @@ export async function assign(context: Context, body: string) { let duration: number | null = null; if (!priceLabel) { - throw logger.warn( - context.event, - "No price label is set, so this is not ready to be self assigned yet.", - priceLabel - ); + throw logger.warn("No price label is set, so this is not ready to be self assigned yet.", priceLabel); } else { const timeLabelsAssigned = getTimeLabelsAssigned(context, payload, config); if (timeLabelsAssigned) { @@ -95,14 +87,14 @@ export async function assign(context: Context, body: string) { const metadata = structuredMetadata.create("Assignment", { duration, priceLabel }); if (!assignees.map((i) => i.login).includes(payload.sender.login)) { - logger.info(context.event, "Adding the assignee", { assignee: payload.sender.login }); + logger.info("Adding the assignee", { assignee: payload.sender.login }); await addAssignees(context, issue.number, [payload.sender.login]); } const isTaskStale = checkTaskStale(taskStaleTimeoutDuration, issue); // double check whether the assign message has been already posted or not - logger.info(context.event, "Creating an issue comment", { comment }); + logger.info("Creating an issue comment", { comment }); const { multiplierAmount: multiplierAmount, diff --git a/src/handlers/comment/handlers/authorize.ts b/src/handlers/comment/handlers/authorize.ts index 3e38cb153..a1c6b2d60 100644 --- a/src/handlers/comment/handlers/authorize.ts +++ b/src/handlers/comment/handlers/authorize.ts @@ -6,15 +6,15 @@ import { taskPaymentMetaData } from "../../wildcard"; export async function authorizeLabelChanges(context: Context) { const runtime = Runtime.getState(); const { label } = runtime.adapters.supabase; - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const sender = payload.sender.login; - logger.info(context.event, "Running '/authorize' command handler", { sender }); + logger.info("Running '/authorize' command handler", { sender }); const { issue, repository } = payload; if (!issue) { - return logger.info(context.event, `Skipping '/authorize' because of no issue instance`); + return logger.info(`Skipping '/authorize' because of no issue instance`); } // check if sender is admin @@ -23,8 +23,7 @@ export async function authorizeLabelChanges(context: Context) { // if sender is not admin, return if (sufficientPrivileges) { - throw runtime.logger.error( - context.event, + throw logger.error( "User is not an admin/billing_manager and do not have the required permissions to access this function.", { sender } ); @@ -33,7 +32,7 @@ export async function authorizeLabelChanges(context: Context) { const task = taskPaymentMetaData(context, issue); if (!task.priceLabel || !task.priorityLabel || !task.timeLabel) { - throw runtime.logger.error(context.event, "Missing required labels", { issueDetailed: task }); + throw logger.error("Missing required labels", { issueDetailed: task }); } // get current repository node id from payload and pass it to getLabelChanges function to get label changes @@ -43,9 +42,9 @@ export async function authorizeLabelChanges(context: Context) { // Approve label changes labelChanges.forEach(async (labelChange) => { await label.approveLabelChange(labelChange.id); - return logger.info(context.event, "Approved label change", { labelChange }); + return logger.info("Approved label change", { labelChange }); }); } - return runtime.logger.ok(context.event, "Label change has been approved, permit can now be generated"); + return logger.ok("Label change has been approved, permit can now be generated"); } diff --git a/src/handlers/comment/handlers/first.ts b/src/handlers/comment/handlers/first.ts index 7ac5b0e32..a1aeb9154 100644 --- a/src/handlers/comment/handlers/first.ts +++ b/src/handlers/comment/handlers/first.ts @@ -1,12 +1,10 @@ -import Runtime from "../../../bindings/bot-runtime"; import { Context, Payload } from "../../../types"; import { generateHelpMenu } from "./help"; export async function verifyFirstCommentInRepository(context: Context) { - const runtime = Runtime.getState(); const payload = context.event.payload as Payload; if (!payload.issue) { - throw runtime.logger.error(context.event, "Issue is null. Skipping", { issue: payload.issue }, true); + throw context.logger.error("Issue is null. Skipping", { issue: payload.issue }, true); } const { features: { @@ -36,5 +34,5 @@ export async function verifyFirstCommentInRepository(context: Context) { // await upsertCommentToIssue(payload.issue.number, msg, payload.action, payload.comment); } } - return runtime.logger.info(context.event, `Skipping first comment`); + return context.logger.info(`Skipping first comment`); } diff --git a/src/handlers/comment/handlers/help.ts b/src/handlers/comment/handlers/help.ts index 90b6783ac..8a7af964e 100644 --- a/src/handlers/comment/handlers/help.ts +++ b/src/handlers/comment/handlers/help.ts @@ -1,18 +1,15 @@ import { userCommands } from "."; -import Runtime from "../../../bindings/bot-runtime"; -import { Context, Payload } from "../../../types"; +import { Context } from "../../../types"; export async function listAvailableCommands(context: Context, body: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; if (body != "/help") { - return logger.info(context.event, "Skipping to list available commands.", { body }); + return logger.info("Skipping to list available commands.", { body }); } - const payload = context.event.payload as Payload; - const issue = payload.issue; + const issue = context.payload.issue; if (!issue) { - return logger.info(context.event, "Skipping /help, reason: not issue"); + return context.logger.info("Skipping /help, reason: not issue"); } return generateHelpMenu(context); diff --git a/src/handlers/comment/handlers/issue/allCommentScoring.ts b/src/handlers/comment/handlers/issue/allCommentScoring.ts index 655487cef..6f5e588f0 100644 --- a/src/handlers/comment/handlers/issue/allCommentScoring.ts +++ b/src/handlers/comment/handlers/issue/allCommentScoring.ts @@ -1,4 +1,3 @@ -import Runtime from "../../../../bindings/bot-runtime"; import { Comment } from "../../../../types/payload"; import { commentScoringByContributionClass } from "./comment-scoring-by-contribution-style"; import { CommentScoring } from "./comment-scoring-rubric"; @@ -26,7 +25,7 @@ export async function allCommentScoring({ const selection = usersByClass[contributionStyle as keyof typeof usersByClass]; if (!selection) { - Runtime.getState().logger.verbose(context.event, `No ${String(contributionStyle)} found`); + context.logger.verbose(`No ${String(contributionStyle)} found`); return []; } diff --git a/src/handlers/comment/handlers/issue/assignee-scoring.ts b/src/handlers/comment/handlers/issue/assignee-scoring.ts index f0bdf721e..da9f79b02 100644 --- a/src/handlers/comment/handlers/issue/assignee-scoring.ts +++ b/src/handlers/comment/handlers/issue/assignee-scoring.ts @@ -1,5 +1,4 @@ import Decimal from "decimal.js"; -import Runtime from "../../../../bindings/bot-runtime"; import { Issue, User } from "../../../../types/payload"; import { ContributorView } from "./contribution-style-types"; import { UserScoreDetails } from "./issue-shared-types"; @@ -19,7 +18,7 @@ export async function assigneeScoring( ): Promise { // get the price label const priceLabels = issue.labels.filter((label) => label.name.startsWith("Price: ")); - if (!priceLabels) throw Runtime.getState().logger.warn(context.event, "Price label is undefined"); + if (!priceLabels) throw context.logger.warn("Price label is undefined"); // get the smallest price label const priceLabel = priceLabels @@ -32,7 +31,7 @@ export async function assigneeScoring( ?.shift(); if (!priceLabel) { - throw Runtime.getState().logger.warn(context.event, "Price label is undefined"); + throw context.logger.warn("Price label is undefined"); } // get the price diff --git a/src/handlers/comment/handlers/issue/comment-scoring-rubric.ts b/src/handlers/comment/handlers/issue/comment-scoring-rubric.ts index 93a7d69fe..43d09304a 100644 --- a/src/handlers/comment/handlers/issue/comment-scoring-rubric.ts +++ b/src/handlers/comment/handlers/issue/comment-scoring-rubric.ts @@ -3,7 +3,6 @@ import { JSDOM } from "jsdom"; import Decimal from "decimal.js"; import _ from "lodash"; import MarkdownIt from "markdown-it"; -import Runtime from "../../../../bindings/bot-runtime"; import { Comment } from "../../../../types/payload"; import { ContributorClassesKeys } from "./contribution-style-types"; import { FormatScoreConfig, FormatScoreConfigParams } from "./element-score-config"; @@ -226,7 +225,7 @@ export class CommentScoring { private _initialize(context: Context, comment: Comment, userId: number) { if (!this.commentScores[userId]) { - Runtime.getState().logger.debug(context.event, "good thing we initialized, was unsure if necessary"); + context.logger.debug("good thing we initialized, was unsure if necessary"); const initialCommentScoreValue = { totalScoreTotal: ZERO, wordScoreTotal: ZERO, @@ -236,7 +235,7 @@ export class CommentScoring { this.commentScores[userId] = { ...initialCommentScoreValue }; } if (!this.commentScores[userId].details[comment.id]) { - Runtime.getState().logger.debug(context.event, "good thing we initialized, was unsure if necessary"); + context.logger.debug("good thing we initialized, was unsure if necessary"); this.commentScores[userId].details[comment.id] = { totalScoreComment: ZERO, relevanceScoreComment: ZERO, diff --git a/src/handlers/comment/handlers/issue/generate-permit-2-signature.ts b/src/handlers/comment/handlers/issue/generate-permit-2-signature.ts index 54437264b..7ec8d5db0 100644 --- a/src/handlers/comment/handlers/issue/generate-permit-2-signature.ts +++ b/src/handlers/comment/handlers/issue/generate-permit-2-signature.ts @@ -2,7 +2,6 @@ import { MaxUint256, PERMIT2_ADDRESS, PermitTransferFrom, SignatureTransfer } fr import Decimal from "decimal.js"; import { BigNumber, ethers } from "ethers"; import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; -import Runtime from "../../../../bindings/bot-runtime"; import { Context } from "../../../../types"; import { getPayoutConfigByNetworkId } from "../../../../helpers"; import { decryptKeys } from "../../../../utils/private"; @@ -11,31 +10,32 @@ export async function generatePermit2Signature( context: Context, { beneficiary, amount, userId }: GeneratePermit2SignatureParams ) { - const runtime = Runtime.getState(); + const logger = context.logger; const { payments: { evmNetworkId }, keys: { evmPrivateEncrypted }, } = context.config; - if (!evmPrivateEncrypted) throw runtime.logger.warn(context.event, "No bot wallet private key defined"); + + if (!evmPrivateEncrypted) throw logger.warn("No bot wallet private key defined"); const { rpc, paymentToken } = getPayoutConfigByNetworkId(evmNetworkId); const { privateKey } = await decryptKeys(evmPrivateEncrypted); - if (!rpc) throw runtime.logger.error(context.event, "RPC is not defined"); - if (!privateKey) throw runtime.logger.error(context.event, "Private key is not defined"); - if (!paymentToken) throw runtime.logger.error(context.event, "Payment token is not defined"); + if (!rpc) throw logger.error("RPC is not defined"); + if (!privateKey) throw logger.error("Private key is not defined"); + if (!paymentToken) throw logger.error("Payment token is not defined"); let provider; let adminWallet; try { provider = new ethers.providers.JsonRpcProvider(rpc); } catch (error) { - throw runtime.logger.debug(context.event, "Failed to instantiate provider", error); + throw logger.debug("Failed to instantiate provider", error); } try { adminWallet = new ethers.Wallet(privateKey, provider); } catch (error) { - throw runtime.logger.debug(context.event, "Failed to instantiate wallet", error); + throw logger.debug("Failed to instantiate wallet", error); } const permitTransferFromData: PermitTransferFrom = { @@ -55,7 +55,7 @@ export async function generatePermit2Signature( ); const signature = await adminWallet._signTypedData(domain, types, values).catch((error) => { - throw runtime.logger.debug(context.event, "Failed to sign typed data", error); + throw logger.debug("Failed to sign typed data", error); }); const transactionData: TransactionData = { @@ -89,7 +89,7 @@ export async function generatePermit2Signature( url.searchParams.append("claim", base64encodedTxData); url.searchParams.append("network", evmNetworkId.toString()); - runtime.logger.info(context.event, "Generated permit2 signature", { transactionData, url: url.toString() }); + logger.info("Generated permit2 signature", { transactionData, url: url.toString() }); return { transactionData, url }; } diff --git a/src/handlers/comment/handlers/issue/generate-permits.ts b/src/handlers/comment/handlers/issue/generate-permits.ts index ba2f6dd36..275244c59 100644 --- a/src/handlers/comment/handlers/issue/generate-permits.ts +++ b/src/handlers/comment/handlers/issue/generate-permits.ts @@ -41,7 +41,7 @@ async function generateComment(context: Context, totals: TotalsById) { const contributorName = userTotals.user.login; // const contributionClassName = userTotals.details[0].contribution as ContributorClassNames; - if (!evmPrivateEncrypted) throw runtime.logger.warn(context.event, "No bot wallet private key defined"); + if (!evmPrivateEncrypted) throw context.logger.warn("No bot wallet private key defined"); const beneficiaryAddress = await runtime.adapters.supabase.wallet.getAddress(parseInt(userId)); diff --git a/src/handlers/comment/handlers/issue/get-collaborator-ids-for-repo.ts b/src/handlers/comment/handlers/issue/get-collaborator-ids-for-repo.ts index 2bbaf268e..751e1c674 100644 --- a/src/handlers/comment/handlers/issue/get-collaborator-ids-for-repo.ts +++ b/src/handlers/comment/handlers/issue/get-collaborator-ids-for-repo.ts @@ -1,8 +1,6 @@ -import Runtime from "../../../../bindings/bot-runtime"; import { Context, Payload, User } from "../../../../types"; export async function getCollaboratorsForRepo(context: Context): Promise { - const runtime = Runtime.getState(); const payload = context.event.payload as Payload; const collaboratorUsers: User[] = []; @@ -26,7 +24,7 @@ export async function getCollaboratorsForRepo(context: Context): Promise } } } catch (e: unknown) { - runtime.logger.error(context.event, "Fetching collaborator IDs for repo failed!", e); + context.logger.error("Fetching collaborator IDs for repo failed!", e); } return collaboratorUsers; diff --git a/src/handlers/comment/handlers/issue/issue-closed.ts b/src/handlers/comment/handlers/issue/issue-closed.ts index 7155e020c..b36be2472 100644 --- a/src/handlers/comment/handlers/issue/issue-closed.ts +++ b/src/handlers/comment/handlers/issue/issue-closed.ts @@ -1,7 +1,6 @@ -import { Logs } from "../../../../adapters/supabase"; import Runtime from "../../../../bindings/bot-runtime"; import { checkUserPermissionForRepoAndOrg, getAllIssueComments } from "../../../../helpers"; -import { BotConfig, Context } from "../../../../types"; +import { Context } from "../../../../types"; import { Comment, Issue, Payload, StateReason } from "../../../../types/payload"; import structuredMetadata from "../../../shared/structured-metadata"; import { generatePermits } from "./generate-permits"; @@ -16,14 +15,11 @@ const botCommentsFilter = (comment: Comment) => comment.user.type === "Bot"; /* export async function issueClosed(context: Context) { // TODO: delegate permit calculation to GitHub Action - const runtime = Runtime.getState(); - const logger = runtime.logger; const payload = context.event.payload as Payload; const issue = payload.issue as Issue; - const config = context.config; const { issueComments, owner, repository, issueNumber } = await getEssentials(context); - await preflightChecks({ issue, logger, issueComments, config, payload, context }); + await preflightChecks({ issue, issueComments, context }); // === Calculate Permit === // @@ -49,10 +45,10 @@ async function getEssentials(context: Context) { const issue = payload.issue as Issue; const runtime = Runtime.getState(); const logger = runtime.logger; - if (!issue) throw runtime.logger.error(context.event, "Issue is not defined"); + if (!issue) throw context.logger.error("Issue is not defined"); const issueComments = await getAllIssueComments(context, issue.number); const owner = payload?.organization?.login || payload.repository.owner.login; - if (!owner) throw logger.error(context.event, "Owner is not defined"); + if (!owner) throw context.logger.error("Owner is not defined"); const repository = payload?.repository?.name; const issueNumber = issue.number; return { issue, runtime, logger, issueComments, owner, repository, issueNumber }; @@ -61,37 +57,35 @@ async function getEssentials(context: Context) { interface PreflightChecksParams { issue: Issue; - logger: Logs; issueComments: Comment[]; - config: BotConfig; - payload: Payload; context: Context; } -async function preflightChecks({ issue, logger, issueComments, config, payload, context }: PreflightChecksParams) { - if (!issue) throw logger.error(context.event, "Permit generation skipped because issue is undefined"); + +async function preflightChecks({ issue, issueComments, context }: PreflightChecksParams) { + const { payload, config } = context; + if (!issue) throw context.logger.error("Permit generation skipped because issue is undefined"); if (issue.state_reason !== StateReason.COMPLETED) - throw logger.info(context.event, "Issue was not closed as completed. Skipping.", { issue }); + throw context.logger.info("Issue was not closed as completed. Skipping.", { issue }); if (config.features.publicAccessControl.fundExternalClosedIssue) { const userHasPermission = await checkUserPermissionForRepoAndOrg(context, payload.sender.login); if (!userHasPermission) - throw logger.warn( - context.event, + throw context.logger.warn( "Permit generation disabled because this issue has been closed by an external contributor." ); } const priceLabels = issue.labels.find((label) => label.name.startsWith("Price: ")); if (!priceLabels) { - throw logger.warn(context.event, "No price label has been set. Skipping permit generation.", { + throw context.logger.warn("No price label has been set. Skipping permit generation.", { labels: issue.labels, }); } const botComments = issueComments.filter(botCommentsFilter); - checkIfPermitsAlreadyPosted(context, botComments, logger); + checkIfPermitsAlreadyPosted(context, botComments); } -function checkIfPermitsAlreadyPosted(context: Context, botComments: Comment[], logger: Logs) { +function checkIfPermitsAlreadyPosted(context: Context, botComments: Comment[]) { botComments.forEach((comment) => { const parsed = structuredMetadata.parse(comment.body); if (parsed) { @@ -99,7 +93,7 @@ function checkIfPermitsAlreadyPosted(context: Context, botComments: Comment[], l if (parsed.caller === "generatePermits") { // in the comment metadata we store what function rendered the comment console.trace({ parsed }); - throw logger.warn(context.event, "Permit already posted"); + throw context.logger.warn("Permit already posted"); } } }); diff --git a/src/handlers/comment/handlers/issue/relevance-scoring.ts b/src/handlers/comment/handlers/issue/relevance-scoring.ts index a79f96a68..722515b3c 100644 --- a/src/handlers/comment/handlers/issue/relevance-scoring.ts +++ b/src/handlers/comment/handlers/issue/relevance-scoring.ts @@ -1,7 +1,6 @@ import Decimal from "decimal.js"; import { encodingForModel } from "js-tiktoken"; import OpenAI from "openai"; -import Runtime from "../../../../bindings/bot-runtime"; import { Context } from "../../../../types"; import { Comment, Issue } from "../../../../types/payload"; @@ -135,7 +134,7 @@ interface InEachRequestParams { function filterSamples(context: Context, batchResults: number[][], correctLength: number) { return batchResults.filter((result) => { if (result.length != correctLength) { - Runtime.getState().logger.error(context.event, "Correct length is not defined", { + context.logger.error("Correct length is not defined", { batchResultsLength: batchResults.length, result, }); diff --git a/src/handlers/comment/handlers/labels.ts b/src/handlers/comment/handlers/labels.ts index a082fe775..ec3068c6b 100644 --- a/src/handlers/comment/handlers/labels.ts +++ b/src/handlers/comment/handlers/labels.ts @@ -3,19 +3,15 @@ import { isUserAdminOrBillingManager } from "../../../helpers"; import { Context, Payload } from "../../../types"; export async function setLabels(context: Context, body: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const sender = payload.sender.login; const sufficientPrivileges = await isUserAdminOrBillingManager(context, sender); if (!sufficientPrivileges) - return logger.info( - context.event, - `You are not an admin and do not have the required permissions to access this function.` - ); // if sender is not admin, return + return logger.info(`You are not an admin and do not have the required permissions to access this function.`); // if sender is not admin, return - if (!payload.issue) return logger.info(context.event, `Skipping '/labels' because of no issue instance`); + if (!payload.issue) return context.logger.info(`Skipping '/labels' because of no issue instance`); if (body.startsWith("/labels")) { const { username, labels } = parseComment(body); @@ -32,12 +28,11 @@ export async function setLabels(context: Context, body: string) { const userId = await user.getUserId(context.event, username); await access.setAccess(labels, nodeInfo, userId); if (!labels.length) { - return logger.ok(context.event, "Successfully cleared access", { username }); + return context.logger.ok("Successfully cleared access", { username }); } - return logger.ok(context.event, "Successfully set access", { username, labels }); + return context.logger.ok("Successfully set access", { username, labels }); } else { throw logger.error( - context.event, `Invalid syntax for allow \n usage: '/labels set-(access type) @user true|false' \n ex-1 /labels set-multiplier @user false` ); } diff --git a/src/handlers/comment/handlers/multiplier.ts b/src/handlers/comment/handlers/multiplier.ts index 40035e968..984b37d72 100644 --- a/src/handlers/comment/handlers/multiplier.ts +++ b/src/handlers/comment/handlers/multiplier.ts @@ -13,16 +13,15 @@ import { Context, Payload } from "../../../types"; * /multiplier @user "Multiplier reason" 0.5 **/ export async function multiplier(context: Context, body: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const sender = payload.sender.login; const repo = payload.repository; const comment = payload.comment; - if (!comment) return logger.info(context.event, `Skipping '/multiplier' because of no comment instance`); + if (!comment) return context.logger.info(`Skipping '/multiplier' because of no comment instance`); const issue = payload.issue; - logger.info(context.event, "Running '/multiplier' command handler", { sender }); - if (!issue) return logger.info(context.event, `Skipping '/multiplier' because of no issue instance`); + context.logger.info("Running '/multiplier' command handler", { sender }); + if (!issue) return context.logger.info(`Skipping '/multiplier' because of no issue instance`); const regex = /(".*?"|[^"\s]+)(?=\s*|\s*$)/g; const matches = body.match(regex); matches?.shift(); @@ -48,7 +47,7 @@ export async function multiplier(context: Context, body: string) { // if sender is not admin or billing_manager, check db for access if (sufficientPrivileges) { - logger.info(context.event, "Getting multiplier access", { + context.logger.info("Getting multiplier access", { repo: repo.full_name, user: sender, }); @@ -62,7 +61,6 @@ export async function multiplier(context: Context, body: string) { if (!accessible) { return logger.warn( - context.event, "Insufficient permissions to update the payout multiplier. User is not an 'admin' or 'billing_manager'", { repo: repo.full_name, @@ -71,14 +69,13 @@ export async function multiplier(context: Context, body: string) { ); } } - logger.info(context.event, "Upserting to the wallet table", { username, taskMultiplier, reason }); + context.logger.info("Upserting to the wallet table", { username, taskMultiplier, reason }); const { access } = Runtime.getState().adapters.supabase; await access.upsertMultiplier(payload.sender.id, taskMultiplier, reason, comment); if (taskMultiplier > 1) { return logger.ok( - context.event, "Successfully changed the payout multiplier. \ This feature is designed to limit the contributor's compensation \ for any task on the current repository \ @@ -91,7 +88,7 @@ export async function multiplier(context: Context, body: string) { } ); } else { - return logger.ok(context.event, "Successfully changed the payout multiplier", { + return context.logger.ok("Successfully changed the payout multiplier", { username, taskMultiplier, reason, @@ -99,7 +96,6 @@ export async function multiplier(context: Context, body: string) { } } else { return logger.error( - context.event, "Invalid body for taskMultiplier command. Example usage: /multiplier @user 0.5 'Multiplier reason'" ); } diff --git a/src/handlers/comment/handlers/payout.ts b/src/handlers/comment/handlers/payout.ts index 221a9f565..fcc379686 100644 --- a/src/handlers/comment/handlers/payout.ts +++ b/src/handlers/comment/handlers/payout.ts @@ -1,13 +1,11 @@ -import Runtime from "../../../bindings/bot-runtime"; import { Context, Payload } from "../../../types"; import { isUserAdminOrBillingManager } from "../../../helpers/issue"; export async function autoPay(context: Context, body: string) { - const runtime = Runtime.getState(); const payload = context.event.payload as Payload; - const logger = runtime.logger; + const logger = context.logger; - logger.info(context.event, "Running '/autopay' command handler", { sender: payload.sender.login }); + logger.info("Running '/autopay' command handler", { sender: payload.sender.login }); const pattern = /^\/autopay (true|false)$/; const autopayCommand = body.match(pattern); @@ -16,14 +14,12 @@ export async function autoPay(context: Context, body: string) { const hasSufficientPrivileges = await isUserAdminOrBillingManager(context, payload.sender.login); if (!hasSufficientPrivileges) { return logger.warn( - context.event, "You must be an 'admin' or 'billing_manager' to toggle automatic payments for completed issues." ); } - return logger.ok(context.event, "Automatic payment for this issue state:", { autopayCommand }); + return context.logger.ok("Automatic payment for this issue state:", { autopayCommand }); } return logger.warn( - context.event, `Invalid command. Please use the following format: \`/autopay true\` or \`/autopay false\` to toggle automatic payments for completed issues.` ); } diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index 93207fc72..e3fa1d069 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -4,28 +4,28 @@ import _ from "lodash"; export async function query(context: Context, body: string) { const runtime = Runtime.getState(), - logger = runtime.logger, + logger = context.logger, payload = context.event.payload as Payload, sender = payload.sender.login; - logger.info(context.event, "Running '/query' command handler", { sender }); + logger.info("Running '/query' command handler", { sender }); const issue = payload.issue; - if (!issue) return logger.info(context.event, `Skipping '/query' because of no issue instance`); + if (!issue) return logger.info(`Skipping '/query' because of no issue instance`); const regex = /^\/query\s+@([\w-]+)\s*$/; const matches = body.match(regex); const username = matches?.[1]; if (!username) { - throw logger.error(context.event, "Invalid body for query command \n usage /query @user"); + throw logger.error("Invalid body for query command \n usage /query @user"); } const database = runtime.adapters.supabase; const usernameResponse = await context.event.octokit.users.getByUsername({ username }); const user = usernameResponse.data; if (!user) { - throw logger.error(context.event, "User not found", { username }); + throw logger.error("User not found", { username }); } const accessData = await database.access.getAccess(user.id); const walletAddress = await database.wallet.getAddress(user.id); @@ -34,7 +34,7 @@ export async function query(context: Context, body: string) { messageBuffer.push(renderMarkdownTableHeader()); if (!accessData && !walletAddress) { - return logger.warn(context.event, "No access or wallet found for user", { username }); + return logger.warn("No access or wallet found for user", { username }); } if (accessData) { messageBuffer.push(appendToMarkdownTableBody(accessData)); diff --git a/src/handlers/comment/handlers/unassign.ts b/src/handlers/comment/handlers/unassign.ts index 232fb6a29..903c2768f 100644 --- a/src/handlers/comment/handlers/unassign.ts +++ b/src/handlers/comment/handlers/unassign.ts @@ -1,29 +1,27 @@ -import Runtime from "../../../bindings/bot-runtime"; import { Context, Payload } from "../../../types"; import { closePullRequestForAnIssue } from "../../assign/index"; export async function unassign(context: Context, body: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; if (!body.startsWith("/stop")) { - return logger.error(context.event, "Skipping to unassign", { body }); + return logger.error("Skipping to unassign", { body }); } const payload = context.event.payload as Payload; - logger.info(context.event, "Running '/stop' command handler", { sender: payload.sender.login }); + logger.info("Running '/stop' command handler", { sender: payload.sender.login }); const issue = payload.issue; if (!issue) { - return logger.info(context.event, `Skipping '/stop' because of no issue instance`); + return logger.info(`Skipping '/stop' because of no issue instance`); } const issueNumber = issue.number; const assignees = payload.issue?.assignees ?? []; if (assignees.length == 0) { - return logger.warn(context.event, "No assignees found for issue", { issueNumber }); + return logger.warn("No assignees found for issue", { issueNumber }); } const shouldUnassign = assignees[0]?.login.toLowerCase() == payload.sender.login.toLowerCase(); - logger.debug(context.event, "Unassigning sender", { + logger.debug("Unassigning sender", { sender: payload.sender.login.toLowerCase(), assignee: assignees[0]?.login.toLowerCase(), shouldUnassign, @@ -39,10 +37,10 @@ export async function unassign(context: Context, body: string) { issue_number: issueNumber, assignees: [payload.sender.login], }); - return logger.ok(context.event, "You have been unassigned from the task", { + return logger.ok("You have been unassigned from the task", { issueNumber, user: payload.sender.login, }); } - return logger.warn(context.event, "You are not assigned to this task", { issueNumber, user: payload.sender.login }); + return logger.warn("You are not assigned to this task", { issueNumber, user: payload.sender.login }); } diff --git a/src/handlers/comment/handlers/wallet.ts b/src/handlers/comment/handlers/wallet.ts index 7f8563011..c49134a32 100644 --- a/src/handlers/comment/handlers/wallet.ts +++ b/src/handlers/comment/handlers/wallet.ts @@ -1,5 +1,4 @@ import { constants, ethers } from "ethers"; -import { Logs } from "../../../adapters/supabase"; import Runtime from "../../../bindings/bot-runtime"; import { resolveAddress } from "../../../helpers"; import { Context, Payload } from "../../../types"; @@ -21,7 +20,7 @@ export async function registerWallet(context: Context, body: string) { const runtime = Runtime.getState(); const payload = context.event.payload as Payload; const config = context.config; - const logger = runtime.logger; + const logger = context.logger; const sender = payload.sender.login; const regexForAddress = /(0x[a-fA-F0-9]{40})/g; @@ -30,25 +29,24 @@ export async function registerWallet(context: Context, body: string) { const ensName = extractEnsName(body.replace("/wallet", "").trim()); if (!address && ensName) { - logger.info(context.event, "Trying to resolve address from ENS name", { ensName }); + context.logger.info("Trying to resolve address from ENS name", { ensName }); address = await resolveAddress(ensName); if (!address) { - throw logger.error(context.event, "Resolving address from ENS name failed", { ensName }); + throw context.logger.error("Resolving address from ENS name failed", { ensName }); } - logger.ok(context.event, "Resolved address from ENS name", { ensName, address }); + context.logger.ok("Resolved address from ENS name", { ensName, address }); } if (!address) { - return logger.info(context.event, "Skipping to register a wallet address because both address/ens doesn't exist"); + return context.logger.info("Skipping to register a wallet address because both address/ens doesn't exist"); } if (config.miscellaneous.registerWalletWithVerification) { - _registerWalletWithVerification(context, body, address, logger); + _registerWalletWithVerification(context, body, address); } if (address == constants.AddressZero) { return logger.warn( - context.event, "Skipping to register a wallet address because user is trying to set their address to null address" ); } @@ -56,13 +54,13 @@ export async function registerWallet(context: Context, body: string) { if (payload.comment) { const { wallet } = runtime.adapters.supabase; await wallet.upsertWalletAddress(context.event, address); - return logger.ok(context.event, "Successfully registered wallet address", { sender, address }); + return context.logger.ok("Successfully registered wallet address", { sender, address }); } else { throw new Error("Payload comment is undefined"); } } -function _registerWalletWithVerification(context: Context, body: string, address: string, logger: Logs) { +function _registerWalletWithVerification(context: Context, body: string, address: string) { const regexForSigHash = /(0x[a-fA-F0-9]{130})/g; const sigHashMatches = body.match(regexForSigHash); const sigHash = sigHashMatches ? sigHashMatches[0] : null; @@ -73,10 +71,10 @@ function _registerWalletWithVerification(context: Context, body: string, address const isSigHashValid = sigHash && ethers.utils.verifyMessage(messageToSign, sigHash) == ethers.utils.getAddress(address); if (!isSigHashValid) { - throw logger.error(context.event, failedSigLogMsg); + throw context.logger.error(failedSigLogMsg); } } catch (e) { - logger.error(context.event, "Exception thrown by verifyMessage for /wallet: ", e); - throw logger.error(context.event, failedSigLogMsg); + context.logger.error("Exception thrown by verifyMessage for /wallet: ", e); + throw context.logger.error(failedSigLogMsg); } } diff --git a/src/handlers/label/index.ts b/src/handlers/label/index.ts index cd102f48a..168a50bbe 100644 --- a/src/handlers/label/index.ts +++ b/src/handlers/label/index.ts @@ -3,21 +3,20 @@ import { hasLabelEditPermission } from "../../helpers"; import { Context, Payload } from "../../types"; export async function watchLabelChange(context: Context) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const { label, changes, sender } = payload; const previousLabel = changes?.name?.from; if (!previousLabel) { - throw logger.error(context.event, "previous label name is undefined"); + throw logger.error("previous label name is undefined"); } const currentLabel = label?.name; const triggerUser = sender.login; if (!previousLabel || !currentLabel) { - return logger.debug(context.event, "No label name change.. skipping"); + return logger.debug("No label name change.. skipping"); } // check if user is authorized to make the change @@ -31,5 +30,5 @@ export async function watchLabelChange(context: Context) { authorized: hasAccess, repository: payload.repository, }); - return logger.debug(context.event, "label name change saved to db"); + return logger.debug("label name change saved to db"); } diff --git a/src/handlers/pricing/action.ts b/src/handlers/pricing/action.ts index d53ef2ec6..69978695a 100644 --- a/src/handlers/pricing/action.ts +++ b/src/handlers/pricing/action.ts @@ -1,14 +1,12 @@ -import Runtime from "../../bindings/bot-runtime"; import { calculateLabelValue, clearAllPriceLabelsOnIssue } from "../../helpers"; import { Label, Context } from "../../types"; export async function handleParentIssue(context: Context, labels: Label[]) { - const runtime = Runtime.getState(); const issuePrices = labels.filter((label) => label.name.toString().startsWith("Price:")); if (issuePrices.length) { await clearAllPriceLabelsOnIssue(context); } - throw runtime.logger.warn(context.event, "Pricing is disabled on parent issues."); + throw context.logger.warn("Pricing is disabled on parent issues."); } export function sortLabelsByValue(labels: Label[]) { diff --git a/src/handlers/pricing/pre.ts b/src/handlers/pricing/pre.ts index debf5deb7..d7d9e3ae4 100644 --- a/src/handlers/pricing/pre.ts +++ b/src/handlers/pricing/pre.ts @@ -1,4 +1,3 @@ -import Runtime from "../../bindings/bot-runtime"; import { calculateLabelValue, createLabel, listLabelsForRepo } from "../../helpers"; import { Context } from "../../types"; import { calculateTaskPrice } from "../shared/pricing"; @@ -7,16 +6,15 @@ import { calculateTaskPrice } from "../shared/pricing"; // If there's something missing, they will be added export async function syncPriceLabelsToConfig(context: Context) { - const runtime = Runtime.getState(); const config = context.config; - const logger = runtime.logger; + const logger = context.logger; const { features: { assistivePricing }, } = config; if (!assistivePricing) { - logger.info(context.event, `Assistive pricing is disabled`); + logger.info(`Assistive pricing is disabled`); return; } @@ -44,8 +42,8 @@ export async function syncPriceLabelsToConfig(context: Context) { // Create missing labels if (missingLabels.length > 0) { - logger.info(context.event, "Missing labels found, creating them", { missingLabels }); + logger.info("Missing labels found, creating them", { missingLabels }); await Promise.all(missingLabels.map((label) => createLabel(context, label))); - logger.info(context.event, `Creating missing labels done`); + logger.info(`Creating missing labels done`); } } diff --git a/src/handlers/pricing/pricing-label.ts b/src/handlers/pricing/pricing-label.ts index 24c316e86..22b84ed55 100644 --- a/src/handlers/pricing/pricing-label.ts +++ b/src/handlers/pricing/pricing-label.ts @@ -1,4 +1,3 @@ -import Runtime from "../../bindings/bot-runtime"; import { addLabelToIssue, clearAllPriceLabelsOnIssue, createLabel, getAllLabeledEvents } from "../../helpers"; import { BotConfig, Context, Label, Payload, UserType } from "../../types"; import { labelAccessPermissionsCheck } from "../access"; @@ -6,11 +5,10 @@ import { setPrice } from "../shared/pricing"; import { handleParentIssue, isParentIssue, sortLabelsByValue } from "./action"; export async function onLabelChangeSetPricing(context: Context): Promise { - const runtime = Runtime.getState(); const config = context.config; - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; - if (!payload.issue) throw logger.error(context.event, "Issue is not defined"); + if (!payload.issue) throw context.logger.error("Issue is not defined"); const labels = payload.issue.labels; const labelNames = labels.map((i) => i.name); @@ -22,19 +20,19 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const permission = await labelAccessPermissionsCheck(context); if (!permission) { if (config.features.publicAccessControl.setLabel === false) { - throw logger.warn(context.event, "No public access control to set labels"); + throw logger.warn("No public access control to set labels"); } - throw logger.warn(context.event, "No permission to set labels"); + throw logger.warn("No permission to set labels"); } const { assistivePricing } = config.features; - if (!labels) throw logger.warn(context.event, `No labels to calculate price`); + if (!labels) throw logger.warn(`No labels to calculate price`); // here we should make an exception if it was a price label that was just set to just skip this action const isPayloadToSetPrice = payload.label?.name.includes("Price: "); if (isPayloadToSetPrice) { - logger.info(context.event, "This is setting the price label directly so skipping the rest of the action."); + logger.info("This is setting the price label directly so skipping the rest of the action."); // make sure to clear all other price labels except for the smallest price label. @@ -59,7 +57,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const recognizedLabels = getRecognizedLabels(labels, config); if (!recognizedLabels.time.length || !recognizedLabels.priority.length) { - logger.warn(context.event, "No recognized labels to calculate price"); + logger.warn("No recognized labels to calculate price"); await clearAllPriceLabelsOnIssue(context); return; } @@ -67,7 +65,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const minLabels = getMinLabels(recognizedLabels); if (!minLabels.time || !minLabels.priority) { - logger.warn(context.event, "No label to calculate price"); + logger.warn("No label to calculate price"); return; } @@ -77,7 +75,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { await handleTargetPriceLabel(context, targetPriceLabel, labelNames, assistivePricing); } else { await clearAllPriceLabelsOnIssue(context); - logger.info(context.event, `Skipping action...`); + logger.info(`Skipping action...`); } } @@ -118,27 +116,26 @@ async function handleTargetPriceLabel( } async function handleExistingPriceLabel(context: Context, targetPriceLabel: string, assistivePricing: boolean) { - const logger = Runtime.getState().logger; + const logger = context.logger; let labeledEvents = await getAllLabeledEvents(context); - if (!labeledEvents) return logger.warn(context.event, "No labeled events found"); + if (!labeledEvents) return logger.warn("No labeled events found"); labeledEvents = labeledEvents.filter((event) => event.label?.name.includes("Price")); - if (!labeledEvents.length) return logger.warn(context.event, "No price labeled events found"); + if (!labeledEvents.length) return logger.warn("No price labeled events found"); if (labeledEvents[labeledEvents.length - 1].actor?.type == UserType.User) { - logger.info(context.event, `Skipping... already exists`); + logger.info(`Skipping... already exists`); } else { await addPriceLabelToIssue(context, targetPriceLabel, assistivePricing); } } async function addPriceLabelToIssue(context: Context, targetPriceLabel: string, assistivePricing: boolean) { - const logger = Runtime.getState().logger; await clearAllPriceLabelsOnIssue(context); const exists = await labelExists(context, targetPriceLabel); if (assistivePricing && !exists) { - logger.info(context.event, "Assistive pricing is enabled, creating label...", { targetPriceLabel }); + context.logger.info("Assistive pricing is enabled, creating label...", { targetPriceLabel }); await createLabel(context, targetPriceLabel, "price"); } diff --git a/src/handlers/processors.ts b/src/handlers/processors.ts index 52c002804..411276423 100644 --- a/src/handlers/processors.ts +++ b/src/handlers/processors.ts @@ -27,7 +27,7 @@ export const processors: Record = { }, [GitHubEvent.ISSUES_REOPENED]: { pre: [], - action: [async () => Runtime.getState().logger.debug(null, "TODO: replace ISSUES_REOPENED handler")], + action: [async () => Runtime.getState().logger.debug("TODO: replace ISSUES_REOPENED handler")], post: [], }, [GitHubEvent.ISSUES_LABELED]: { diff --git a/src/handlers/pull-request/create-devpool-pr.ts b/src/handlers/pull-request/create-devpool-pr.ts index e1d38be97..a2201857f 100644 --- a/src/handlers/pull-request/create-devpool-pr.ts +++ b/src/handlers/pull-request/create-devpool-pr.ts @@ -1,21 +1,19 @@ -import Runtime from "../../bindings/bot-runtime"; import { Context, GithubContent, Payload } from "../../types"; export async function createDevPoolPR(context: Context) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const devPoolOwner = "ubiquity"; const devPoolRepo = "devpool-directory"; if (!payload.repositories_added) { - return logger.info(context.event, "No repositories added"); + return logger.info("No repositories added"); } const repository = payload.repositories_added[0]; - logger.info(context.event, "New Install: ", { repository: repository.full_name }); + logger.info("New Install: ", { repository: repository.full_name }); const [owner, repo] = repository.full_name.split("/"); @@ -58,7 +56,7 @@ export async function createDevPoolPR(context: Context) { sha: mainSha, }); - logger.info(context.event, "Branch created on DevPool Directory"); + logger.info("Branch created on DevPool Directory"); await context.event.octokit.repos.createOrUpdateFileContents({ owner: devPoolOwner, @@ -79,5 +77,5 @@ export async function createDevPoolPR(context: Context) { base: baseRef, }); - return logger.info(context.event, "Pull request created on DevPool Directory"); + return logger.info("Pull request created on DevPool Directory"); } diff --git a/src/handlers/push/check-modified-base-rate.ts b/src/handlers/push/check-modified-base-rate.ts index 573d9d511..c389e660b 100644 --- a/src/handlers/push/check-modified-base-rate.ts +++ b/src/handlers/push/check-modified-base-rate.ts @@ -1,24 +1,22 @@ -import Runtime from "../../bindings/bot-runtime"; import { PushPayload, Context } from "../../types"; import { updateBaseRate } from "./update-base-rate"; import { ZERO_SHA, getCommitChanges, BASE_RATE_FILE } from "./index"; export async function checkModifiedBaseRate(context: Context) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as PushPayload; // if zero sha, push is a pr change if (payload.before === ZERO_SHA) { - logger.debug(context.event, "Skipping push events, not a master write"); + logger.debug("Skipping push events, not a master write"); } const changes = getCommitChanges(payload.commits); // skip if empty if (changes && changes.length === 0) { - logger.debug(context.event, "Skipping push events, file change empty 1"); + logger.debug("Skipping push events, file change empty 1"); } // check for modified or added files and check for specified file @@ -26,5 +24,5 @@ export async function checkModifiedBaseRate(context: Context) { // update base rate await updateBaseRate(context, BASE_RATE_FILE); } - logger.debug(context.event, "Skipping push events, file change empty 2"); + logger.debug("Skipping push events, file change empty 2"); } diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index dd07ea195..b87f8074b 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -29,7 +29,7 @@ export async function validateConfigChange(context: ProbotContext) { const payload = context.payload as PushPayload; if (!payload.ref.startsWith("refs/heads/")) { - logger.debug(context, "Skipping push events, not a branch"); + logger.debug("Skipping push events, not a branch"); return; } @@ -37,7 +37,7 @@ export async function validateConfigChange(context: ProbotContext) { // skip if empty if (changes && changes.length === 0) { - logger.debug(context, "Skipping push events, file change empty 3"); + logger.debug("Skipping push events, file change empty 3"); return; } @@ -47,7 +47,7 @@ export async function validateConfigChange(context: ProbotContext) { .filter((commit) => commit.modified.includes(BASE_RATE_FILE) || commit.added.includes(BASE_RATE_FILE)) .reverse()[0]?.id; if (!commitSha) { - logger.debug(context, "Skipping push events, commit sha not found"); + logger.debug("Skipping push events, commit sha not found"); return; } @@ -82,14 +82,14 @@ export async function validateConfigChange(context: ProbotContext) { } if (errorMsg) { - logger.info(context, "Config validation failed!", errorMsg); + logger.info("Config validation failed!", errorMsg); await createCommitComment(context, errorMsg, commitSha, BASE_RATE_FILE); } else { - logger.debug(context, `Config validation passed!`); + logger.debug(`Config validation passed!`); } } } else { - logger.debug(context, `Skipping push events, file change doesn't include config file: ${JSON.stringify(changes)}`); + logger.debug(`Skipping push events, file change doesn't include config file: ${JSON.stringify(changes)}`); } } diff --git a/src/handlers/push/update-base-rate.ts b/src/handlers/push/update-base-rate.ts index dfd143a26..a157d70e1 100644 --- a/src/handlers/push/update-base-rate.ts +++ b/src/handlers/push/update-base-rate.ts @@ -1,12 +1,9 @@ -import Runtime from "../../bindings/bot-runtime"; - import { getPreviousFileContent, listLabelsForRepo, updateLabelsFromBaseRate } from "../../helpers"; import { Label, PushPayload, Context } from "../../types"; import { parseYaml } from "../../utils/generate-configuration"; export async function updateBaseRate(context: Context, filePath: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; // Get default branch from ref const payload = context.event.payload as PushPayload; const branch = payload.ref?.split("refs/heads/")[1]; @@ -17,26 +14,26 @@ export async function updateBaseRate(context: Context, filePath: string) { const previousFileContent = await getPreviousFileContent(context, owner, repo, branch, filePath); if (!previousFileContent) { - throw logger.error(context.event, "Getting previous file content failed"); + throw logger.error("Getting previous file content failed"); } const previousConfigRaw = Buffer.from(previousFileContent, "base64").toString(); const previousConfigParsed = parseYaml(previousConfigRaw); if (!previousConfigParsed || !previousConfigParsed.payments.basePriceMultiplier) { - throw logger.warn(context.event, "No multiplier found in previous config"); + throw logger.warn("No multiplier found in previous config"); } const previousBaseRate = previousConfigParsed.payments.basePriceMultiplier; if (!previousBaseRate) { - throw logger.warn(context.event, "No base rate found in previous config"); + throw logger.warn("No base rate found in previous config"); } // fetch all labels const repoLabels = await listLabelsForRepo(context); if (repoLabels.length === 0) { - throw logger.warn(context.event, "No labels on this repo"); + throw logger.warn("No labels on this repo"); } return await updateLabelsFromBaseRate(context, owner, repo, repoLabels as Label[], previousBaseRate); diff --git a/src/handlers/shared/pricing.ts b/src/handlers/shared/pricing.ts index 04a706bbc..c061bd3d2 100644 --- a/src/handlers/shared/pricing.ts +++ b/src/handlers/shared/pricing.ts @@ -1,4 +1,3 @@ -import Runtime from "../../bindings/bot-runtime"; import { calculateLabelValue } from "../../helpers"; import { Label, Context } from "../../types"; @@ -15,23 +14,22 @@ export function calculateTaskPrice( } export function setPrice(context: Context, timeLabel: Label, priorityLabel: Label) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const { labels } = context.config; - if (!timeLabel || !priorityLabel) throw logger.warn(context.event, "Time or priority label is not defined"); + if (!timeLabel || !priorityLabel) throw logger.warn("Time or priority label is not defined"); const recognizedTimeLabels = labels.time.find((configLabel) => configLabel === timeLabel.name); - if (!recognizedTimeLabels) throw logger.warn(context.event, "Time label is not recognized"); + if (!recognizedTimeLabels) throw logger.warn("Time label is not recognized"); const recognizedPriorityLabels = labels.priority.find((configLabel) => configLabel === priorityLabel.name); - if (!recognizedPriorityLabels) throw logger.warn(context.event, "Priority label is not recognized"); + if (!recognizedPriorityLabels) throw logger.warn("Priority label is not recognized"); const timeValue = calculateLabelValue(recognizedTimeLabels); - if (!timeValue) throw logger.warn(context.event, "Time value is not defined"); + if (!timeValue) throw logger.warn("Time value is not defined"); const priorityValue = calculateLabelValue(recognizedPriorityLabels); - if (!priorityValue) throw logger.warn(context.event, "Priority value is not defined"); + if (!priorityValue) throw logger.warn("Priority value is not defined"); const taskPrice = calculateTaskPrice(context, timeValue, priorityValue); return `Price: ${taskPrice} USD`; diff --git a/src/handlers/wildcard/unassign/unassign.ts b/src/handlers/wildcard/unassign/unassign.ts index bbc1d9ca8..23e9d3539 100644 --- a/src/handlers/wildcard/unassign/unassign.ts +++ b/src/handlers/wildcard/unassign/unassign.ts @@ -1,6 +1,4 @@ import { RestEndpointMethodTypes } from "@octokit/rest"; -import { Logs } from "../../../adapters/supabase"; -import Runtime from "../../../bindings/bot-runtime"; import { listAllIssuesAndPullsForRepo } from "../../../helpers"; import { getLinkedPullRequests } from "../../../helpers/parser"; import { Commit, Context, Issue, IssueType, Payload, User } from "../../../types"; @@ -9,31 +7,29 @@ type IssuesListEventsResponseData = RestEndpointMethodTypes["issues"]["listEvent // type Commit[] = Commit[]; // RestEndpointMethodTypes["pulls"]["listCommits"]["response"]["data"]; export async function checkTasksToUnassign(context: Context) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const issuesAndPullsOpened = await listAllIssuesAndPullsForRepo(context, IssueType.OPEN); const assignedIssues = issuesAndPullsOpened.filter((issue) => issue.assignee); const tasksToUnassign = await Promise.all( assignedIssues.map(async (assignedIssue: Issue) => checkTaskToUnassign(context, assignedIssue)) ); - logger.ok(context.event, "Checked all the tasks to unassign", { + logger.ok("Checked all the tasks to unassign", { tasksToUnassign: tasksToUnassign.filter(Boolean).map((task) => task?.metadata), }); } async function checkTaskToUnassign(context: Context, assignedIssue: Issue) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const { timers: { taskDisqualifyDuration, taskFollowUpDuration }, } = context.config; - logger.info(context.event, "Checking for neglected tasks", { issueNumber: assignedIssue.number }); + logger.info("Checking for neglected tasks", { issueNumber: assignedIssue.number }); if (!assignedIssue.assignees) { - throw logger.error(context.event, "No assignees found when there are supposed to be assignees.", { + throw logger.error("No assignees found when there are supposed to be assignees.", { issueNumber: assignedIssue.number, }); } @@ -95,7 +91,6 @@ async function checkTaskToUnassign(context: Context, assignedIssue: Issue) { login, name, number, - logger, }); // DONE: follow up with those who are in `assignees` and not inside of `disqualifiedAssignees` or `activeAssigneesInFollowUpDuration` @@ -106,11 +101,10 @@ async function checkTaskToUnassign(context: Context, assignedIssue: Issue) { login, name, number, - logger, taskDisqualifyDuration, }); - return logger.ok(context.event, "Checked task to unassign", { + return logger.ok("Checked task to unassign", { issueNumber: assignedIssue.number, disqualifiedAssignees, }); @@ -125,7 +119,6 @@ async function followUpWithTheRest( login, name, number, - logger, taskDisqualifyDuration, }: FollowUpWithTheRest ) { @@ -156,9 +149,9 @@ async function followUpWithTheRest( issue_number: number, body: followUpMessage, }); - logger.info(context.event, "Followed up with idle assignees", { followUpAssignees }); + context.logger.info("Followed up with idle assignees", { followUpAssignees }); } catch (e: unknown) { - logger.error(context.event, "Failed to follow up with idle assignees", e); + context.logger.error("Failed to follow up with idle assignees", e); } } } @@ -230,7 +223,7 @@ async function aggregateAssigneeActivity({ context, login, name, number, assigne async function disqualifyIdleAssignees( context: Context, - { assignees, activeAssigneesInDisqualifyDuration, login, name, number, logger }: DisqualifyIdleAssignees + { assignees, activeAssigneesInDisqualifyDuration, login, name, number }: DisqualifyIdleAssignees ) { const idleAssignees = assignees.filter((assignee) => !activeAssigneesInDisqualifyDuration.includes(assignee)); @@ -242,9 +235,9 @@ async function disqualifyIdleAssignees( issue_number: number, assignees: idleAssignees, }); - logger.info(context.event, "Unassigned idle assignees", { idleAssignees }); + context.logger.info("Unassigned idle assignees", { idleAssignees }); } catch (e: unknown) { - logger.error(context.event, "Failed to unassign idle assignees", e); + context.logger.error("Failed to unassign idle assignees", e); } } return idleAssignees; @@ -375,7 +368,6 @@ interface DisqualifyIdleAssignees { login: string; name: string; number: number; - logger: Logs; } interface FollowUpWithTheRest { @@ -385,7 +377,6 @@ interface FollowUpWithTheRest { login: string; name: string; number: number; - logger: Logs; taskDisqualifyDuration: number; } diff --git a/src/helpers/file.ts b/src/helpers/file.ts index 2aa7f5555..4d9a78584 100644 --- a/src/helpers/file.ts +++ b/src/helpers/file.ts @@ -10,8 +10,7 @@ export async function getPreviousFileContent( branch: string, filePath: string ) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; try { // Get the latest commit of the branch @@ -63,7 +62,7 @@ export async function getPreviousFileContent( } return null; } catch (error: unknown) { - logger.debug(context.event, "Error retrieving previous file content.", { error }); + logger.debug("Error retrieving previous file content.", { error }); return null; } } @@ -122,7 +121,7 @@ export async function getFileContent( } return null; } catch (error: unknown) { - logger.debug(context, "Error retrieving file content.", { error }); + logger.debug("Error retrieving file content.", { error }); return null; } } diff --git a/src/helpers/gpt.ts b/src/helpers/gpt.ts index d0d40cddc..586e88788 100644 --- a/src/helpers/gpt.ts +++ b/src/helpers/gpt.ts @@ -1,6 +1,5 @@ import OpenAI from "openai"; import { CreateChatCompletionRequestMessage } from "openai/resources/chat"; -import Runtime from "../bindings/bot-runtime"; import { getAllIssueComments, getAllLinkedIssuesAndPullsInBody } from "../helpers"; import { Context, Payload, StreamlinedComment, UserType } from "../types"; @@ -61,8 +60,7 @@ export async function decideContextGPT( linkedPRStreamlined: StreamlinedComment[], linkedIssueStreamlined: StreamlinedComment[] ) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const payload = context.event.payload as Payload; const issue = payload.issue; @@ -77,7 +75,7 @@ export async function decideContextGPT( const commentsRaw = await getAllIssueComments(context, issue.number, "raw"); if (!comments) { - logger.info(context.event, `Error getting issue comments`); + logger.info(`Error getting issue comments`); return `Error getting issue comments`; } @@ -101,7 +99,7 @@ export async function decideContextGPT( const links = await getAllLinkedIssuesAndPullsInBody(context, issue.number); if (typeof links === "string") { - return logger.info(context.event, "Error getting linked issues or prs: ", { links }); + return logger.info("Error getting linked issues or prs: ", { links }); } linkedIssueStreamlined = links.linkedIssues; @@ -133,14 +131,12 @@ export async function decideContextGPT( export async function askGPT(context: Context, chatHistory: CreateChatCompletionRequestMessage[]) { // base askGPT function - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const config = context.config; const { keys } = config; if (!keys.openAi) { throw logger.error( - context.event, "You must configure the `openai-api-key` property in the bot configuration in order to use AI powered features." ); } @@ -165,7 +161,7 @@ export async function askGPT(context: Context, chatHistory: CreateChatCompletion }; if (!res) { - throw logger.error(context.event, "Error getting GPT response", { res }); + throw context.logger.error("Error getting GPT response", { res }); } return { answer, tokenUsage }; diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index 619819d95..2e9422dae 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -8,7 +8,6 @@ import { UserType, } from "../types"; import { checkRateLimitGit } from "../utils"; -import Runtime from "../bindings/bot-runtime"; import { LogReturn } from "../adapters/supabase"; import { Payload, Context } from "../types"; @@ -75,16 +74,14 @@ export async function clearAllPriceLabelsOnIssue(context: Context) { name: issuePrices[0].name, }); // } catch (e: unknown) { - // runtime.logger.debug(context.event, "Clearing all price labels failed!", e); + // context.logger.debug("Clearing all price labels failed!", e); // } } export async function addLabelToIssue(context: Context, labelName: string) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; if (!payload.issue) { - throw runtime.logger.error(context.event, "Issue object is null"); + throw context.logger.error("Issue object is null"); } try { @@ -95,7 +92,7 @@ export async function addLabelToIssue(context: Context, labelName: string) { labels: [labelName], }); } catch (e: unknown) { - runtime.logger.debug(context.event, "Adding a label to issue failed!", e); + context.logger.debug("Adding a label to issue failed!", e); } } @@ -147,7 +144,6 @@ export async function listAllIssuesAndPullsForRepo(context: Context, state: "ope export async function addCommentToIssue(context: Context, message: HandlerReturnValuesNoVoid, issueNumber: number) { let comment = message as string; - const runtime = Runtime.getState(); if (message instanceof LogReturn) { comment = message.logMessage.diff; console.trace( @@ -167,20 +163,18 @@ export async function addCommentToIssue(context: Context, message: HandlerReturn body: comment, }); } catch (e: unknown) { - runtime.logger.error(context.event, "Adding a comment failed!", e); + context.logger.error("Adding a comment failed!", e); } } export async function upsertLastCommentToIssue(context: Context, issue_number: number, commentBody: string) { - const runtime = Runtime.getState(); - try { const comments = await getAllIssueComments(context, issue_number); if (comments.length > 0 && comments[comments.length - 1].body !== commentBody) await addCommentToIssue(context, commentBody, issue_number); } catch (e: unknown) { - runtime.logger.debug(context.event, "Upserting last comment failed!", e); + context.logger.debug("Upserting last comment failed!", e); } } @@ -189,8 +183,6 @@ export async function getIssueDescription( issueNumber: number, format: "raw" | "html" | "text" = "raw" ): Promise { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; const response = await context.event.octokit.rest.issues.get({ owner: payload.repository.owner.login, @@ -212,7 +204,7 @@ export async function getIssueDescription( } if (!result) { - throw runtime.logger.error(context.event, "Issue description is empty"); + throw context.logger.error("Issue description is empty"); } return result; @@ -300,8 +292,6 @@ export async function checkUserPermissionForRepoAndOrg(context: Context, usernam } async function checkUserPermissionForRepo(context: Context, username: string): Promise { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; try { const res = await context.event.octokit.rest.repos.checkCollaborator({ @@ -312,14 +302,12 @@ async function checkUserPermissionForRepo(context: Context, username: string): P return res.status === 204; } catch (e: unknown) { - runtime.logger.error(context.event, "Checking if user permisson for repo failed!", e); + context.logger.error("Checking if user permisson for repo failed!", e); return false; } } async function checkUserPermissionForOrg(context: Context, username: string): Promise { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; if (!payload.organization) return false; @@ -331,7 +319,7 @@ async function checkUserPermissionForOrg(context: Context, username: string): Pr // skipping status check due to type error of checkMembershipForUser function of octokit return true; } catch (e: unknown) { - runtime.logger.error(context.event, "Checking if user permisson for org failed!", e); + context.logger.error("Checking if user permisson for org failed!", e); return false; } } @@ -363,9 +351,7 @@ export async function isUserAdminOrBillingManager( } async function checkIfIsBillingManager() { - const runtime = Runtime.getState(); - - if (!payload.organization) throw runtime.logger.error(context.event, `No organization found in payload!`); + if (!payload.organization) throw context.logger.error(`No organization found in payload!`); const { data: membership } = await context.event.octokit.rest.orgs.getMembershipForUser({ org: payload.organization.login, username: payload.repository.owner.login, @@ -381,8 +367,6 @@ export async function isUserAdminOrBillingManager( } export async function addAssignees(context: Context, issue: number, assignees: string[]) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; try { await context.event.octokit.rest.issues.addAssignees({ @@ -392,13 +376,11 @@ export async function addAssignees(context: Context, issue: number, assignees: s assignees, }); } catch (e: unknown) { - runtime.logger.debug(context.event, "Adding assignees failed!", e); + context.logger.debug("Adding assignees failed!", e); } } export async function deleteLabel(context: Context, label: string) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; try { const response = await context.event.octokit.rest.search.issuesAndPullRequests({ @@ -413,16 +395,14 @@ export async function deleteLabel(context: Context, label: string) { }); } } catch (e: unknown) { - runtime.logger.debug(context.event, "Deleting label failed!", e); + context.logger.debug("Deleting label failed!", e); } } export async function removeLabel(context: Context, name: string) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; if (!payload.issue) { - runtime.logger.debug(context.event, "Invalid issue object"); + context.logger.debug("Invalid issue object"); return; } @@ -434,7 +414,7 @@ export async function removeLabel(context: Context, name: string) { name: name, }); } catch (e: unknown) { - runtime.logger.debug(context.event, "Removing label failed!", e); + context.logger.debug("Removing label failed!", e); } } @@ -474,7 +454,6 @@ async function getPullRequests( } export async function closePullRequest(context: Context, pull_number: number) { - const runtime = Runtime.getState(); const payload = context.event.payload as Payload; try { await context.event.octokit.rest.pulls.update({ @@ -484,7 +463,7 @@ export async function closePullRequest(context: Context, pull_number: number) { state: "closed", }); } catch (e: unknown) { - runtime.logger.debug(context.event, "Closing pull requests failed!", e); + context.logger.debug("Closing pull requests failed!", e); } } @@ -517,8 +496,6 @@ async function getPullRequestReviews( page: number, format: "raw" | "html" | "text" | "full" = "raw" ) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; try { const { data: reviews } = await context.event.octokit.rest.pulls.listReviews({ @@ -533,14 +510,12 @@ async function getPullRequestReviews( }); return reviews; } catch (e: unknown) { - runtime.logger.debug(context.event, "Fetching pull request reviews failed!", e); + context.logger.debug("Fetching pull request reviews failed!", e); return []; } } export async function getReviewRequests(context: Context, pull_number: number, owner: string, repo: string) { - const runtime = Runtime.getState(); - try { const response = await context.event.octokit.pulls.listRequestedReviewers({ owner: owner, @@ -549,14 +524,12 @@ export async function getReviewRequests(context: Context, pull_number: number, o }); return response.data; } catch (e: unknown) { - runtime.logger.error(context.event, "Could not get requested reviewers", e); + context.logger.error("Could not get requested reviewers", e); return null; } } // Get issues by issue number export async function getIssueByNumber(context: Context, issueNumber: number) { - const runtime = Runtime.getState(); - const payload = context.event.payload as Payload; try { const { data: issue } = await context.event.octokit.rest.issues.get({ @@ -566,7 +539,7 @@ export async function getIssueByNumber(context: Context, issueNumber: number) { }); return issue; } catch (e: unknown) { - runtime.logger.debug(context.event, "Fetching issue failed!", e); + context.logger.debug("Fetching issue failed!", e); return; } } @@ -659,17 +632,16 @@ export async function getAvailableOpenedPullRequests(context: Context, username: // Strips out all links from the body of an issue or pull request and fetches the conversational context from each linked issue or pull request export async function getAllLinkedIssuesAndPullsInBody(context: Context, issueNumber: number) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const issue = await getIssueByNumber(context, issueNumber); if (!issue) { - throw logger.error(context.event, "No issue found!", { issueNumber }); + throw logger.error("No issue found!", { issueNumber }); } if (!issue.body) { - throw logger.error(context.event, "No body found!", { issueNumber }); + throw logger.error("No body found!", { issueNumber }); } const body = issue.body; @@ -698,7 +670,7 @@ export async function getAllLinkedIssuesAndPullsInBody(context: Context, issueNu } }); } else { - runtime.logger.info(context.event, `No linked issues or prs found`); + logger.info(`No linked issues or prs found`); } if (linkedPrs.length > 0) { @@ -756,7 +728,7 @@ export async function getAllLinkedIssuesAndPullsInBody(context: Context, issueNu linkedPrs: linkedPRStreamlined, }; } else { - runtime.logger.info(context.event, `No matches found`); + logger.info(`No matches found`); return { linkedIssues: [], linkedPrs: [], diff --git a/src/helpers/label.ts b/src/helpers/label.ts index 410e8a8fd..48631e765 100644 --- a/src/helpers/label.ts +++ b/src/helpers/label.ts @@ -1,4 +1,3 @@ -import Runtime from "../bindings/bot-runtime"; import { labelExists } from "../handlers/pricing/pricing-label"; import { calculateTaskPrice } from "../handlers/shared/pricing"; import { calculateLabelValue } from "../helpers"; @@ -10,7 +9,6 @@ const COLORS = { default: "ededed", price: "1f883d" }; // cspell:enable export async function listLabelsForRepo(context: Context): Promise { - const runtime = Runtime.getState(); const payload = context.event.payload as Payload; const res = await context.event.octokit.rest.issues.listLabelsForRepo({ @@ -24,7 +22,7 @@ export async function listLabelsForRepo(context: Context): Promise { return res.data; } - throw runtime.logger.error(context.event, "Failed to fetch lists of labels", { status: res.status }); + throw context.logger.error("Failed to fetch lists of labels", { status: res.status }); } export async function createLabel( @@ -49,8 +47,7 @@ export async function updateLabelsFromBaseRate( labels: Label[], previousBaseRate: number ) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const config = context.config; const newLabels: string[] = []; @@ -84,7 +81,7 @@ export async function updateLabelsFromBaseRate( const labelsFiltered: string[] = labels.map((obj) => obj["name"]); const usedLabels = uniquePreviousLabels.filter((value: string) => labelsFiltered.includes(value)); - logger.debug(context.event, "Got used labels: ", { usedLabels }); + logger.debug("Got used labels: ", { usedLabels }); for (const label of usedLabels) { if (label.startsWith("Price: ")) { @@ -94,7 +91,7 @@ export async function updateLabelsFromBaseRate( const exist = await labelExists(context, uniqueNewLabels[index]); if (exist) { // we have to delete first - logger.debug(context.event, "Label already exists, deleting it", { label }); + logger.debug("Label already exists, deleting it", { label }); await deleteLabel(context, uniqueNewLabels[index]); } @@ -111,7 +108,7 @@ export async function updateLabelsFromBaseRate( }, }); - logger.debug(context.event, "Label updated", { label, to: uniqueNewLabels[index] }); + logger.debug("Label updated", { label, to: uniqueNewLabels[index] }); } } } diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index 49f3f0d74..2f83dfefe 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -1,7 +1,6 @@ import axios from "axios"; import { HTMLElement, parse } from "node-html-parser"; import { getPullByNumber } from "./issue"; -import Runtime from "../bindings/bot-runtime"; import { Context } from "../types"; interface GetLinkedParams { @@ -36,14 +35,14 @@ export async function getLinkedPullRequests( context: Context, { owner, repository, issue }: GetLinkedParams ): Promise { - const logger = Runtime.getState().logger; + const logger = context.logger; const collection = [] as GetLinkedResults[]; const { data } = await axios.get(`https://github.com/${owner}/${repository}/issues/${issue}`); const dom = parse(data); const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; const linkedList = devForm.querySelectorAll(".my-1"); if (linkedList.length === 0) { - logger.info(context.event, `No linked pull requests found`); + context.logger.info(`No linked pull requests found`); return []; } @@ -62,7 +61,7 @@ export async function getLinkedPullRequests( const href = `https://github.com${relativeHref}`; if (`${organization}/${repository}` !== `${owner}/${repository}`) { - logger.info(context.event, "Skipping linked pull request from another repository", href); + logger.info("Skipping linked pull request from another repository", href); continue; } diff --git a/src/helpers/payout.ts b/src/helpers/payout.ts index 91d9de660..eb8d008ca 100644 --- a/src/helpers/payout.ts +++ b/src/helpers/payout.ts @@ -40,8 +40,7 @@ export function getPayoutConfigByNetworkId(evmNetworkId: number) { } export async function hasLabelEditPermission(context: Context, label: string, caller: string) { - const runtime = Runtime.getState(); - const logger = runtime.logger; + const logger = context.logger; const sufficientPrivileges = await isUserAdminOrBillingManager(context, caller); // get text before : @@ -54,7 +53,7 @@ export async function hasLabelEditPermission(context: Context, label: string, ca const userId = await user.getUserId(context.event, caller); const accessible = await access.getAccess(userId); if (accessible) return true; - logger.info(context.event, "No access to edit label", { caller, label }); + logger.info("No access to edit label", { caller, label }); return false; } diff --git a/src/types/context.ts b/src/types/context.ts index f2d6e4bb9..b568ba843 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -1,9 +1,13 @@ -import { Context as ProbotContext } from "probot"; -import { BotConfig } from "./"; +import { Context as ProbotContext, ProbotOctokit } from "probot"; +import { BotConfig, Payload } from "./"; import OpenAI from "openai"; +import { Logs } from "../adapters/supabase"; export interface Context { event: ProbotContext; config: BotConfig; openAi: OpenAI | null; + logger: Logs; + payload: Payload; + octokit: InstanceType; } diff --git a/src/utils/check-github-rate-limit.ts b/src/utils/check-github-rate-limit.ts index 5e26865ac..4da87bace 100644 --- a/src/utils/check-github-rate-limit.ts +++ b/src/utils/check-github-rate-limit.ts @@ -9,7 +9,7 @@ export async function checkRateLimitGit(headers: { "x-ratelimit-remaining"?: str const now = new Date(); const timeToWait = resetTime.getTime() - now.getTime(); const logger = Runtime.getState().logger; - logger.warn(null, "No remaining requests.", { resetTime, now, timeToWait }); + logger.warn("No remaining requests.", { resetTime, now, timeToWait }); await wait(timeToWait); } return remainingRequests; diff --git a/src/utils/generate-configuration.ts b/src/utils/generate-configuration.ts index ae256128d..f13ca6af1 100644 --- a/src/utils/generate-configuration.ts +++ b/src/utils/generate-configuration.ts @@ -46,7 +46,7 @@ export async function generateConfiguration(context: ProbotContext): Promise