diff --git a/.eslintrc.json b/.eslintrc.json index 9ef5ac7b1f..234af75290 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -114,7 +114,8 @@ "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/require-await": "off", "@typescript-eslint/await-thenable": "off", - "@typescript-eslint/no-misused-promises": "off" + "@typescript-eslint/no-misused-promises": "off", + "@typescript-eslint/no-explicit-any": "off" } }, { @@ -131,7 +132,8 @@ "@typescript-eslint/no-unsafe-argument": "off", "@typescript-eslint/no-unsafe-member-access": "off", "@typescript-eslint/no-unsafe-return": "off", - "@typescript-eslint/no-unsafe-call": "off" + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-explicit-any": "off" } }, { @@ -142,8 +144,7 @@ "@typescript-eslint/no-throw-literal": "off", "@typescript-eslint/no-dynamic-delete": "off", "@typescript-eslint/no-base-to-string": "off", - "@typescript-eslint/no-unnecessary-condition": "off", - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-unnecessary-condition": "off" } } ] diff --git a/src/config/logger.ts b/src/config/logger.ts index 1d6675c70d..b4be084463 100644 --- a/src/config/logger.ts +++ b/src/config/logger.ts @@ -220,7 +220,7 @@ const requestSerializer = (req) => req && ({ remotePort: req.socket?.remotePort }); -const graphQlErrorsSerializer = (errors: Array) => ( +const graphQlErrorsSerializer = (errors: Array) => ( { errors: errors.map(error => errorSerializer(error)) } diff --git a/src/github/client/github-client.types.ts b/src/github/client/github-client.types.ts index f6b920a154..c36ae17319 100644 --- a/src/github/client/github-client.types.ts +++ b/src/github/client/github-client.types.ts @@ -1,6 +1,7 @@ import { AxiosResponse } from "axios"; import { GraphQLError } from "./github-client-errors"; import { Octokit } from "@octokit/rest"; +import { JiraAuthor } from "~/src/interfaces/jira"; export enum SortDirection { ASC = "asc", @@ -151,6 +152,14 @@ export type CodeScanningAlertResponseItem = { most_recent_instance: CodeScanningAlertResponseItemMostRecentInstance; }; +export interface Commit { + author: JiraAuthor; + authoredDate: string; + message: string; + oid: string; + url: string; +} + export interface Branch { associatedPullRequests: { nodes: { @@ -169,7 +178,9 @@ export interface Branch { oid: string; message: string; url: string; - history: any; + history: { + nodes: Commit[]; + } }; } diff --git a/src/middleware/frontend-log-middleware.ts b/src/middleware/frontend-log-middleware.ts index c4a917f0d6..eb0750fffc 100644 --- a/src/middleware/frontend-log-middleware.ts +++ b/src/middleware/frontend-log-middleware.ts @@ -46,7 +46,7 @@ declare global { } } -export const LogMiddleware = async (req: Request, res: Response, next: NextFunction): Promise => { +export const LogMiddleware = async (req: Request, res: Response, next: NextFunction): Promise => { req.log = getLogger("frontend-log-middleware", { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment fields: req.log?.fields, @@ -77,7 +77,7 @@ export const LogMiddleware = async (req: Request): string | undefined => +const getUnvalidatedJiraHost = (req: Request): string | undefined => req.session?.jiraHost || extractUnsafeJiraHost(req); /** @@ -85,7 +85,7 @@ const getUnvalidatedJiraHost = (req: Request moduleUrls.some(moduleUrl => matchRouteWithPattern(moduleUrl, url)); -const extractUnsafeJiraHost = (req: Request): string | undefined => { +const extractUnsafeJiraHost = (req: Request): string | undefined => { if (checkPathValidity(req.path) && req.method == "GET") { // Only save xdm_e query when on the GET post install url (iframe url) return req.query.xdm_e as string; diff --git a/src/middleware/github-server-app-middleware.test.ts b/src/middleware/github-server-app-middleware.test.ts index 91c584aeac..5bc26a51c7 100644 --- a/src/middleware/github-server-app-middleware.test.ts +++ b/src/middleware/github-server-app-middleware.test.ts @@ -9,7 +9,7 @@ jest.mock("models/installation"); jest.mock("models/github-server-app"); const GIT_HUB_SERVER_APP_ID = 123; -const GIT_HUB_SERVER_APP_APP_ID = 789; +const GIT_HUB_SERVER_APP_APP_ID = "789"; const UUID = "97da6b0e-ec61-11ec-8ea0-0242ac120002"; const JIRA_INSTALLATION_ID = 1; diff --git a/src/middleware/github-server-app-middleware.ts b/src/middleware/github-server-app-middleware.ts index 75c335dce5..77ab27d235 100644 --- a/src/middleware/github-server-app-middleware.ts +++ b/src/middleware/github-server-app-middleware.ts @@ -5,7 +5,7 @@ import { envVars } from "config/env"; import { GITHUB_CLOUD_BASEURL } from "~/src/github/client/github-client-constants"; import { BaseLocals } from "../rest/routes"; -export const GithubServerAppMiddleware = async (req: Request, res: Response, next: NextFunction): Promise => { +export const GithubServerAppMiddleware = async (req: Request, res: Response, next: NextFunction): Promise => { const jiraHost = res.locals.jiraHost; const { uuid } = req.params; @@ -40,7 +40,7 @@ export const GithubServerAppMiddleware = async (req: Request, res: Response, res: Response, next: NextFunction) => { +export const jiraSymmetricJwtMiddleware = async (req: Request, res: Response, next: NextFunction) => { const authHeader = req.headers["authorization"] as string; const authHeaderPrefix = "JWT "; const cookies = req.cookies as { jwt?: string }; @@ -36,7 +36,7 @@ export const jiraSymmetricJwtMiddleware = async (req: Request; + let verifiedClaims: Record; try { verifiedClaims = await verifySymmetricJwt(req, token, installation); } catch (err: unknown) { @@ -107,7 +107,7 @@ const verifySymmetricJwt = async (req: Request, token: string, installation: Ins const secret = await installation.decrypt("encryptedSharedSecret", req.log); try { - const claims = decodeSymmetric(token, secret, algorithm, false) as { exp?: number, qsh?: string }; + const claims = decodeSymmetric(token, secret, algorithm, false) as Record; const tokenType = await getTokenType(req.originalUrl, req.method); verifyJwtClaims(claims, tokenType, req); diff --git a/src/rest/middleware/jira-admin/jira-admin-check.ts b/src/rest/middleware/jira-admin/jira-admin-check.ts index a083dcac76..19d714a9d7 100644 --- a/src/rest/middleware/jira-admin/jira-admin-check.ts +++ b/src/rest/middleware/jira-admin/jira-admin-check.ts @@ -6,7 +6,7 @@ import { errorWrapper } from "../../helper"; import { BaseLocals } from "../../routes"; const ADMIN_PERMISSION = "ADMINISTER"; -export const JiraAdminEnforceMiddleware = errorWrapper("jiraAdminEnforceMiddleware", async (req: Request, res: Response, next: NextFunction): Promise => { +export const JiraAdminEnforceMiddleware = errorWrapper("jiraAdminEnforceMiddleware", async (req: Request, res: Response, next: NextFunction): Promise => { const { accountId, installation, jiraHost } = res.locals; diff --git a/src/rest/middleware/jwt/jwt-handler.ts b/src/rest/middleware/jwt/jwt-handler.ts index 99086de75d..3c53d2e90e 100644 --- a/src/rest/middleware/jwt/jwt-handler.ts +++ b/src/rest/middleware/jwt/jwt-handler.ts @@ -9,7 +9,7 @@ import { BaseLocals } from "../../routes"; const INVALID_SECRET = "some-invalid-secret"; const SKIP_PATHS = ["/spa/deferred"]; -export const JwtHandler = errorWrapper("JwtHandler", async (req: Request, res: Response, next: NextFunction) => { +export const JwtHandler = errorWrapper("JwtHandler", async (req: Request, res: Response, next: NextFunction) => { const token = req.headers["authorization"]; diff --git a/src/rest/routes/github-orgs/index.ts b/src/rest/routes/github-orgs/index.ts index ab07fac578..024d450d55 100644 --- a/src/rest/routes/github-orgs/index.ts +++ b/src/rest/routes/github-orgs/index.ts @@ -20,7 +20,7 @@ GitHubOrgsRouter.get("/", errorWrapper("GitHubOrgsFetchOrgs", async (req: Reques GitHubOrgsRouter.post("/", errorWrapper("GitHubOrgsConnectJira", async (req: Request, res: Response) => { const { installation, githubToken, gitHubAppId } = res.locals; - const body = req.body as { installationId: any }; + const body = req.body as { installationId: unknown }; const gitHubInstallationId = Number(body.installationId); if (!gitHubInstallationId) { diff --git a/src/rest/routes/index.d.ts b/src/rest/routes/index.d.ts index 6a75ed1791..bb3caa85ee 100644 --- a/src/rest/routes/index.d.ts +++ b/src/rest/routes/index.d.ts @@ -1,6 +1,13 @@ import { Installation } from "~/src/models/installation"; -export interface BaseLocals extends Record { +export interface BaseLocals extends Record { + gitHubAppConfig: { + gitHubAppId: number | undefined; + appId: string; + uuid: string | undefined; + hostname: string; + clientId: string; + }; installation: Installation; jiraHost: string; githubToken: string; diff --git a/src/routes/github/github-router.test.ts b/src/routes/github/github-router.test.ts index 584783c61d..b7c3713194 100644 --- a/src/routes/github/github-router.test.ts +++ b/src/routes/github/github-router.test.ts @@ -273,7 +273,7 @@ describe("GitHub router", () => { jiraHost, gitHubAppId: gitHubAppId, gitHubAppConfig: expect.objectContaining({ - appId: GITHUB_SERVER_APP_ID, + appId: String(GITHUB_SERVER_APP_ID), uuid: GITHUB_SERVER_APP_UUID }) }) diff --git a/src/routes/jira/connect/enterprise/app/jira-connect-enterprise-app-router.test.ts b/src/routes/jira/connect/enterprise/app/jira-connect-enterprise-app-router.test.ts index a8a26460f8..94b3c02cc0 100644 --- a/src/routes/jira/connect/enterprise/app/jira-connect-enterprise-app-router.test.ts +++ b/src/routes/jira/connect/enterprise/app/jira-connect-enterprise-app-router.test.ts @@ -52,7 +52,7 @@ describe("JiraConnectEnterpriseAppRouter", () => { .expect(200); expect(capturedGHEAppConfig).toEqual(expect.objectContaining({ uuid: GHE_APP_UUID, - appId: 1 + appId: "1" })); }); it("should throw error for invalid uuid", async () => { diff --git a/src/sqs/sqs.ts b/src/sqs/sqs.ts index 1747a2a3ff..7a4eacca43 100644 --- a/src/sqs/sqs.ts +++ b/src/sqs/sqs.ts @@ -358,7 +358,7 @@ export class SqsQueue { try { context.log.warn({ err }, "Failed message"); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - const errorHandlingResult = await this.errorHandler(err as any, context); + const errorHandlingResult = await this.errorHandler(err as Error, context); this.log.info({ errorHandlingResult }, "Error handling result"); if (errorHandlingResult.isFailure) { diff --git a/src/sync/transforms/branch.ts b/src/sync/transforms/branch.ts index e6e9fae621..1e21281a75 100644 --- a/src/sync/transforms/branch.ts +++ b/src/sync/transforms/branch.ts @@ -4,7 +4,44 @@ import { isEmpty, union } from "lodash"; import { generateCreatePullRequestUrl } from "../../transforms/util/pull-request-link-generator"; import { transformRepositoryDevInfoBulk } from "~/src/transforms/transform-repository"; import { Repository } from "models/subscription"; -import { Branch } from "~/src/github/client/github-client.types"; +import { Branch, Commit } from "~/src/github/client/github-client.types"; +import { JiraAuthor } from "~/src/interfaces/jira"; + +interface JiraBranch { + createPullRequestUrl: string, + id: string, + issueKeys: string[], + lastCommit: { + author: JiraAuthor, + authorTimestamp: string, + displayId: string, + fileCount: number, + hash: string, + id: string, + issueKeys: string[], + message: string, + url?: string, + updateSequenceId: number + }, + name: string, + url: string, + updateSequenceId: number +} + +interface JiraCommit { + author: JiraAuthor, + authorTimestamp: string, + displayId: string, + fileCount: number, + hash: string, + id: string, + issueKeys: string[], + message: string, + timestamp: string, + url: string, + updateSequenceId: number +} + // TODO: better typing in file /** @@ -16,7 +53,7 @@ import { Branch } from "~/src/github/client/github-client.types"; * - Title of the last associated Pull Request * - Message from the last commit in that branch */ -const mapBranch = (branch: Branch, repository: Repository, alwaysSend: boolean) => { +const mapBranch = (branch: Branch, repository: Repository, alwaysSend: boolean): JiraBranch | undefined => { const branchKeys = jiraIssueKeyParser(branch.name); const pullRequestKeys = jiraIssueKeyParser( branch.associatedPullRequests.nodes.length ? branch.associatedPullRequests.nodes[0].title : "" @@ -57,7 +94,7 @@ const mapBranch = (branch: Branch, repository: Repository, alwaysSend: boolean) * of commits we got from the GraphQL response and maps the data * to the structure needed for the DevInfo API */ -const mapCommit = (commit, alwaysSend: boolean) => { +const mapCommit = (commit: Commit, alwaysSend: boolean): JiraCommit | undefined => { const issueKeys = jiraIssueKeyParser(commit.message); if (isEmpty(issueKeys) && !alwaysSend) { @@ -85,17 +122,17 @@ const mapCommit = (commit, alwaysSend: boolean) => { * @param payload * @param gitHubBaseUrl - can be undefined for Cloud */ -export const transformBranches = (payload: { branches: any, repository: Repository }, gitHubBaseUrl: string | undefined, alwaysSendBranches: boolean, alwaysSendCommits: boolean) => { +export const transformBranches = (payload: { branches: Branch[], repository: Repository }, gitHubBaseUrl: string | undefined, alwaysSendBranches: boolean, alwaysSendCommits: boolean) => { // TODO: use reduce instead of map/filter const branches = payload.branches - .map((branch) => mapBranch(branch, payload.repository, alwaysSendBranches)) - .filter((branch) => !!branch); + .map((branch: Branch) => mapBranch(branch, payload.repository, alwaysSendBranches)) + .filter((branch: JiraBranch | undefined) => !!branch); // TODO: use reduce instead of map/filter - const commits = payload.branches.flatMap((branch) => + const commits = payload.branches.flatMap((branch: Branch) => branch.target.history.nodes - .map((commit) => mapCommit(commit, alwaysSendCommits)) - .filter((branch) => !!branch) + .map((commit: Commit) => mapCommit(commit, alwaysSendCommits)) + .filter((commit: JiraCommit | undefined) => !!commit) ); if ((!commits || !commits.length) && (!branches || !branches.length)) { diff --git a/src/transforms/transform-pull-request.ts b/src/transforms/transform-pull-request.ts index a686fd6075..7b5a03dfc3 100644 --- a/src/transforms/transform-pull-request.ts +++ b/src/transforms/transform-pull-request.ts @@ -241,7 +241,7 @@ export const transformPullRequest = (repository: Repository, _jiraHost: string, const mapReviews = (reviews: pullRequestNode["reviews"]["nodes"] = [], reviewRequests: pullRequestNode["reviewRequests"]["nodes"] = []): JiraReview[] => { const allReviews = [...reviewRequests || [], ...reviews || []] as pullRequestNode["reviews"]["nodes"]; - const usernames: Record = {}; + const usernames: Record = {}; // The reduce function goes through all the reviews and creates an array of unique users // (so users' avatars won't be duplicated on the dev panel in Jira) diff --git a/src/util/curl/curl-utils.test.ts b/src/util/curl/curl-utils.test.ts index 769dfc26e6..861da52a65 100644 --- a/src/util/curl/curl-utils.test.ts +++ b/src/util/curl/curl-utils.test.ts @@ -19,7 +19,7 @@ describe("curl-utils", () => { authorization: "secrets" }); expect(result.meta).toContain("> POST / HTTP"); - expect(result.body).toEqual(expect.stringContaining("HTTP Status 403")); + expect(result.body).toEqual(expect.stringContaining("403")); expect(result.meta).toContain("< HTTP/2 403"); }); it("should not contains private information in the headers", async () => { diff --git a/src/util/filtering-http-logs-stream.ts b/src/util/filtering-http-logs-stream.ts index 53671cf2b2..04ade9869d 100644 --- a/src/util/filtering-http-logs-stream.ts +++ b/src/util/filtering-http-logs-stream.ts @@ -17,7 +17,7 @@ import { Writable } from "stream"; */ export const filteringHttpLogsStream = (filteringLoggerName: string, out: Writable = process.stdout): Writable => new Writable({ - write: (chunk: any, encoding: BufferEncoding, next) => { + write: (chunk: unknown, encoding: BufferEncoding, next) => { //TODO Remove this code when there will be convenient way to do it in Probot. //See https://github.com/probot/probot/issues/1577 if (String(chunk)?.match(`${filteringLoggerName}.*(GET|POST|DELETE|PUT|PATCH) /`)) { diff --git a/src/util/handlebars/handlebar-helpers.ts b/src/util/handlebars/handlebar-helpers.ts index 1817690be4..63eee2d6cc 100644 --- a/src/util/handlebars/handlebar-helpers.ts +++ b/src/util/handlebars/handlebar-helpers.ts @@ -21,9 +21,9 @@ export const registerHandlebarsHelpers = () => { hbs.registerHelper( "ifAllReposSynced", - (numberOfSyncedRepos: number, totalNumberOfRepos: number): any => + (numberOfSyncedRepos: number, totalNumberOfRepos: number): string => numberOfSyncedRepos === totalNumberOfRepos - ? totalNumberOfRepos + ? String(totalNumberOfRepos) : `${numberOfSyncedRepos} / ${totalNumberOfRepos}` );