UNPKG

@atomist/automation-client

Version:

Atomist API for software low-level client

99 lines (90 loc) 4.46 kB
import { ActionResult } from "../../action/ActionResult"; import { HandleCommand } from "../../HandleCommand"; import { HandlerContext } from "../../HandlerContext"; import { commandHandlerFrom, OnCommand, } from "../../onCommand"; import { Maker } from "../../util/constructionUtils"; import { CommandDetails } from "../CommandDetails"; import { EditorOrReviewerParameters } from "../common/params/BaseEditorOrReviewerParameters"; import { andFilter, RepoFilter, } from "../common/repoFilter"; import { RepoFinder } from "../common/repoFinder"; import { RepoRef } from "../common/RepoId"; import { issueRaisingReviewRouter } from "./issueRaisingReviewRouter"; import { ProjectReviewer } from "./projectReviewer"; import { reviewAll } from "./reviewAll"; import { ProjectReview } from "./ReviewResult"; /** * Function signature to route ProjectReviews, for example to GitHub issues or MessageClient */ export type ReviewRouter<PARAMS> = (pr: ProjectReview, params: PARAMS, title: string, ctx: HandlerContext) => Promise<ActionResult<RepoRef>>; /** * Further details of an editor to allow selective customization */ export interface ReviewerCommandDetails<PARAMS extends EditorOrReviewerParameters> extends CommandDetails<PARAMS> { repoFilter?: RepoFilter; reviewRouter: ReviewRouter<PARAMS>; } function defaultDetails(name: string): ReviewerCommandDetails<EditorOrReviewerParameters> { return { description: name, reviewRouter: issueRaisingReviewRouter, }; } /** * Create a handle function that reviews one or many repos, following AllReposByDefaultParameters * @param reviewerFactory function returning a reviewer instance for the appropriate parameters * @param factory construction function * @param {string} name * @param {string} details object allowing customization beyond reasonable defaults * @return {HandleCommand} */ export function reviewerHandler<PARAMS extends EditorOrReviewerParameters>(reviewerFactory: (params: PARAMS) => ProjectReviewer<PARAMS>, factory: Maker<PARAMS>, name: string, details: Partial<ReviewerCommandDetails<PARAMS>> = {}): HandleCommand { const detailsToUse: ReviewerCommandDetails<EditorOrReviewerParameters> = { ...defaultDetails(name), ...details, } as ReviewerCommandDetails<EditorOrReviewerParameters>; return commandHandlerFrom(handleReviewOneOrMany(reviewerFactory, name, detailsToUse), factory, name, detailsToUse.description, detailsToUse.intent, detailsToUse.tags); } /** * If owner and repo are required, review just one repo. Otherwise review all repos * in the present team */ function handleReviewOneOrMany<PARAMS extends EditorOrReviewerParameters>(reviewerFactory: (params: PARAMS) => ProjectReviewer<PARAMS>, name: string, details: ReviewerCommandDetails<PARAMS>): OnCommand<PARAMS> { return (ctx: HandlerContext, parameters: PARAMS) => { const repoFinder: RepoFinder = parameters.targets.repoRef ? () => Promise.resolve([parameters.targets.repoRef]) : details.repoFinder; return reviewAll(ctx, parameters.targets.credentials, reviewerFactory(parameters), parameters, repoFinder, andFilter(parameters.targets.test, details.repoFilter), !!details.repoLoader ? details.repoLoader(parameters) : undefined) .then(projectReviews => { return Promise.all(projectReviews .filter(pr => pr.comments.length > 0) .map(pr => { return details.reviewRouter(pr, parameters, name, ctx); })) .then(persisted => ctx.messageClient.respond( `${name} reviewed ${projectReviews.length} repositories: Reported on ${persisted.length} with problems`) .then(() => ({ projectsReviewed: projectReviews.length, projectReviews, }))); }); }; }