From 40005e62a0a99529a7a72b5fe51295f590f12c71 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 19 Nov 2023 23:33:25 +0100 Subject: [PATCH] feat: remove context from addapters and pass it by parameter --- src/adapters/index.ts | 21 +++--- .../supabase/helpers/tables/access.ts | 9 +-- src/adapters/supabase/helpers/tables/label.ts | 7 +- .../supabase/helpers/tables/locations.ts | 10 +-- src/adapters/supabase/helpers/tables/logs.ts | 73 +++++++++---------- .../supabase/helpers/tables/settlement.ts | 5 +- src/adapters/supabase/helpers/tables/super.ts | 5 +- src/adapters/supabase/helpers/tables/user.ts | 11 ++- .../supabase/helpers/tables/wallet.test.ts | 9 +-- .../supabase/helpers/tables/wallet.ts | 10 +-- src/bindings/event.ts | 33 +++++---- src/handlers/access/labels-access.ts | 8 +- src/handlers/assign/action.ts | 22 +++--- src/handlers/assign/auto.ts | 10 +-- src/handlers/comment/action.ts | 12 +-- src/handlers/comment/handlers/ask.ts | 8 +- .../assign/generate-assignment-comment.ts | 6 +- .../assign/get-time-labels-assigned.ts | 6 +- src/handlers/comment/handlers/assign/index.ts | 30 +++++--- src/handlers/comment/handlers/authorize.ts | 11 +-- src/handlers/comment/handlers/first.ts | 4 +- src/handlers/comment/handlers/help.ts | 4 +- .../handlers/issue/allCommentScoring.ts | 3 +- .../handlers/issue/assignee-scoring.ts | 26 ++++--- .../handlers/issue/comment-scoring-rubric.ts | 15 ++-- .../issue/generate-permit-2-signature.ts | 16 ++-- .../handlers/issue/generate-permits.ts | 2 +- .../issue/get-collaborator-ids-for-repo.ts | 2 +- .../handlers/issue/getPullRequestComments.ts | 2 +- .../comment/handlers/issue/issue-closed.ts | 23 +++--- .../handlers/issue/perUserCommentScoring.ts | 12 ++- .../handlers/issue/relevance-scoring.ts | 6 +- .../comment/handlers/issue/scoreSources.ts | 2 +- src/handlers/comment/handlers/labels.ts | 14 ++-- src/handlers/comment/handlers/multiplier.ts | 15 ++-- src/handlers/comment/handlers/payout.ts | 6 +- src/handlers/comment/handlers/query.ts | 10 +-- src/handlers/comment/handlers/unassign.ts | 17 +++-- src/handlers/comment/handlers/wallet.ts | 23 +++--- src/handlers/label/index.ts | 6 +- src/handlers/pricing/action.ts | 2 +- src/handlers/pricing/pre.ts | 6 +- src/handlers/pricing/pricing-label.ts | 24 +++--- src/handlers/processors.ts | 2 +- .../pull-request/create-devpool-pr.ts | 8 +- src/handlers/push/check-modified-base-rate.ts | 6 +- src/handlers/push/index.ts | 12 +-- src/handlers/push/update-base-rate.ts | 8 +- src/handlers/shared/pricing.ts | 10 +-- src/handlers/wildcard/unassign/unassign.ts | 21 +++--- src/helpers/file.ts | 4 +- src/helpers/gpt.ts | 7 +- src/helpers/issue.ts | 42 +++++------ src/helpers/label.ts | 8 +- src/helpers/parser.ts | 13 ++-- src/helpers/payout.ts | 4 +- src/utils/check-github-rate-limit.ts | 4 +- src/utils/generate-configuration.ts | 6 +- 58 files changed, 370 insertions(+), 331 deletions(-) diff --git a/src/adapters/index.ts b/src/adapters/index.ts index bbf63c2e1..d9d057c02 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -1,5 +1,4 @@ import { createClient } from "@supabase/supabase-js"; -import { Context as ProbotContext } from "probot"; import { Access } from "./supabase/helpers/tables/access"; import { Label } from "./supabase/helpers/tables/label"; import { Locations } from "./supabase/helpers/tables/locations"; @@ -13,18 +12,18 @@ import { env } from "../bindings/env"; const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY, { auth: { persistSession: false } }); -export function createAdapters(context: ProbotContext) { +export function createAdapters() { return { supabase: { - access: new Access(supabaseClient, context), - wallet: new Wallet(supabaseClient, context), - user: new User(supabaseClient, context), - debit: new Settlement(supabaseClient, context), - settlement: new Settlement(supabaseClient, context), - label: new Label(supabaseClient, context), - logs: new Logs(supabaseClient, context, env.LOG_ENVIRONMENT, env.LOG_RETRY_LIMIT, env.LOG_LEVEL), - locations: new Locations(supabaseClient, context), - super: new Super(supabaseClient, context), + access: new Access(supabaseClient), + wallet: new Wallet(supabaseClient), + user: new User(supabaseClient), + 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), + 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 dc1ca7a98..80e711536 100644 --- a/src/adapters/supabase/helpers/tables/access.ts +++ b/src/adapters/supabase/helpers/tables/access.ts @@ -4,7 +4,6 @@ import { Database } from "../../types/database"; import { GitHubNode } from "../client"; import { Super } from "./super"; import { UserRow } from "./user"; -import { Context as ProbotContext } from "probot"; type AccessRow = Database["public"]["Tables"]["access"]["Row"]; type AccessInsert = Database["public"]["Tables"]["access"]["Insert"]; type UserWithAccess = (UserRow & { access: AccessRow | null })[]; @@ -19,15 +18,15 @@ type _Access = { }; export class Access extends Super { - constructor(supabase: SupabaseClient, context: ProbotContext) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } private async _getUserWithAccess(id: number): Promise { const { data, error } = await this.supabase.from("access").select("*, users(*)").filter("id", "eq", id); if (error) { - this.runtime.logger.error(error.message, error); + this.runtime.logger.error(null, error.message, error); throw new Error(error.message); } return data; @@ -36,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("Access is undefined"); + this.runtime.logger.debug(null, "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 4f723f650..17d713356 100644 --- a/src/adapters/supabase/helpers/tables/label.ts +++ b/src/adapters/supabase/helpers/tables/label.ts @@ -2,14 +2,13 @@ import { SupabaseClient } from "@supabase/supabase-js"; import { Repository } from "../../../../types/payload"; import { Database } from "../../types"; import { Super } from "./super"; -import { Context as ProbotContext } from "probot"; import Runtime from "../../../../bindings/bot-runtime"; type LabelRow = Database["public"]["Tables"]["labels"]["Row"]; export class Label extends Super { - constructor(supabase: SupabaseClient, context: ProbotContext) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } async saveLabelChange({ @@ -75,7 +74,7 @@ export class Label extends Super { if (locationError) throw new Error(locationError.message); if (!locationData) { - runtime.logger.warn("Repository location ID not found in database."); + runtime.logger.warn(null, "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 7a372d653..94c093675 100644 --- a/src/adapters/supabase/helpers/tables/locations.ts +++ b/src/adapters/supabase/helpers/tables/locations.ts @@ -17,8 +17,8 @@ export class Locations extends Super { node_id: string | undefined; node_type: string | undefined; - constructor(supabase: SupabaseClient, context: ProbotContext) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } public async getLocationsFromRepo(repositoryId: number) { @@ -27,11 +27,11 @@ export class Locations extends Super { .select("id") .eq("repository_id", repositoryId); - if (error) throw this.runtime.logger.error("Error getting location data", new Error(error.message)); + if (error) throw this.runtime.logger.error(null, "Error getting location data", new Error(error.message)); return locationData; } - public async getLocationsMetaData(issueCommentId: string) { + public async getLocationsMetaData(context: ProbotContext, issueCommentId: string) { const graphQlQuery = ` query { node(id: "${issueCommentId}") { @@ -62,7 +62,7 @@ export class Locations extends Super { } `; - this.locationResponse = (await this.context.octokit.graphql(graphQlQuery)) as LocationResponse; + this.locationResponse = (await context.octokit.graphql(graphQlQuery)) as LocationResponse; console.trace(this.locationResponse); this.user_id = this.locationResponse.data.node.author.id; diff --git a/src/adapters/supabase/helpers/tables/logs.ts b/src/adapters/supabase/helpers/tables/logs.ts index eaf3a41dd..1eb2990bd 100644 --- a/src/adapters/supabase/helpers/tables/logs.ts +++ b/src/adapters/supabase/helpers/tables/logs.ts @@ -15,6 +15,7 @@ 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; @@ -48,7 +49,7 @@ export class Logs extends Super { private throttleCount = 0; private retryLimit = 0; // Retries disabled by default - private _log({ level, consoleLog, logMessage, metadata, postComment, type }: _LogParams): LogReturn | null { + private _log({ context, 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. @@ -57,21 +58,17 @@ export class Logs extends Super { // - the comment to post on github (must include diff syntax) // - the comment to post on the console (must be colorized) - if (metadata) { - // metadata = Logs.convertErrorsIntoObjects(metadata); - consoleLog(logMessage, metadata); - if (postComment) { - const colorizedCommentMessage = this._diffColorCommentMessage(type, logMessage); - const commentMetaData = Logs._commentMetaData(metadata, level); - this._postComment([colorizedCommentMessage, commentMetaData].join("\n")); - } - } else { - consoleLog(logMessage); - if (postComment) { - const colorizedCommentMessage = this._diffColorCommentMessage(type, logMessage); - this._postComment(colorizedCommentMessage); - } + consoleLog(logMessage, metadata || null); + + if (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 + ); } + const toSupabase = { log: logMessage, level, metadata } as LogInsert; this._save(toSupabase); @@ -115,9 +112,10 @@ export class Logs extends Super { return metadata; } - public ok(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public ok(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.VERBOSE, consoleLog: prettyLogs.ok, logMessage: log, @@ -127,9 +125,10 @@ export class Logs extends Super { }); } - public info(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public info(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.INFO, consoleLog: prettyLogs.info, logMessage: log, @@ -139,9 +138,10 @@ export class Logs extends Super { }); } - public warn(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public warn(context: ProbotContext | null, 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,9 +151,10 @@ export class Logs extends Super { }); } - public debug(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public debug(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.DEBUG, consoleLog: prettyLogs.debug, logMessage: log, @@ -163,7 +164,7 @@ export class Logs extends Super { }); } - public error(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + public error(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { if (!metadata) { metadata = Logs.convertErrorsIntoObjects(new Error(log)); const stack = metadata.stack as string[]; @@ -179,6 +180,7 @@ export class Logs extends Super { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.ERROR, consoleLog: prettyLogs.error, logMessage: log, @@ -188,9 +190,10 @@ export class Logs extends Super { }); } - http(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + http(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.HTTP, consoleLog: prettyLogs.http, logMessage: log, @@ -200,9 +203,10 @@ export class Logs extends Super { }); } - verbose(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + verbose(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.VERBOSE, consoleLog: prettyLogs.verbose, logMessage: log, @@ -212,9 +216,10 @@ export class Logs extends Super { }); } - silly(log: string, metadata?: any, postComment?: boolean): LogReturn | null { + silly(context: ProbotContext | null, log: string, metadata?: any, postComment?: boolean): LogReturn | null { metadata = this._addDiagnosticInformation(metadata); return this._log({ + context, level: LogLevel.SILLY, consoleLog: prettyLogs.silly, logMessage: log, @@ -224,14 +229,8 @@ export class Logs extends Super { }); } - constructor( - supabase: SupabaseClient, - context: ProbotContext, - environment: string, - retryLimit: number, - logLevel: LogLevel - ) { - super(supabase, context); + constructor(supabase: SupabaseClient, environment: string, retryLimit: number, logLevel: LogLevel) { + super(supabase); this.environment = environment; this.retryLimit = retryLimit; @@ -312,7 +311,7 @@ export class Logs extends Super { } static _commentMetaData(metadata: any, level: LogLevel) { - Runtime.getState().logger.debug("the main place that metadata is being serialized as an html comment"); + Runtime.getState().logger.debug(null, "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 @@ -367,13 +366,13 @@ export class Logs extends Super { return [diffHeader, message, diffFooter].join("\n"); } - private _postComment(message: string) { + private _postComment(context: ProbotContext, message: string) { // post on issue - this.context.octokit.issues + context.octokit.issues .createComment({ - owner: this.context.issue().owner, - repo: this.context.issue().repo, - issue_number: this.context.issue().issue_number, + owner: context.issue().owner, + repo: context.issue().repo, + issue_number: context.issue().issue_number, body: message, }) // .then((x) => console.trace(x)) diff --git a/src/adapters/supabase/helpers/tables/settlement.ts b/src/adapters/supabase/helpers/tables/settlement.ts index bd5f4888d..dad557c30 100644 --- a/src/adapters/supabase/helpers/tables/settlement.ts +++ b/src/adapters/supabase/helpers/tables/settlement.ts @@ -3,7 +3,6 @@ import Decimal from "decimal.js"; import { Comment, Payload } from "../../../../types/payload"; import { Database } from "../../types/database"; import { Super } from "./super"; -import { Context as ProbotContext } from "probot"; type DebitInsert = Database["public"]["Tables"]["debits"]["Insert"]; type CreditInsert = Database["public"]["Tables"]["credits"]["Insert"]; @@ -26,8 +25,8 @@ type AddCreditWithPermit = { }; export class Settlement extends Super { - constructor(supabase: SupabaseClient, context: ProbotContext) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } private async _lookupTokenId(networkId: number, address: string): Promise { diff --git a/src/adapters/supabase/helpers/tables/super.ts b/src/adapters/supabase/helpers/tables/super.ts index 175620561..3f940f5e9 100644 --- a/src/adapters/supabase/helpers/tables/super.ts +++ b/src/adapters/supabase/helpers/tables/super.ts @@ -1,15 +1,12 @@ import { SupabaseClient } from "@supabase/supabase-js"; import Runtime from "../../../../bindings/bot-runtime"; -import { Context as ProbotContext } from "probot"; export class Super { protected supabase: SupabaseClient; protected runtime: Runtime; // convenience accessor - protected context: ProbotContext; - constructor(supabase: SupabaseClient, context: ProbotContext) { + constructor(supabase: SupabaseClient) { this.supabase = supabase; this.runtime = Runtime.getState(); - this.context = context; } } diff --git a/src/adapters/supabase/helpers/tables/user.ts b/src/adapters/supabase/helpers/tables/user.ts index 857348a1c..7829ae420 100644 --- a/src/adapters/supabase/helpers/tables/user.ts +++ b/src/adapters/supabase/helpers/tables/user.ts @@ -5,13 +5,12 @@ import { Context as ProbotContext } from "probot"; export type UserRow = Database["public"]["Tables"]["users"]["Row"]; export class User extends Super { - constructor(supabase: SupabaseClient, context: ProbotContext) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } - public async getUserId(username: string): Promise { - const octokit = this.context.octokit; - const { data } = await octokit.rest.users.getByUsername({ username }); + public async getUserId(context: ProbotContext, username: string): Promise { + const { data } = await context.octokit.rest.users.getByUsername({ username }); return data.id; } @@ -39,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("Error getting access data", accessError); + if (accessError) throw this.runtime.logger.error(null, "Error getting access data", accessError); return accessData; } } diff --git a/src/adapters/supabase/helpers/tables/wallet.test.ts b/src/adapters/supabase/helpers/tables/wallet.test.ts index 72f3bbdc8..ebee5afbe 100644 --- a/src/adapters/supabase/helpers/tables/wallet.test.ts +++ b/src/adapters/supabase/helpers/tables/wallet.test.ts @@ -1,7 +1,6 @@ import dotenv from "dotenv"; dotenv.config(); -import { Context as ProbotContext } from "probot"; import { createAdapters } from "../../.."; import { User } from "../../../../types"; const SUPABASE_URL = process.env.SUPABASE_URL; @@ -9,10 +8,8 @@ if (!SUPABASE_URL) throw new Error("SUPABASE_URL is not defined"); const SUPABASE_KEY = process.env.SUPABASE_KEY; if (!SUPABASE_KEY) throw new Error("SUPABASE_KEY is not defined"); -const mockContext = { supabase: { url: SUPABASE_URL, key: SUPABASE_KEY } } as unknown as ProbotContext; - -async function getWalletAddressAndUrlTest(eventContext: ProbotContext) { - const { wallet } = createAdapters(eventContext).supabase; +async function getWalletAddressAndUrlTest() { + const { wallet } = createAdapters().supabase; const userId = 4975670 as User["id"]; const results = [] as unknown[]; try { @@ -26,4 +23,4 @@ async function getWalletAddressAndUrlTest(eventContext: ProbotContext) { console.trace(results); } -void getWalletAddressAndUrlTest(mockContext); +void getWalletAddressAndUrlTest(); diff --git a/src/adapters/supabase/helpers/tables/wallet.ts b/src/adapters/supabase/helpers/tables/wallet.ts index 871eb4acd..2e87b5353 100644 --- a/src/adapters/supabase/helpers/tables/wallet.ts +++ b/src/adapters/supabase/helpers/tables/wallet.ts @@ -16,8 +16,8 @@ type IssueCommentPayload = | ProbotContext<"issue_comment.edited">["payload"]; export class Wallet extends Super { - constructor(supabase: SupabaseClient, context: ProbotContext) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } public async getAddress(id: number): Promise { @@ -25,8 +25,8 @@ export class Wallet extends Super { return this._validateAndGetWalletAddress(userWithWallet); } - public async upsertWalletAddress(address: string) { - const payload = this.context.payload as + public async upsertWalletAddress(context: ProbotContext, address: string) { + const payload = context.payload as | ProbotContext<"issue_comment.created">["payload"] | ProbotContext<"issue_comment.edited">["payload"]; @@ -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("Enriching wallet location metadata", locationMetaData); + logger.ok(null, "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 ff6ad4bc4..73a2ab637 100644 --- a/src/bindings/event.ts +++ b/src/bindings/event.ts @@ -35,17 +35,17 @@ const validatePayload = ajv.compile(PayloadSchema); export async function bindEvents(eventContext: ProbotContext) { const runtime = Runtime.getState(); - runtime.adapters = createAdapters(eventContext); + runtime.adapters = createAdapters(); runtime.logger = runtime.adapters.supabase.logs; const payload = eventContext.payload as Payload; const eventName = payload?.action ? `${eventContext.name}.${payload?.action}` : eventContext.name; // some events wont have actions as this grows - runtime.logger.info("Event received", { id: eventContext.id, name: eventName }); + runtime.logger.info(eventContext, "Event received", { id: eventContext.id, name: eventName }); if (!allowedEvents.includes(eventName)) { // just check if its on the watch list - return runtime.logger.info(`Skipping the event. reason: not configured`); + return runtime.logger.info(eventContext, `Skipping the event. reason: not configured`); } // Skip validation for installation event and push @@ -53,13 +53,13 @@ export async function bindEvents(eventContext: ProbotContext) { // Validate payload const valid = validatePayload(payload); if (!valid && validatePayload.errors) { - return runtime.logger.error("Payload schema validation failed!", validatePayload.errors); + return runtime.logger.error(eventContext, "Payload schema validation failed!", validatePayload.errors); } // Check if we should skip the event const should = shouldSkip(eventContext); if (should.stop) { - return runtime.logger.info("Skipping the event.", { reason: should.reason }); + return runtime.logger.info(eventContext, "Skipping the event.", { reason: should.reason }); } } @@ -80,7 +80,7 @@ export async function bindEvents(eventContext: ProbotContext) { }; if (!context.config.keys.evmPrivateEncrypted) { - runtime.logger.warn("No EVM private key found"); + runtime.logger.warn(eventContext, "No EVM private key found"); } if (!runtime.logger) { @@ -91,7 +91,7 @@ export async function bindEvents(eventContext: ProbotContext) { const handlers = processors[eventName]; if (!handlers) { - return runtime.logger.warn("No handler configured for event:", { eventName }); + return runtime.logger.warn(eventContext, "No handler configured for event:", { eventName }); } const { pre, action, post } = handlers; @@ -106,6 +106,7 @@ export async function bindEvents(eventContext: ProbotContext) { const functionNames = handlerWithType.actions.map((action) => action?.name); runtime.logger.info( + eventContext, `Running "${handlerWithType.type}" \ for event: "${eventName}". \ handlers: "${functionNames.join(", ")}"` @@ -116,11 +117,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("Skipping wildcard handlers for event:", eventName); + return runtime.logger.info(eventContext, "Skipping wildcard handlers for event:", eventName); } else { // Run wildcard handlers const functionNames = wildcardProcessors.map((action) => action?.name); - runtime.logger.info(`Running wildcard handlers: "${functionNames.join(", ")}"`); + runtime.logger.info(eventContext, `Running wildcard handlers: "${functionNames.join(", ")}"`); const wildCardHandlerType: WildCardHandlerWithType = { type: "wildcard", actions: wildcardProcessors }; await logAnyReturnFromHandlers(context, wildCardHandlerType); } @@ -138,7 +139,7 @@ async function logAnyReturnFromHandlers(context: Context, handlerType: AllHandle await renderMainActionOutput(context, response, action); } else { const runtime = Runtime.getState(); - runtime.logger.ok("Completed", { action: action.name, type: handlerType.type }); + runtime.logger.ok(context.event, "Completed", { action: action.name, type: handlerType.type }); } } catch (report: unknown) { await renderCatchAllWithContext(report); @@ -173,9 +174,10 @@ async function renderMainActionOutput( } else if (typeof response == "string") { await addCommentToIssue(context, response, issueNumber); } else if (response === null) { - runtime.logger.debug("null response", { action: action.name }); + runtime.logger.debug(context.event, "null response", { action: action.name }); } else { runtime.logger.error( + context.event, "No response from action. Ensure return of string, null, or LogReturn object", { action: action.name }, true @@ -189,7 +191,7 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType const payload = context.event.payload as Payload; const issue = payload.issue; if (!issue) { - return runtime.logger.error("Issue is null. Skipping", { issue }); + return runtime.logger.error(context.event, "Issue is null. Skipping", { issue }); } if (report instanceof LogReturn) { @@ -197,7 +199,10 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType const { logMessage } = report; if (report.metadata) { - runtime.logger.debug("this is the second place that metadata is being serialized as an html comment"); + runtime.logger.debug( + context.event, + "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 @@ -221,6 +226,7 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType }; return runtime.logger.error( + context.event, "action has an uncaught error", { logReturn: report, handlerType, activeHandler: activeHandler.name, error }, true @@ -237,6 +243,7 @@ function createRenderCatchAll(context: Context, handlerType: AllHandlersWithType // report as SupabaseError return runtime.logger.error( + context.event, "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 46e7dab35..838e3868b 100644 --- a/src/handlers/access/labels-access.ts +++ b/src/handlers/access/labels-access.ts @@ -28,17 +28,17 @@ export async function labelAccessPermissionsCheck(context: Context) { const labelType = match[0].toLowerCase(); if (sufficientPrivileges) { - logger.info("Admin and billing managers have full control over all labels", { + logger.info(context.event, "Admin and billing managers have full control over all labels", { repo: repo.full_name, user: sender, labelType, }); return true; } else { - logger.info("Checking access for labels", { repo: repo.full_name, user: sender, labelType }); + logger.info(context.event, "Checking access for labels", { repo: repo.full_name, user: sender, labelType }); // check permission const { access, user } = runtime.adapters.supabase; - const userId = await user.getUserId(sender); + const userId = await user.getUserId(context.event, sender); const accessible = await access.getAccess(userId); if (accessible) { return true; @@ -58,7 +58,7 @@ export async function labelAccessPermissionsCheck(context: Context) { `@${sender}, You are not allowed to ${eventName} ${labelName}`, payload.issue.number ); - logger.info("No access to edit label", { sender, label: labelName }); + logger.info(context.event, "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 d7a92ae1c..059b4841d 100644 --- a/src/handlers/assign/action.ts +++ b/src/handlers/assign/action.ts @@ -9,14 +9,14 @@ export async function startCommandHandler(context: Context) { const logger = runtime.logger; const payload = context.event.payload as Payload; if (!payload.issue) { - return logger.error("Issue is not defined"); + return logger.error(context.event, "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("No assignees"); + return logger.warn(context.event, "No assignees"); } // Flatten assignees into a string @@ -27,7 +27,7 @@ export async function startCommandHandler(context: Context) { // If no labels exist, log a debug message and return if (!labels) { - return logger.warn(`No labels to calculate timeline`); + return logger.warn(context.event, `No labels to calculate timeline`); } // Filter out labels that match the time labels defined in the config @@ -38,7 +38,7 @@ export async function startCommandHandler(context: Context) { ); if (timeLabelsAssigned.length == 0) { - return logger.debug("No labels to calculate timeline"); + return logger.debug(context.event, "No labels to calculate timeline"); } // Sort labels by weight and select the one with the smallest weight @@ -68,11 +68,11 @@ export async function startCommandHandler(context: Context) { // Format the commit message const commitMessage = `${flattenedAssignees} the deadline is at ${endDate.toISOString()}`; - logger.debug("Creating an issue comment", { commitMessage }); + logger.debug(context.event, "Creating an issue comment", { commitMessage }); // Add the commit message as a comment to the issue // await addCommentToIssue(commitMessage, payload.issue?.number); - return logger.info(commitMessage); + return logger.info(context.event, commitMessage); } export async function closePullRequestForAnIssue(context: Context) { @@ -80,25 +80,25 @@ export async function closePullRequestForAnIssue(context: Context) { const logger = runtime.logger; const payload = context.event.payload as Payload; if (!payload.issue?.number) { - throw logger.error("Issue is not defined"); + throw logger.error(context.event, "Issue is not defined"); } - const linkedPullRequests = await getLinkedPullRequests({ + const linkedPullRequests = await getLinkedPullRequests(context, { owner: payload.repository.owner.login, repository: payload.repository.name, issue: payload.issue.number, }); if (!linkedPullRequests.length) { - return logger.info(`No linked pull requests to close`); + return logger.info(context.event, `No linked pull requests to close`); } - logger.info(`Opened prs`, linkedPullRequests); + logger.info(context.event, `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(comment); + return logger.info(context.event, comment); // await addCommentToIssue(comment, payload.issue.number); } diff --git a/src/handlers/assign/auto.ts b/src/handlers/assign/auto.ts index 06db07b37..3b8ed8147 100644 --- a/src/handlers/assign/auto.ts +++ b/src/handlers/assign/auto.ts @@ -10,7 +10,7 @@ export async function checkPullRequests(context: Context) { const pulls = await getAllPullRequests(context); if (pulls.length === 0) { - return logger.debug(`No pull requests found at this time`); + return logger.debug(context.event, `No pull requests found at this time`); } const payload = context.event.payload as Payload; @@ -31,7 +31,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("It's an updated Pull Request, reverting"); + logger.debug(context.event, "It's an updated Pull Request, reverting"); continue; } @@ -45,19 +45,19 @@ export async function checkPullRequests(context: Context) { // if issue is already assigned, continue if (issue.assignees.length > 0) { - logger.debug(`Issue already assigned, ignoring...`); + logger.debug(context.event, `Issue already assigned, ignoring...`); continue; } const assignedUsernames = issue.assignees.map((assignee) => assignee.login); if (!assignedUsernames.includes(opener)) { await addAssignees(context, +linkedIssueNumber, [opener]); - logger.debug("Assigned pull request opener to issue", { + logger.debug(context.event, "Assigned pull request opener to issue", { pullRequest: pull.number, issue: linkedIssueNumber, opener, }); } } - return logger.debug(`Checking pull requests done!`); + return logger.debug(context.event, `Checking pull requests done!`); } diff --git a/src/handlers/comment/action.ts b/src/handlers/comment/action.ts index ab4ac995d..c1fa3729a 100644 --- a/src/handlers/comment/action.ts +++ b/src/handlers/comment/action.ts @@ -15,11 +15,11 @@ export async function commentCreatedOrEdited(context: Context) { const commentedCommand = commentParser(body); if (!comment) { - logger.info(`Comment is null. Skipping`); + logger.info(context.event, `Comment is null. Skipping`); } const issue = payload.issue; if (!issue) { - throw logger.error("Issue is null. Skipping", { issue }); + throw logger.error(context.event, "Issue is null. Skipping", { issue }); } if (commentedCommand) { @@ -31,17 +31,19 @@ export async function commentCreatedOrEdited(context: Context) { if (userCommand) { const { id, handler } = userCommand; - logger.info("Running a comment handler", { id, handler: handler.name }); + logger.info(context.event, "Running a comment handler", { id, handler: handler.name }); const disabled = config.disabledCommands.some((command) => command === id.replace("/", "")); if (disabled && id !== "/help") { - return logger.warn("Skipping because it is disabled on this repo.", { id }); + return logger.warn(context.event, "Skipping because it is disabled on this repo.", { id }); } return await handler(context, body); } else { const sanitizedBody = body.replace(//g, ""); - return logger.verbose("Comment event received without a recognized user command.", { sanitizedBody }); + return logger.verbose(context.event, "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 fc63460c7..bb5f28f1b 100644 --- a/src/handlers/comment/handlers/ask.ts +++ b/src/handlers/comment/handlers/ask.ts @@ -38,7 +38,7 @@ export async function ask(context: Context, body: string) { const commentsRaw = await getAllIssueComments(context, issue.number, "raw"); if (!comments) { - throw logger.error(`Error getting issue comments`); + throw logger.error(context.event, `Error getting issue comments`); } // add the first comment of the issue/pull request @@ -61,7 +61,7 @@ export async function ask(context: Context, body: string) { const links = await getAllLinkedIssuesAndPullsInBody(context, issue.number); if (typeof links === "string") { - logger.info("Error getting linked issues or prs: ", links); + logger.info(context.event, "Error getting linked issues or prs: ", links); } else { linkedIssueStreamlined = links.linkedIssues; linkedPRStreamlined = links.linkedPrs; @@ -117,9 +117,9 @@ export async function ask(context: Context, body: string) { } else if (gptResponse.answer) { return gptResponse.answer; } else { - throw logger.error("Error getting response from OpenAI"); + throw logger.error(context.event, "Error getting response from OpenAI"); } } else { - return logger.warn("Invalid syntax for ask. usage: '/ask What is pi?'"); + return logger.warn(context.event, "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 2f028d4d2..3fc172c67 100644 --- a/src/handlers/comment/handlers/assign/generate-assignment-comment.ts +++ b/src/handlers/comment/handlers/assign/generate-assignment-comment.ts @@ -1,5 +1,5 @@ import Runtime from "../../../../bindings/bot-runtime"; -import { Payload } from "../../../../types"; +import { Context, Payload } from "../../../../types"; const options: Intl.DateTimeFormatOptions = { weekday: "short", @@ -11,7 +11,7 @@ const options: Intl.DateTimeFormatOptions = { timeZoneName: "short", }; -export async function generateAssignmentComment(payload: Payload, duration: number | null = null) { +export async function generateAssignmentComment(context: Context, payload: Payload, duration: number | null = null) { const runtime = Runtime.getState(); const startTime = new Date().getTime(); let endTime: null | Date = null; @@ -24,7 +24,7 @@ export async function generateAssignmentComment(payload: Payload, duration: numb const issueCreationTime = payload.issue?.created_at; if (!issueCreationTime) { const logger = Runtime.getState().logger; - throw logger.error("Issue creation time is not defined"); + throw logger.error(context.event, "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 332ffe482..450f24bd8 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,12 @@ import Runtime from "../../../../bindings/bot-runtime"; -import { BotConfig, Label, Payload } from "../../../../types"; +import { BotConfig, Context, Label, Payload } from "../../../../types"; -export function getTimeLabelsAssigned(payload: Payload, config: BotConfig) { +export function getTimeLabelsAssigned(context: Context, payload: Payload, config: BotConfig) { const runtime = Runtime.getState(); const logger = runtime.logger; const labels = payload.issue?.labels; if (!labels?.length) { - logger.warn("Skipping '/start' since no labels are set to calculate the timeline", { labels }); + logger.warn(context.event, "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 75165c947..28828d493 100644 --- a/src/handlers/comment/handlers/assign/index.ts +++ b/src/handlers/comment/handlers/assign/index.ts @@ -28,46 +28,48 @@ export async function assign(context: Context, body: string) { const startDisabled = disabledCommands.some((command) => command === "start"); - logger.info("Received '/start' command", { sender: payload.sender.login, body }); + logger.info(context.event, "Received '/start' command", { sender: payload.sender.login, body }); if (!issue) { - throw logger.warn(`Skipping '/start' because of no issue instance`); + throw logger.warn(context.event, `Skipping '/start' because of no issue instance`); } if (startDisabled) { - throw logger.warn("The `/assign` command is disabled for this repository."); + throw logger.warn(context.event, "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("Max issue allowed is", maxConcurrentTasks); + logger.info(context.event, "Max issue allowed is", maxConcurrentTasks); // check for max and enforce max if (assignedIssues.length - openedPullRequests.length >= maxConcurrentTasks) { - throw logger.warn("Too many assigned issues, you have reached your max limit", { + throw logger.warn(context.event, "Too many assigned issues, you have reached your max limit", { maxConcurrentTasks, }); } if (issue.state == IssueType.CLOSED) { - throw logger.warn("Skipping '/start' since the issue is closed"); + throw logger.warn(context.event, "Skipping '/start' since the issue is closed"); } const assignees: User[] = (payload.issue?.assignees ?? []).filter(Boolean) as User[]; if (assignees.length !== 0) { - throw logger.warn("Skipping '/start' since the issue is already assigned"); + throw logger.warn(context.event, "Skipping '/start' since the issue is already assigned"); } // ==== preamble checks completed ==== // @@ -77,26 +79,30 @@ export async function assign(context: Context, body: string) { let duration: number | null = null; if (!priceLabel) { - throw logger.warn("No price label is set, so this is not ready to be self assigned yet.", priceLabel); + throw logger.warn( + context.event, + "No price label is set, so this is not ready to be self assigned yet.", + priceLabel + ); } else { - const timeLabelsAssigned = getTimeLabelsAssigned(payload, config); + const timeLabelsAssigned = getTimeLabelsAssigned(context, payload, config); if (timeLabelsAssigned) { duration = calculateDurations(timeLabelsAssigned).shift() || null; } } - const comment = await generateAssignmentComment(payload, duration); + const comment = await generateAssignmentComment(context, payload, duration); const metadata = structuredMetadata.create("Assignment", { duration, priceLabel }); if (!assignees.map((i) => i.login).includes(payload.sender.login)) { - logger.info("Adding the assignee", { assignee: payload.sender.login }); + logger.info(context.event, "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("Creating an issue comment", { comment }); + logger.info(context.event, "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 2d1874f5d..3e38cb153 100644 --- a/src/handlers/comment/handlers/authorize.ts +++ b/src/handlers/comment/handlers/authorize.ts @@ -10,11 +10,11 @@ export async function authorizeLabelChanges(context: Context) { const payload = context.event.payload as Payload; const sender = payload.sender.login; - logger.info("Running '/authorize' command handler", { sender }); + logger.info(context.event, "Running '/authorize' command handler", { sender }); const { issue, repository } = payload; if (!issue) { - return logger.info(`Skipping '/authorize' because of no issue instance`); + return logger.info(context.event, `Skipping '/authorize' because of no issue instance`); } // check if sender is admin @@ -24,6 +24,7 @@ export async function authorizeLabelChanges(context: Context) { // if sender is not admin, return if (sufficientPrivileges) { throw runtime.logger.error( + context.event, "User is not an admin/billing_manager and do not have the required permissions to access this function.", { sender } ); @@ -32,7 +33,7 @@ export async function authorizeLabelChanges(context: Context) { const task = taskPaymentMetaData(context, issue); if (!task.priceLabel || !task.priorityLabel || !task.timeLabel) { - throw runtime.logger.error("Missing required labels", { issueDetailed: task }); + throw runtime.logger.error(context.event, "Missing required labels", { issueDetailed: task }); } // get current repository node id from payload and pass it to getLabelChanges function to get label changes @@ -42,9 +43,9 @@ export async function authorizeLabelChanges(context: Context) { // Approve label changes labelChanges.forEach(async (labelChange) => { await label.approveLabelChange(labelChange.id); - return logger.info("Approved label change", { labelChange }); + return logger.info(context.event, "Approved label change", { labelChange }); }); } - return runtime.logger.ok("Label change has been approved, permit can now be generated"); + return runtime.logger.ok(context.event, "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 2d35985dc..7ac5b0e32 100644 --- a/src/handlers/comment/handlers/first.ts +++ b/src/handlers/comment/handlers/first.ts @@ -6,7 +6,7 @@ export async function verifyFirstCommentInRepository(context: Context) { const runtime = Runtime.getState(); const payload = context.event.payload as Payload; if (!payload.issue) { - throw runtime.logger.error("Issue is null. Skipping", { issue: payload.issue }, true); + throw runtime.logger.error(context.event, "Issue is null. Skipping", { issue: payload.issue }, true); } const { features: { @@ -36,5 +36,5 @@ export async function verifyFirstCommentInRepository(context: Context) { // await upsertCommentToIssue(payload.issue.number, msg, payload.action, payload.comment); } } - return runtime.logger.info(`Skipping first comment`); + return runtime.logger.info(context.event, `Skipping first comment`); } diff --git a/src/handlers/comment/handlers/help.ts b/src/handlers/comment/handlers/help.ts index 3e1afb617..90b6783ac 100644 --- a/src/handlers/comment/handlers/help.ts +++ b/src/handlers/comment/handlers/help.ts @@ -6,13 +6,13 @@ export async function listAvailableCommands(context: Context, body: string) { const runtime = Runtime.getState(); const logger = runtime.logger; if (body != "/help") { - return logger.info("Skipping to list available commands.", { body }); + return logger.info(context.event, "Skipping to list available commands.", { body }); } const payload = context.event.payload as Payload; const issue = payload.issue; if (!issue) { - return logger.info("Skipping /help, reason: not issue"); + return logger.info(context.event, "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 3d42f1a2f..655487cef 100644 --- a/src/handlers/comment/handlers/issue/allCommentScoring.ts +++ b/src/handlers/comment/handlers/issue/allCommentScoring.ts @@ -26,7 +26,7 @@ export async function allCommentScoring({ const selection = usersByClass[contributionStyle as keyof typeof usersByClass]; if (!selection) { - Runtime.getState().logger.verbose(`No ${String(contributionStyle)} found`); + Runtime.getState().logger.verbose(context.event, `No ${String(contributionStyle)} found`); return []; } @@ -38,6 +38,7 @@ export async function allCommentScoring({ return []; } perUserCommentScoring( + context, user, commentsOfRole.filter((comment) => comment.user.id === user.id), scoring diff --git a/src/handlers/comment/handlers/issue/assignee-scoring.ts b/src/handlers/comment/handlers/issue/assignee-scoring.ts index 458ae0bb4..f0bdf721e 100644 --- a/src/handlers/comment/handlers/issue/assignee-scoring.ts +++ b/src/handlers/comment/handlers/issue/assignee-scoring.ts @@ -3,19 +3,23 @@ import Runtime from "../../../../bindings/bot-runtime"; import { Issue, User } from "../../../../types/payload"; import { ContributorView } from "./contribution-style-types"; import { UserScoreDetails } from "./issue-shared-types"; +import { Context } from "../../../../types"; -export async function assigneeScoring({ - issue, - source, - view, -}: { - issue: Issue; - source: User[]; - view: ContributorView; -}): Promise { +export async function assigneeScoring( + context: Context, + { + issue, + source, + view, + }: { + issue: Issue; + source: User[]; + view: ContributorView; + } +): Promise { // get the price label const priceLabels = issue.labels.filter((label) => label.name.startsWith("Price: ")); - if (!priceLabels) throw Runtime.getState().logger.warn("Price label is undefined"); + if (!priceLabels) throw Runtime.getState().logger.warn(context.event, "Price label is undefined"); // get the smallest price label const priceLabel = priceLabels @@ -28,7 +32,7 @@ export async function assigneeScoring({ ?.shift(); if (!priceLabel) { - throw Runtime.getState().logger.warn("Price label is undefined"); + throw Runtime.getState().logger.warn(context.event, "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 087431ea8..93a7d69fe 100644 --- a/src/handlers/comment/handlers/issue/comment-scoring-rubric.ts +++ b/src/handlers/comment/handlers/issue/comment-scoring-rubric.ts @@ -7,6 +7,7 @@ import Runtime from "../../../../bindings/bot-runtime"; import { Comment } from "../../../../types/payload"; import { ContributorClassesKeys } from "./contribution-style-types"; import { FormatScoreConfig, FormatScoreConfigParams } from "./element-score-config"; +import { Context } from "../../../../types"; export type Tags = keyof HTMLElementTagNameMap; @@ -188,7 +189,7 @@ export class CommentScoring { return wordCount; } - public computeElementScore(comment: Comment, userId: number) { + public computeElementScore(context: Context, comment: Comment, userId: number) { const htmlString = this._getRenderedCommentBody(comment); const formatStatistics = _.mapValues(_.cloneDeep(this._formatConfig), () => ({ count: 0, @@ -215,7 +216,7 @@ export class CommentScoring { } } - this._initialize(comment, userId); + this._initialize(context, comment, userId); // Store the element score for the comment this.commentScores[userId].details[comment.id].formatScoreComment = totalElementScore; this.commentScores[userId].details[comment.id].formatScoreCommentDetails = formatStatistics; @@ -223,9 +224,9 @@ export class CommentScoring { return htmlString; } - private _initialize(comment: Comment, userId: number) { + private _initialize(context: Context, comment: Comment, userId: number) { if (!this.commentScores[userId]) { - Runtime.getState().logger.debug("good thing we initialized, was unsure if necessary"); + Runtime.getState().logger.debug(context.event, "good thing we initialized, was unsure if necessary"); const initialCommentScoreValue = { totalScoreTotal: ZERO, wordScoreTotal: ZERO, @@ -235,7 +236,7 @@ export class CommentScoring { this.commentScores[userId] = { ...initialCommentScoreValue }; } if (!this.commentScores[userId].details[comment.id]) { - Runtime.getState().logger.debug("good thing we initialized, was unsure if necessary"); + Runtime.getState().logger.debug(context.event, "good thing we initialized, was unsure if necessary"); this.commentScores[userId].details[comment.id] = { totalScoreComment: ZERO, relevanceScoreComment: ZERO, @@ -248,11 +249,11 @@ export class CommentScoring { } } - public computeWordScore(comment: Comment, userId: number) { + public computeWordScore(context: Context, comment: Comment, userId: number) { const words = this._getWordsNotInDisabledElements(comment); const wordScoreDetails = this._calculateWordScores(words); - this._initialize(comment, userId); + this._initialize(context, comment, userId); this.commentScores[userId].details[comment.id].comment = comment; this.commentScores[userId].details[comment.id].wordScoreComment = this._calculateWordScoresTotals(wordScoreDetails); this.commentScores[userId].details[comment.id].wordScoreCommentDetails = wordScoreDetails; 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 73dd1e03b..54437264b 100644 --- a/src/handlers/comment/handlers/issue/generate-permit-2-signature.ts +++ b/src/handlers/comment/handlers/issue/generate-permit-2-signature.ts @@ -16,26 +16,26 @@ export async function generatePermit2Signature( payments: { evmNetworkId }, keys: { evmPrivateEncrypted }, } = context.config; - if (!evmPrivateEncrypted) throw runtime.logger.warn("No bot wallet private key defined"); + if (!evmPrivateEncrypted) throw runtime.logger.warn(context.event, "No bot wallet private key defined"); const { rpc, paymentToken } = getPayoutConfigByNetworkId(evmNetworkId); const { privateKey } = await decryptKeys(evmPrivateEncrypted); - if (!rpc) throw runtime.logger.error("RPC is not defined"); - if (!privateKey) throw runtime.logger.error("Private key is not defined"); - if (!paymentToken) throw runtime.logger.error("Payment token is not defined"); + 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"); let provider; let adminWallet; try { provider = new ethers.providers.JsonRpcProvider(rpc); } catch (error) { - throw runtime.logger.debug("Failed to instantiate provider", error); + throw runtime.logger.debug(context.event, "Failed to instantiate provider", error); } try { adminWallet = new ethers.Wallet(privateKey, provider); } catch (error) { - throw runtime.logger.debug("Failed to instantiate wallet", error); + throw runtime.logger.debug(context.event, "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("Failed to sign typed data", error); + throw runtime.logger.debug(context.event, "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("Generated permit2 signature", { transactionData, url: url.toString() }); + runtime.logger.info(context.event, "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 dadd0de73..ba2f6dd36 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("No bot wallet private key defined"); + if (!evmPrivateEncrypted) throw runtime.logger.warn(context.event, "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 7022c1898..2bbaf268e 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 @@ -26,7 +26,7 @@ export async function getCollaboratorsForRepo(context: Context): Promise } } } catch (e: unknown) { - runtime.logger.error("Fetching collaborator IDs for repo failed!", e); + runtime.logger.error(context.event, "Fetching collaborator IDs for repo failed!", e); } return collaboratorUsers; diff --git a/src/handlers/comment/handlers/issue/getPullRequestComments.ts b/src/handlers/comment/handlers/issue/getPullRequestComments.ts index 29e71e357..f0831d258 100644 --- a/src/handlers/comment/handlers/issue/getPullRequestComments.ts +++ b/src/handlers/comment/handlers/issue/getPullRequestComments.ts @@ -5,7 +5,7 @@ import { Comment } from "../../../../types/payload"; export async function getPullRequestComments(context: Context, owner: string, repository: string, issueNumber: number) { const pullRequestComments: Comment[] = []; - const linkedPullRequests = await getLinkedPullRequests({ owner, repository, issue: issueNumber }); + const linkedPullRequests = await getLinkedPullRequests(context, { owner, repository, issue: issueNumber }); if (linkedPullRequests.length) { const linkedCommentsPromises = linkedPullRequests.map((pull) => getAllIssueComments(context, pull.number)); const linkedCommentsResolved = await Promise.all(linkedCommentsPromises); diff --git a/src/handlers/comment/handlers/issue/issue-closed.ts b/src/handlers/comment/handlers/issue/issue-closed.ts index de932df5c..7155e020c 100644 --- a/src/handlers/comment/handlers/issue/issue-closed.ts +++ b/src/handlers/comment/handlers/issue/issue-closed.ts @@ -49,10 +49,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("Issue is not defined"); + if (!issue) throw runtime.logger.error(context.event, "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("Owner is not defined"); + if (!owner) throw logger.error(context.event, "Owner is not defined"); const repository = payload?.repository?.name; const issueNumber = issue.number; return { issue, runtime, logger, issueComments, owner, repository, issueNumber }; @@ -68,25 +68,30 @@ interface PreflightChecksParams { context: Context; } async function preflightChecks({ issue, logger, issueComments, config, payload, context }: PreflightChecksParams) { - if (!issue) throw logger.error("Permit generation skipped because issue is undefined"); + if (!issue) throw logger.error(context.event, "Permit generation skipped because issue is undefined"); if (issue.state_reason !== StateReason.COMPLETED) - throw logger.info("Issue was not closed as completed. Skipping.", { issue }); + throw logger.info(context.event, "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("Permit generation disabled because this issue has been closed by an external contributor."); + throw logger.warn( + context.event, + "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("No price label has been set. Skipping permit generation.", { labels: issue.labels }); + throw logger.warn(context.event, "No price label has been set. Skipping permit generation.", { + labels: issue.labels, + }); } const botComments = issueComments.filter(botCommentsFilter); - checkIfPermitsAlreadyPosted(botComments, logger); + checkIfPermitsAlreadyPosted(context, botComments, logger); } -function checkIfPermitsAlreadyPosted(botComments: Comment[], logger: Logs) { +function checkIfPermitsAlreadyPosted(context: Context, botComments: Comment[], logger: Logs) { botComments.forEach((comment) => { const parsed = structuredMetadata.parse(comment.body); if (parsed) { @@ -94,7 +99,7 @@ function checkIfPermitsAlreadyPosted(botComments: Comment[], logger: Logs) { if (parsed.caller === "generatePermits") { // in the comment metadata we store what function rendered the comment console.trace({ parsed }); - throw logger.warn("Permit already posted"); + throw logger.warn(context.event, "Permit already posted"); } } }); diff --git a/src/handlers/comment/handlers/issue/perUserCommentScoring.ts b/src/handlers/comment/handlers/issue/perUserCommentScoring.ts index dd50c6114..64e007c15 100644 --- a/src/handlers/comment/handlers/issue/perUserCommentScoring.ts +++ b/src/handlers/comment/handlers/issue/perUserCommentScoring.ts @@ -1,10 +1,16 @@ +import { Context } from "../../../../types"; import { Comment, User } from "../../../../types/payload"; import { CommentScoring } from "./comment-scoring-rubric"; -export function perUserCommentScoring(user: User, comments: Comment[], scoringRubric: CommentScoring): CommentScoring { +export function perUserCommentScoring( + context: Context, + user: User, + comments: Comment[], + scoringRubric: CommentScoring +): CommentScoring { for (const comment of comments) { - scoringRubric.computeWordScore(comment, user.id); - scoringRubric.computeElementScore(comment, user.id); + scoringRubric.computeWordScore(context, comment, user.id); + scoringRubric.computeElementScore(context, comment, user.id); } scoringRubric.compileTotalUserScores(); return scoringRubric; diff --git a/src/handlers/comment/handlers/issue/relevance-scoring.ts b/src/handlers/comment/handlers/issue/relevance-scoring.ts index d6d735f2c..a79f96a68 100644 --- a/src/handlers/comment/handlers/issue/relevance-scoring.ts +++ b/src/handlers/comment/handlers/issue/relevance-scoring.ts @@ -102,7 +102,7 @@ async function sampleRelevanceScores( issue, maxConcurrency: BATCH_SIZE, }); - const filteredSamples = filterSamples(fetchedSamples, correctLength); + const filteredSamples = filterSamples(context, fetchedSamples, correctLength); const averagedSample = averageSamples(filteredSamples, 10); batchSamples.push(averagedSample); } @@ -132,10 +132,10 @@ interface InEachRequestParams { maxConcurrency: number; } -function filterSamples(batchResults: number[][], correctLength: number) { +function filterSamples(context: Context, batchResults: number[][], correctLength: number) { return batchResults.filter((result) => { if (result.length != correctLength) { - Runtime.getState().logger.error("Correct length is not defined", { + Runtime.getState().logger.error(context.event, "Correct length is not defined", { batchResultsLength: batchResults.length, result, }); diff --git a/src/handlers/comment/handlers/issue/scoreSources.ts b/src/handlers/comment/handlers/issue/scoreSources.ts index 3d070376b..b4d4a19b6 100644 --- a/src/handlers/comment/handlers/issue/scoreSources.ts +++ b/src/handlers/comment/handlers/issue/scoreSources.ts @@ -17,7 +17,7 @@ export async function aggregateAndScoreContributions({ }: ScoreParams): Promise { const issueIssuerSpecification = await issuerSpecificationScoring({ context, issue, view: "Issue" }); - const issueAssigneeTask = await assigneeTaskScoring({ + const issueAssigneeTask = await assigneeTaskScoring(context, { issue, source: issue.assignees.filter((assignee): assignee is User => Boolean(assignee)), view: "Issue", diff --git a/src/handlers/comment/handlers/labels.ts b/src/handlers/comment/handlers/labels.ts index 6b4a893e7..a082fe775 100644 --- a/src/handlers/comment/handlers/labels.ts +++ b/src/handlers/comment/handlers/labels.ts @@ -10,9 +10,12 @@ export async function setLabels(context: Context, body: string) { const sufficientPrivileges = await isUserAdminOrBillingManager(context, sender); if (!sufficientPrivileges) - 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 + 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 - if (!payload.issue) return logger.info(`Skipping '/labels' because of no issue instance`); + if (!payload.issue) return logger.info(context.event, `Skipping '/labels' because of no issue instance`); if (body.startsWith("/labels")) { const { username, labels } = parseComment(body); @@ -26,14 +29,15 @@ export async function setLabels(context: Context, body: string) { node_url: url, }; - const userId = await user.getUserId(username); + const userId = await user.getUserId(context.event, username); await access.setAccess(labels, nodeInfo, userId); if (!labels.length) { - return logger.ok("Successfully cleared access", { username }); + return logger.ok(context.event, "Successfully cleared access", { username }); } - return logger.ok("Successfully set access", { username, labels }); + return logger.ok(context.event, "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 122afeb97..40035e968 100644 --- a/src/handlers/comment/handlers/multiplier.ts +++ b/src/handlers/comment/handlers/multiplier.ts @@ -19,10 +19,10 @@ export async function multiplier(context: Context, body: string) { const sender = payload.sender.login; const repo = payload.repository; const comment = payload.comment; - if (!comment) return logger.info(`Skipping '/multiplier' because of no comment instance`); + if (!comment) return logger.info(context.event, `Skipping '/multiplier' because of no comment instance`); const issue = payload.issue; - logger.info("Running '/multiplier' command handler", { sender }); - if (!issue) return logger.info(`Skipping '/multiplier' because of no issue instance`); + logger.info(context.event, "Running '/multiplier' command handler", { sender }); + if (!issue) return logger.info(context.event, `Skipping '/multiplier' because of no issue instance`); const regex = /(".*?"|[^"\s]+)(?=\s*|\s*$)/g; const matches = body.match(regex); matches?.shift(); @@ -48,7 +48,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("Getting multiplier access", { + logger.info(context.event, "Getting multiplier access", { repo: repo.full_name, user: sender, }); @@ -62,6 +62,7 @@ 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, @@ -70,13 +71,14 @@ export async function multiplier(context: Context, body: string) { ); } } - logger.info("Upserting to the wallet table", { username, taskMultiplier, reason }); + logger.info(context.event, "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 \ @@ -89,7 +91,7 @@ export async function multiplier(context: Context, body: string) { } ); } else { - return logger.ok("Successfully changed the payout multiplier", { + return logger.ok(context.event, "Successfully changed the payout multiplier", { username, taskMultiplier, reason, @@ -97,6 +99,7 @@ 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 c4ae4ff8e..221a9f565 100644 --- a/src/handlers/comment/handlers/payout.ts +++ b/src/handlers/comment/handlers/payout.ts @@ -7,7 +7,7 @@ export async function autoPay(context: Context, body: string) { const payload = context.event.payload as Payload; const logger = runtime.logger; - logger.info("Running '/autopay' command handler", { sender: payload.sender.login }); + logger.info(context.event, "Running '/autopay' command handler", { sender: payload.sender.login }); const pattern = /^\/autopay (true|false)$/; const autopayCommand = body.match(pattern); @@ -16,12 +16,14 @@ 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("Automatic payment for this issue state:", { autopayCommand }); + return logger.ok(context.event, "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 ff783dbd0..93207fc72 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -8,24 +8,24 @@ export async function query(context: Context, body: string) { payload = context.event.payload as Payload, sender = payload.sender.login; - logger.info("Running '/query' command handler", { sender }); + logger.info(context.event, "Running '/query' command handler", { sender }); const issue = payload.issue; - if (!issue) return logger.info(`Skipping '/query' because of no issue instance`); + if (!issue) return logger.info(context.event, `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("Invalid body for query command \n usage /query @user"); + throw logger.error(context.event, "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("User not found", { username }); + throw logger.error(context.event, "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("No access or wallet found for user", { username }); + return logger.warn(context.event, "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 493ea44b3..232fb6a29 100644 --- a/src/handlers/comment/handlers/unassign.ts +++ b/src/handlers/comment/handlers/unassign.ts @@ -6,24 +6,24 @@ export async function unassign(context: Context, body: string) { const runtime = Runtime.getState(); const logger = runtime.logger; if (!body.startsWith("/stop")) { - return logger.error("Skipping to unassign", { body }); + return logger.error(context.event, "Skipping to unassign", { body }); } const payload = context.event.payload as Payload; - logger.info("Running '/stop' command handler", { sender: payload.sender.login }); + logger.info(context.event, "Running '/stop' command handler", { sender: payload.sender.login }); const issue = payload.issue; if (!issue) { - return logger.info(`Skipping '/stop' because of no issue instance`); + return logger.info(context.event, `Skipping '/stop' because of no issue instance`); } const issueNumber = issue.number; const assignees = payload.issue?.assignees ?? []; if (assignees.length == 0) { - return logger.warn("No assignees found for issue", { issueNumber }); + return logger.warn(context.event, "No assignees found for issue", { issueNumber }); } const shouldUnassign = assignees[0]?.login.toLowerCase() == payload.sender.login.toLowerCase(); - logger.debug("Unassigning sender", { + logger.debug(context.event, "Unassigning sender", { sender: payload.sender.login.toLowerCase(), assignee: assignees[0]?.login.toLowerCase(), shouldUnassign, @@ -39,7 +39,10 @@ export async function unassign(context: Context, body: string) { issue_number: issueNumber, assignees: [payload.sender.login], }); - return logger.ok("You have been unassigned from the task", { issueNumber, user: payload.sender.login }); + return logger.ok(context.event, "You have been unassigned from the task", { + issueNumber, + user: payload.sender.login, + }); } - return logger.warn("You are not assigned to this task", { issueNumber, user: payload.sender.login }); + return logger.warn(context.event, "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 a92c1e47e..7f8563011 100644 --- a/src/handlers/comment/handlers/wallet.ts +++ b/src/handlers/comment/handlers/wallet.ts @@ -30,38 +30,39 @@ export async function registerWallet(context: Context, body: string) { const ensName = extractEnsName(body.replace("/wallet", "").trim()); if (!address && ensName) { - logger.info("Trying to resolve address from ENS name", { ensName }); + logger.info(context.event, "Trying to resolve address from ENS name", { ensName }); address = await resolveAddress(ensName); if (!address) { - throw logger.error("Resolving address from ENS name failed", { ensName }); + throw logger.error(context.event, "Resolving address from ENS name failed", { ensName }); } - logger.ok("Resolved address from ENS name", { ensName, address }); + logger.ok(context.event, "Resolved address from ENS name", { ensName, address }); } if (!address) { - return logger.info("Skipping to register a wallet address because both address/ens doesn't exist"); + return logger.info(context.event, "Skipping to register a wallet address because both address/ens doesn't exist"); } if (config.miscellaneous.registerWalletWithVerification) { - _registerWalletWithVerification(body, address, logger); + _registerWalletWithVerification(context, body, address, logger); } 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" ); } if (payload.comment) { const { wallet } = runtime.adapters.supabase; - await wallet.upsertWalletAddress(address); - return logger.ok("Successfully registered wallet address", { sender, address }); + await wallet.upsertWalletAddress(context.event, address); + return logger.ok(context.event, "Successfully registered wallet address", { sender, address }); } else { throw new Error("Payload comment is undefined"); } } -function _registerWalletWithVerification(body: string, address: string, logger: Logs) { +function _registerWalletWithVerification(context: Context, body: string, address: string, logger: Logs) { const regexForSigHash = /(0x[a-fA-F0-9]{130})/g; const sigHashMatches = body.match(regexForSigHash); const sigHash = sigHashMatches ? sigHashMatches[0] : null; @@ -72,10 +73,10 @@ function _registerWalletWithVerification(body: string, address: string, logger: const isSigHashValid = sigHash && ethers.utils.verifyMessage(messageToSign, sigHash) == ethers.utils.getAddress(address); if (!isSigHashValid) { - throw logger.error(failedSigLogMsg); + throw logger.error(context.event, failedSigLogMsg); } } catch (e) { - logger.error("Exception thrown by verifyMessage for /wallet: ", e); - throw logger.error(failedSigLogMsg); + logger.error(context.event, "Exception thrown by verifyMessage for /wallet: ", e); + throw logger.error(context.event, failedSigLogMsg); } } diff --git a/src/handlers/label/index.ts b/src/handlers/label/index.ts index 932bf08bc..cd102f48a 100644 --- a/src/handlers/label/index.ts +++ b/src/handlers/label/index.ts @@ -11,13 +11,13 @@ export async function watchLabelChange(context: Context) { const previousLabel = changes?.name?.from; if (!previousLabel) { - throw logger.error("previous label name is undefined"); + throw logger.error(context.event, "previous label name is undefined"); } const currentLabel = label?.name; const triggerUser = sender.login; if (!previousLabel || !currentLabel) { - return logger.debug("No label name change.. skipping"); + return logger.debug(context.event, "No label name change.. skipping"); } // check if user is authorized to make the change @@ -31,5 +31,5 @@ export async function watchLabelChange(context: Context) { authorized: hasAccess, repository: payload.repository, }); - return logger.debug("label name change saved to db"); + return logger.debug(context.event, "label name change saved to db"); } diff --git a/src/handlers/pricing/action.ts b/src/handlers/pricing/action.ts index 1b9f8b3e4..d53ef2ec6 100644 --- a/src/handlers/pricing/action.ts +++ b/src/handlers/pricing/action.ts @@ -8,7 +8,7 @@ export async function handleParentIssue(context: Context, labels: Label[]) { if (issuePrices.length) { await clearAllPriceLabelsOnIssue(context); } - throw runtime.logger.warn("Pricing is disabled on parent issues."); + throw runtime.logger.warn(context.event, "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 1650589a6..debf5deb7 100644 --- a/src/handlers/pricing/pre.ts +++ b/src/handlers/pricing/pre.ts @@ -16,7 +16,7 @@ export async function syncPriceLabelsToConfig(context: Context) { } = config; if (!assistivePricing) { - logger.info(`Assistive pricing is disabled`); + logger.info(context.event, `Assistive pricing is disabled`); return; } @@ -44,8 +44,8 @@ export async function syncPriceLabelsToConfig(context: Context) { // Create missing labels if (missingLabels.length > 0) { - logger.info("Missing labels found, creating them", { missingLabels }); + logger.info(context.event, "Missing labels found, creating them", { missingLabels }); await Promise.all(missingLabels.map((label) => createLabel(context, label))); - logger.info(`Creating missing labels done`); + logger.info(context.event, `Creating missing labels done`); } } diff --git a/src/handlers/pricing/pricing-label.ts b/src/handlers/pricing/pricing-label.ts index 2817f4253..24c316e86 100644 --- a/src/handlers/pricing/pricing-label.ts +++ b/src/handlers/pricing/pricing-label.ts @@ -10,7 +10,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const config = context.config; const logger = runtime.logger; const payload = context.event.payload as Payload; - if (!payload.issue) throw logger.error("Issue is not defined"); + if (!payload.issue) throw logger.error(context.event, "Issue is not defined"); const labels = payload.issue.labels; const labelNames = labels.map((i) => i.name); @@ -22,19 +22,19 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const permission = await labelAccessPermissionsCheck(context); if (!permission) { if (config.features.publicAccessControl.setLabel === false) { - throw logger.warn("No public access control to set labels"); + throw logger.warn(context.event, "No public access control to set labels"); } - throw logger.warn("No permission to set labels"); + throw logger.warn(context.event, "No permission to set labels"); } const { assistivePricing } = config.features; - if (!labels) throw logger.warn(`No labels to calculate price`); + if (!labels) throw logger.warn(context.event, `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("This is setting the price label directly so skipping the rest of the action."); + logger.info(context.event, "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 +59,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const recognizedLabels = getRecognizedLabels(labels, config); if (!recognizedLabels.time.length || !recognizedLabels.priority.length) { - logger.warn("No recognized labels to calculate price"); + logger.warn(context.event, "No recognized labels to calculate price"); await clearAllPriceLabelsOnIssue(context); return; } @@ -67,7 +67,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const minLabels = getMinLabels(recognizedLabels); if (!minLabels.time || !minLabels.priority) { - logger.warn("No label to calculate price"); + logger.warn(context.event, "No label to calculate price"); return; } @@ -77,7 +77,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { await handleTargetPriceLabel(context, targetPriceLabel, labelNames, assistivePricing); } else { await clearAllPriceLabelsOnIssue(context); - logger.info(`Skipping action...`); + logger.info(context.event, `Skipping action...`); } } @@ -120,13 +120,13 @@ async function handleTargetPriceLabel( async function handleExistingPriceLabel(context: Context, targetPriceLabel: string, assistivePricing: boolean) { const logger = Runtime.getState().logger; let labeledEvents = await getAllLabeledEvents(context); - if (!labeledEvents) return logger.warn("No labeled events found"); + if (!labeledEvents) return logger.warn(context.event, "No labeled events found"); labeledEvents = labeledEvents.filter((event) => event.label?.name.includes("Price")); - if (!labeledEvents.length) return logger.warn("No price labeled events found"); + if (!labeledEvents.length) return logger.warn(context.event, "No price labeled events found"); if (labeledEvents[labeledEvents.length - 1].actor?.type == UserType.User) { - logger.info(`Skipping... already exists`); + logger.info(context.event, `Skipping... already exists`); } else { await addPriceLabelToIssue(context, targetPriceLabel, assistivePricing); } @@ -138,7 +138,7 @@ async function addPriceLabelToIssue(context: Context, targetPriceLabel: string, const exists = await labelExists(context, targetPriceLabel); if (assistivePricing && !exists) { - logger.info("Assistive pricing is enabled, creating label...", { targetPriceLabel }); + logger.info(context.event, "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 dc77a4944..0b15f7284 100644 --- a/src/handlers/processors.ts +++ b/src/handlers/processors.ts @@ -29,7 +29,7 @@ export const processors: Record = { }, [GitHubEvent.ISSUES_REOPENED]: { pre: [], - action: [async () => runtime.logger.debug("TODO: replace ISSUES_REOPENED handler")], + action: [async () => runtime.logger.debug(null, "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 ad5df1774..e1d38be97 100644 --- a/src/handlers/pull-request/create-devpool-pr.ts +++ b/src/handlers/pull-request/create-devpool-pr.ts @@ -10,12 +10,12 @@ export async function createDevPoolPR(context: Context) { const devPoolRepo = "devpool-directory"; if (!payload.repositories_added) { - return logger.info("No repositories added"); + return logger.info(context.event, "No repositories added"); } const repository = payload.repositories_added[0]; - logger.info("New Install: ", { repository: repository.full_name }); + logger.info(context.event, "New Install: ", { repository: repository.full_name }); const [owner, repo] = repository.full_name.split("/"); @@ -58,7 +58,7 @@ export async function createDevPoolPR(context: Context) { sha: mainSha, }); - logger.info("Branch created on DevPool Directory"); + logger.info(context.event, "Branch created on DevPool Directory"); await context.event.octokit.repos.createOrUpdateFileContents({ owner: devPoolOwner, @@ -79,5 +79,5 @@ export async function createDevPoolPR(context: Context) { base: baseRef, }); - return logger.info("Pull request created on DevPool Directory"); + return logger.info(context.event, "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 2b6cfb571..573d9d511 100644 --- a/src/handlers/push/check-modified-base-rate.ts +++ b/src/handlers/push/check-modified-base-rate.ts @@ -11,14 +11,14 @@ export async function checkModifiedBaseRate(context: Context) { // if zero sha, push is a pr change if (payload.before === ZERO_SHA) { - logger.debug("Skipping push events, not a master write"); + logger.debug(context.event, "Skipping push events, not a master write"); } const changes = getCommitChanges(payload.commits); // skip if empty if (changes && changes.length === 0) { - logger.debug("Skipping push events, file change empty 1"); + logger.debug(context.event, "Skipping push events, file change empty 1"); } // check for modified or added files and check for specified file @@ -26,5 +26,5 @@ export async function checkModifiedBaseRate(context: Context) { // update base rate await updateBaseRate(context, BASE_RATE_FILE); } - logger.debug("Skipping push events, file change empty 2"); + logger.debug(context.event, "Skipping push events, file change empty 2"); } diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index b87f8074b..dd07ea195 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("Skipping push events, not a branch"); + logger.debug(context, "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("Skipping push events, file change empty 3"); + logger.debug(context, "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("Skipping push events, commit sha not found"); + logger.debug(context, "Skipping push events, commit sha not found"); return; } @@ -82,14 +82,14 @@ export async function validateConfigChange(context: ProbotContext) { } if (errorMsg) { - logger.info("Config validation failed!", errorMsg); + logger.info(context, "Config validation failed!", errorMsg); await createCommitComment(context, errorMsg, commitSha, BASE_RATE_FILE); } else { - logger.debug(`Config validation passed!`); + logger.debug(context, `Config validation passed!`); } } } else { - logger.debug(`Skipping push events, file change doesn't include config file: ${JSON.stringify(changes)}`); + logger.debug(context, `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 92df860df..dfd143a26 100644 --- a/src/handlers/push/update-base-rate.ts +++ b/src/handlers/push/update-base-rate.ts @@ -17,26 +17,26 @@ export async function updateBaseRate(context: Context, filePath: string) { const previousFileContent = await getPreviousFileContent(context, owner, repo, branch, filePath); if (!previousFileContent) { - throw logger.error("Getting previous file content failed"); + throw logger.error(context.event, "Getting previous file content failed"); } const previousConfigRaw = Buffer.from(previousFileContent, "base64").toString(); const previousConfigParsed = parseYaml(previousConfigRaw); if (!previousConfigParsed || !previousConfigParsed.payments.basePriceMultiplier) { - throw logger.warn("No multiplier found in previous config"); + throw logger.warn(context.event, "No multiplier found in previous config"); } const previousBaseRate = previousConfigParsed.payments.basePriceMultiplier; if (!previousBaseRate) { - throw logger.warn("No base rate found in previous config"); + throw logger.warn(context.event, "No base rate found in previous config"); } // fetch all labels const repoLabels = await listLabelsForRepo(context); if (repoLabels.length === 0) { - throw logger.warn("No labels on this repo"); + throw logger.warn(context.event, "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 0f2df4dcb..04a706bbc 100644 --- a/src/handlers/shared/pricing.ts +++ b/src/handlers/shared/pricing.ts @@ -19,19 +19,19 @@ export function setPrice(context: Context, timeLabel: Label, priorityLabel: Labe const logger = runtime.logger; const { labels } = context.config; - if (!timeLabel || !priorityLabel) throw logger.warn("Time or priority label is not defined"); + if (!timeLabel || !priorityLabel) throw logger.warn(context.event, "Time or priority label is not defined"); const recognizedTimeLabels = labels.time.find((configLabel) => configLabel === timeLabel.name); - if (!recognizedTimeLabels) throw logger.warn("Time label is not recognized"); + if (!recognizedTimeLabels) throw logger.warn(context.event, "Time label is not recognized"); const recognizedPriorityLabels = labels.priority.find((configLabel) => configLabel === priorityLabel.name); - if (!recognizedPriorityLabels) throw logger.warn("Priority label is not recognized"); + if (!recognizedPriorityLabels) throw logger.warn(context.event, "Priority label is not recognized"); const timeValue = calculateLabelValue(recognizedTimeLabels); - if (!timeValue) throw logger.warn("Time value is not defined"); + if (!timeValue) throw logger.warn(context.event, "Time value is not defined"); const priorityValue = calculateLabelValue(recognizedPriorityLabels); - if (!priorityValue) throw logger.warn("Priority value is not defined"); + if (!priorityValue) throw logger.warn(context.event, "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 57a6d171d..bbc1d9ca8 100644 --- a/src/handlers/wildcard/unassign/unassign.ts +++ b/src/handlers/wildcard/unassign/unassign.ts @@ -17,7 +17,7 @@ export async function checkTasksToUnassign(context: Context) { const tasksToUnassign = await Promise.all( assignedIssues.map(async (assignedIssue: Issue) => checkTaskToUnassign(context, assignedIssue)) ); - logger.ok("Checked all the tasks to unassign", { + logger.ok(context.event, "Checked all the tasks to unassign", { tasksToUnassign: tasksToUnassign.filter(Boolean).map((task) => task?.metadata), }); } @@ -30,10 +30,10 @@ async function checkTaskToUnassign(context: Context, assignedIssue: Issue) { timers: { taskDisqualifyDuration, taskFollowUpDuration }, } = context.config; - logger.info("Checking for neglected tasks", { issueNumber: assignedIssue.number }); + logger.info(context.event, "Checking for neglected tasks", { issueNumber: assignedIssue.number }); if (!assignedIssue.assignees) { - throw logger.error("No assignees found when there are supposed to be assignees.", { + throw logger.error(context.event, "No assignees found when there are supposed to be assignees.", { issueNumber: assignedIssue.number, }); } @@ -110,7 +110,10 @@ async function checkTaskToUnassign(context: Context, assignedIssue: Issue) { taskDisqualifyDuration, }); - return logger.ok("Checked task to unassign", { issueNumber: assignedIssue.number, disqualifiedAssignees }); + return logger.ok(context.event, "Checked task to unassign", { + issueNumber: assignedIssue.number, + disqualifiedAssignees, + }); } async function followUpWithTheRest( @@ -153,9 +156,9 @@ async function followUpWithTheRest( issue_number: number, body: followUpMessage, }); - logger.info("Followed up with idle assignees", { followUpAssignees }); + logger.info(context.event, "Followed up with idle assignees", { followUpAssignees }); } catch (e: unknown) { - logger.error("Failed to follow up with idle assignees", e); + logger.error(context.event, "Failed to follow up with idle assignees", e); } } } @@ -194,7 +197,7 @@ async function aggregateAssigneeActivity({ context, login, name, number, assigne // check the linked pull request and then check that pull request's commits - const linkedPullRequests = await getLinkedPullRequests({ owner: login, repository: name, issue: number }); + const linkedPullRequests = await getLinkedPullRequests(context, { owner: login, repository: name, issue: number }); const allCommits = [] as Commit[]; for (const pullRequest of linkedPullRequests) { @@ -239,9 +242,9 @@ async function disqualifyIdleAssignees( issue_number: number, assignees: idleAssignees, }); - logger.info("Unassigned idle assignees", { idleAssignees }); + logger.info(context.event, "Unassigned idle assignees", { idleAssignees }); } catch (e: unknown) { - logger.error("Failed to unassign idle assignees", e); + logger.error(context.event, "Failed to unassign idle assignees", e); } } return idleAssignees; diff --git a/src/helpers/file.ts b/src/helpers/file.ts index 5071e1db4..2aa7f5555 100644 --- a/src/helpers/file.ts +++ b/src/helpers/file.ts @@ -63,7 +63,7 @@ export async function getPreviousFileContent( } return null; } catch (error: unknown) { - logger.debug("Error retrieving previous file content.", { error }); + logger.debug(context.event, "Error retrieving previous file content.", { error }); return null; } } @@ -122,7 +122,7 @@ export async function getFileContent( } return null; } catch (error: unknown) { - logger.debug("Error retrieving file content.", { error }); + logger.debug(context, "Error retrieving file content.", { error }); return null; } } diff --git a/src/helpers/gpt.ts b/src/helpers/gpt.ts index f151a0099..d0d40cddc 100644 --- a/src/helpers/gpt.ts +++ b/src/helpers/gpt.ts @@ -77,7 +77,7 @@ export async function decideContextGPT( const commentsRaw = await getAllIssueComments(context, issue.number, "raw"); if (!comments) { - logger.info(`Error getting issue comments`); + logger.info(context.event, `Error getting issue comments`); return `Error getting issue comments`; } @@ -101,7 +101,7 @@ export async function decideContextGPT( const links = await getAllLinkedIssuesAndPullsInBody(context, issue.number); if (typeof links === "string") { - return logger.info("Error getting linked issues or prs: ", { links }); + return logger.info(context.event, "Error getting linked issues or prs: ", { links }); } linkedIssueStreamlined = links.linkedIssues; @@ -140,6 +140,7 @@ export async function askGPT(context: Context, chatHistory: CreateChatCompletion 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." ); } @@ -164,7 +165,7 @@ export async function askGPT(context: Context, chatHistory: CreateChatCompletion }; if (!res) { - throw logger.error("Error getting GPT response", { res }); + throw logger.error(context.event, "Error getting GPT response", { res }); } return { answer, tokenUsage }; diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index 7386c44f0..619819d95 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -75,7 +75,7 @@ export async function clearAllPriceLabelsOnIssue(context: Context) { name: issuePrices[0].name, }); // } catch (e: unknown) { - // runtime.logger.debug("Clearing all price labels failed!", e); + // runtime.logger.debug(context.event, "Clearing all price labels failed!", e); // } } @@ -84,7 +84,7 @@ export async function addLabelToIssue(context: Context, labelName: string) { const payload = context.event.payload as Payload; if (!payload.issue) { - throw runtime.logger.error("Issue object is null"); + throw runtime.logger.error(context.event, "Issue object is null"); } try { @@ -95,7 +95,7 @@ export async function addLabelToIssue(context: Context, labelName: string) { labels: [labelName], }); } catch (e: unknown) { - runtime.logger.debug("Adding a label to issue failed!", e); + runtime.logger.debug(context.event, "Adding a label to issue failed!", e); } } @@ -167,7 +167,7 @@ export async function addCommentToIssue(context: Context, message: HandlerReturn body: comment, }); } catch (e: unknown) { - runtime.logger.error("Adding a comment failed!", e); + runtime.logger.error(context.event, "Adding a comment failed!", e); } } @@ -180,7 +180,7 @@ export async function upsertLastCommentToIssue(context: Context, issue_number: n if (comments.length > 0 && comments[comments.length - 1].body !== commentBody) await addCommentToIssue(context, commentBody, issue_number); } catch (e: unknown) { - runtime.logger.debug("Upserting last comment failed!", e); + runtime.logger.debug(context.event, "Upserting last comment failed!", e); } } @@ -212,7 +212,7 @@ export async function getIssueDescription( } if (!result) { - throw runtime.logger.error("Issue description is empty"); + throw runtime.logger.error(context.event, "Issue description is empty"); } return result; @@ -312,7 +312,7 @@ async function checkUserPermissionForRepo(context: Context, username: string): P return res.status === 204; } catch (e: unknown) { - runtime.logger.error("Checking if user permisson for repo failed!", e); + runtime.logger.error(context.event, "Checking if user permisson for repo failed!", e); return false; } } @@ -331,7 +331,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("Checking if user permisson for org failed!", e); + runtime.logger.error(context.event, "Checking if user permisson for org failed!", e); return false; } } @@ -365,7 +365,7 @@ export async function isUserAdminOrBillingManager( async function checkIfIsBillingManager() { const runtime = Runtime.getState(); - if (!payload.organization) throw runtime.logger.error(`No organization found in payload!`); + if (!payload.organization) throw runtime.logger.error(context.event, `No organization found in payload!`); const { data: membership } = await context.event.octokit.rest.orgs.getMembershipForUser({ org: payload.organization.login, username: payload.repository.owner.login, @@ -392,7 +392,7 @@ export async function addAssignees(context: Context, issue: number, assignees: s assignees, }); } catch (e: unknown) { - runtime.logger.debug("Adding assignees failed!", e); + runtime.logger.debug(context.event, "Adding assignees failed!", e); } } @@ -413,7 +413,7 @@ export async function deleteLabel(context: Context, label: string) { }); } } catch (e: unknown) { - runtime.logger.debug("Deleting label failed!", e); + runtime.logger.debug(context.event, "Deleting label failed!", e); } } @@ -422,7 +422,7 @@ export async function removeLabel(context: Context, name: string) { const payload = context.event.payload as Payload; if (!payload.issue) { - runtime.logger.debug("Invalid issue object"); + runtime.logger.debug(context.event, "Invalid issue object"); return; } @@ -434,7 +434,7 @@ export async function removeLabel(context: Context, name: string) { name: name, }); } catch (e: unknown) { - runtime.logger.debug("Removing label failed!", e); + runtime.logger.debug(context.event, "Removing label failed!", e); } } @@ -484,7 +484,7 @@ export async function closePullRequest(context: Context, pull_number: number) { state: "closed", }); } catch (e: unknown) { - runtime.logger.debug("Closing pull requests failed!", e); + runtime.logger.debug(context.event, "Closing pull requests failed!", e); } } @@ -533,7 +533,7 @@ async function getPullRequestReviews( }); return reviews; } catch (e: unknown) { - runtime.logger.debug("Fetching pull request reviews failed!", e); + runtime.logger.debug(context.event, "Fetching pull request reviews failed!", e); return []; } } @@ -549,7 +549,7 @@ export async function getReviewRequests(context: Context, pull_number: number, o }); return response.data; } catch (e: unknown) { - runtime.logger.error("Could not get requested reviewers", e); + runtime.logger.error(context.event, "Could not get requested reviewers", e); return null; } } @@ -566,7 +566,7 @@ export async function getIssueByNumber(context: Context, issueNumber: number) { }); return issue; } catch (e: unknown) { - runtime.logger.debug("Fetching issue failed!", e); + runtime.logger.debug(context.event, "Fetching issue failed!", e); return; } } @@ -665,11 +665,11 @@ export async function getAllLinkedIssuesAndPullsInBody(context: Context, issueNu const issue = await getIssueByNumber(context, issueNumber); if (!issue) { - throw logger.error("No issue found!", { issueNumber }); + throw logger.error(context.event, "No issue found!", { issueNumber }); } if (!issue.body) { - throw logger.error("No body found!", { issueNumber }); + throw logger.error(context.event, "No body found!", { issueNumber }); } const body = issue.body; @@ -698,7 +698,7 @@ export async function getAllLinkedIssuesAndPullsInBody(context: Context, issueNu } }); } else { - runtime.logger.info(`No linked issues or prs found`); + runtime.logger.info(context.event, `No linked issues or prs found`); } if (linkedPrs.length > 0) { @@ -756,7 +756,7 @@ export async function getAllLinkedIssuesAndPullsInBody(context: Context, issueNu linkedPrs: linkedPRStreamlined, }; } else { - runtime.logger.info(`No matches found`); + runtime.logger.info(context.event, `No matches found`); return { linkedIssues: [], linkedPrs: [], diff --git a/src/helpers/label.ts b/src/helpers/label.ts index a43650c2a..410e8a8fd 100644 --- a/src/helpers/label.ts +++ b/src/helpers/label.ts @@ -24,7 +24,7 @@ export async function listLabelsForRepo(context: Context): Promise { return res.data; } - throw runtime.logger.error("Failed to fetch lists of labels", { status: res.status }); + throw runtime.logger.error(context.event, "Failed to fetch lists of labels", { status: res.status }); } export async function createLabel( @@ -84,7 +84,7 @@ export async function updateLabelsFromBaseRate( const labelsFiltered: string[] = labels.map((obj) => obj["name"]); const usedLabels = uniquePreviousLabels.filter((value: string) => labelsFiltered.includes(value)); - logger.debug("Got used labels: ", { usedLabels }); + logger.debug(context.event, "Got used labels: ", { usedLabels }); for (const label of usedLabels) { if (label.startsWith("Price: ")) { @@ -94,7 +94,7 @@ export async function updateLabelsFromBaseRate( const exist = await labelExists(context, uniqueNewLabels[index]); if (exist) { // we have to delete first - logger.debug("Label already exists, deleting it", { label }); + logger.debug(context.event, "Label already exists, deleting it", { label }); await deleteLabel(context, uniqueNewLabels[index]); } @@ -111,7 +111,7 @@ export async function updateLabelsFromBaseRate( }, }); - logger.debug("Label updated", { label, to: uniqueNewLabels[index] }); + logger.debug(context.event, "Label updated", { label, to: uniqueNewLabels[index] }); } } } diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index 8a364b254..49f3f0d74 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -32,11 +32,10 @@ export async function getLinkedIssues({ owner, repository, pull }: GetLinkedPara return issueUrl; } -export async function getLinkedPullRequests({ - owner, - repository, - issue, -}: GetLinkedParams): Promise { +export async function getLinkedPullRequests( + context: Context, + { owner, repository, issue }: GetLinkedParams +): Promise { const logger = Runtime.getState().logger; const collection = [] as GetLinkedResults[]; const { data } = await axios.get(`https://github.com/${owner}/${repository}/issues/${issue}`); @@ -44,7 +43,7 @@ export async function getLinkedPullRequests({ const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; const linkedList = devForm.querySelectorAll(".my-1"); if (linkedList.length === 0) { - logger.info(`No linked pull requests found`); + logger.info(context.event, `No linked pull requests found`); return []; } @@ -63,7 +62,7 @@ export async function getLinkedPullRequests({ const href = `https://github.com${relativeHref}`; if (`${organization}/${repository}` !== `${owner}/${repository}`) { - logger.info("Skipping linked pull request from another repository", href); + logger.info(context.event, "Skipping linked pull request from another repository", href); continue; } diff --git a/src/helpers/payout.ts b/src/helpers/payout.ts index 2db964916..91d9de660 100644 --- a/src/helpers/payout.ts +++ b/src/helpers/payout.ts @@ -51,10 +51,10 @@ export async function hasLabelEditPermission(context: Context, label: string, ca if (sufficientPrivileges) { // check permission const { access, user } = Runtime.getState().adapters.supabase; - const userId = await user.getUserId(caller); + const userId = await user.getUserId(context.event, caller); const accessible = await access.getAccess(userId); if (accessible) return true; - logger.info("No access to edit label", { caller, label }); + logger.info(context.event, "No access to edit label", { caller, label }); return false; } diff --git a/src/utils/check-github-rate-limit.ts b/src/utils/check-github-rate-limit.ts index 2b2e65320..5e26865ac 100644 --- a/src/utils/check-github-rate-limit.ts +++ b/src/utils/check-github-rate-limit.ts @@ -1,5 +1,7 @@ import Runtime from "../bindings/bot-runtime"; + const wait = (ms: number) => new Promise((r) => setTimeout(r, ms)); + export async function checkRateLimitGit(headers: { "x-ratelimit-remaining"?: string; "x-ratelimit-reset"?: string }) { const remainingRequests = headers["x-ratelimit-remaining"] ? parseInt(headers["x-ratelimit-remaining"]) : 0; if (remainingRequests === 0) { @@ -7,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("No remaining requests.", { resetTime, now, timeToWait }); + logger.warn(null, "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 f13ca6af1..ae256128d 100644 --- a/src/utils/generate-configuration.ts +++ b/src/utils/generate-configuration.ts @@ -46,7 +46,7 @@ export async function generateConfiguration(context: ProbotContext): Promise