export function getCheckSummary()

in controlplane/src/core/bufservices/check/getCheckSummary.ts [22:223]


export function getCheckSummary(
  opts: RouterOptions,
  req: GetCheckSummaryRequest,
  ctx: HandlerContext,
): Promise<PlainMessage<GetCheckSummaryResponse>> {
  let logger = getLogger(ctx, opts.logger);

  return handleError<PlainMessage<GetCheckSummaryResponse>>(ctx, logger, async () => {
    const authContext = await opts.authenticator.authenticate(ctx.requestHeader);
    logger = enrichLogger(ctx, logger, authContext);

    const fedGraphRepo = new FederatedGraphRepository(logger, opts.db, authContext.organizationId);
    const subgraphRepo = new SubgraphRepository(logger, opts.db, authContext.organizationId);
    const schemaCheckRepo = new SchemaCheckRepository(opts.db);
    const schemaLintRepo = new SchemaLintRepository(opts.db);
    const schemaGraphPruningRepo = new SchemaGraphPruningRepository(opts.db);
    const namespaceRepo = new NamespaceRepository(opts.db, authContext.organizationId);
    const proposalRepo = new ProposalRepository(opts.db);

    const namespace = await namespaceRepo.byName(req.namespace);
    if (!namespace) {
      return {
        response: {
          code: EnumStatusCode.ERR_NOT_FOUND,
          details: `Namespace '${req.namespace}' not found`,
        },
        compositionErrors: [],
        compositionWarnings: [],
        changes: [],
        affectedGraphs: [],
        trafficCheckDays: 0,
        lintIssues: [],
        graphPruningIssues: [],
        isGraphPruningEnabled: false,
        isLintingEnabled: false,
        checkedSubgraphs: [],
        proposalMatches: [],
        isProposalsEnabled: false,
      };
    }

    const graph = await fedGraphRepo.byName(req.graphName, req.namespace);

    if (!graph) {
      return {
        response: {
          code: EnumStatusCode.ERR_NOT_FOUND,
          details: 'Requested graph does not exist',
        },
        compositionErrors: [],
        compositionWarnings: [],
        changes: [],
        affectedGraphs: [],
        trafficCheckDays: 0,
        lintIssues: [],
        graphPruningIssues: [],
        isGraphPruningEnabled: false,
        isLintingEnabled: false,
        checkedSubgraphs: [],
        proposalMatches: [],
        isProposalsEnabled: false,
      };
    }

    if (!authContext.rbac.hasFederatedGraphReadAccess(graph)) {
      throw new UnauthorizedError();
    }

    const check = await subgraphRepo.checkById({
      id: req.checkId,
      federatedGraphTargetId: graph.targetId,
      federatedGraphId: graph.id,
    });
    const checkDetails = await subgraphRepo.checkDetails(req.checkId, graph.targetId);

    if (!check || !checkDetails) {
      return {
        response: {
          code: EnumStatusCode.ERR_NOT_FOUND,
          details: 'Requested check not found',
        },
        compositionErrors: [],
        compositionWarnings: [],
        changes: [],
        affectedGraphs: [],
        trafficCheckDays: 0,
        lintIssues: [],
        graphPruningIssues: [],
        isGraphPruningEnabled: false,
        isLintingEnabled: false,
        checkedSubgraphs: [],
        proposalMatches: [],
        isProposalsEnabled: false,
      };
    }

    const { trafficCheckDays } = await schemaCheckRepo.getFederatedGraphConfigForCheckId(req.checkId, graph.id);

    const lintIssues = await schemaLintRepo.getSchemaCheckLintIsssues({ schemaCheckId: req.checkId });
    const graphPruningIssues = await schemaGraphPruningRepo.getSchemaCheckGraphPruningIsssues({
      schemaCheckId: req.checkId,
      federatedGraphId: graph.id,
    });

    const currentAffectedGraph = check.affectedGraphs.find((ag) => ag.id === graph.id);
    const affectedGraphs: GetCheckSummaryResponse_AffectedGraph[] = [];

    const hasLintErrors = lintIssues.some((issue) => issue.severity === LintSeverity.error);
    let hasAffectedOperations = false;
    if (check.hasClientTraffic) {
      const affectedOperations = await schemaCheckRepo.getAffectedOperationsByCheckId({
        checkId: req.checkId,
        limit: 1,
        offset: 0,
      });
      hasAffectedOperations = affectedOperations.length > 0;
    }
    affectedGraphs.push(
      new GetCheckSummaryResponse_AffectedGraph({
        ...currentAffectedGraph,
        name: graph.name,
        isCheckSuccessful: isCheckSuccessful({
          isComposable: checkDetails.compositionErrors.length === 0,
          isBreaking: checkDetails.changes.some((change) => change.isBreaking),
          hasClientTraffic: hasAffectedOperations,
          hasLintErrors,
          hasGraphPruningErrors: graphPruningIssues.some((issue) => issue.severity === LintSeverity.error),
          clientTrafficCheckSkipped: check.clientTrafficCheckSkipped,
          hasProposalMatchError: check.proposalMatch === 'error',
        }),
      }),
    );

    // checking if the checks for the other affected graphs are successful
    for (const ag of check.affectedGraphs) {
      if (ag.id === graph.id) {
        continue;
      }
      const fedGraph = await fedGraphRepo.byId(ag.id);
      if (!fedGraph) {
        continue;
      }
      const checkDetails = await subgraphRepo.checkDetails(req.checkId, fedGraph.targetId);
      if (!checkDetails) {
        continue;
      }
      const graphPruningIssues = await schemaGraphPruningRepo.getSchemaCheckGraphPruningIsssues({
        schemaCheckId: req.checkId,
        federatedGraphId: fedGraph.id,
      });

      if (check.hasClientTraffic) {
        const affectedOperations = await schemaCheckRepo.getAffectedOperationsByCheckId({
          checkId: req.checkId,
          limit: 1,
          offset: 0,
        });
        hasAffectedOperations = affectedOperations.length > 0;
      }
      affectedGraphs.push(
        new GetCheckSummaryResponse_AffectedGraph({
          ...ag,
          name: fedGraph.name,
          isCheckSuccessful: isCheckSuccessful({
            isComposable: checkDetails.compositionErrors.length === 0,
            isBreaking: checkDetails.changes.some((change) => change.isBreaking),
            hasClientTraffic: hasAffectedOperations,
            hasLintErrors,
            hasGraphPruningErrors: graphPruningIssues.some((issue) => issue.severity === LintSeverity.error),
            clientTrafficCheckSkipped: check.clientTrafficCheckSkipped,
            hasProposalMatchError: check.proposalMatch === 'error',
          }),
        }),
      );
    }

    const proposal = await proposalRepo.getProposalByCheckId({ checkId: req.checkId });
    const proposalSchemaMatches = await proposalRepo.getProposalSchemaMatchesOfCheck({
      checkId: req.checkId,
      federatedGraphId: graph.id,
    });

    return {
      response: {
        code: EnumStatusCode.OK,
      },
      check,
      affectedGraphs,
      proposedSubgraphSchemaSDL: check.proposedSubgraphSchemaSDL,
      changes: checkDetails.changes,
      compositionErrors: checkDetails.compositionErrors,
      trafficCheckDays,
      lintIssues,
      graphPruningIssues,
      compositionWarnings: checkDetails.compositionWarnings,
      proposalId: proposal?.proposalId,
      proposalName: proposal?.proposalName,
      proposalMatches: proposalSchemaMatches,
      isProposalsEnabled: namespace.enableProposals,
    };
  });
}