diff --git a/dev-infra/ng-dev.js b/dev-infra/ng-dev.js index 5bb1d3044a..127ea81814 100755 --- a/dev-infra/ng-dev.js +++ b/dev-infra/ng-dev.js @@ -4917,11 +4917,13 @@ const FALLBACK_GROUP_NAME = 'fallback'; /** A PullApprove group to be able to test files against. */ class PullApproveGroup { constructor(groupName, config, precedingGroups = []) { + var _a; this.groupName = groupName; this.precedingGroups = precedingGroups; /** List of conditions for the group. */ this.conditions = []; this._captureConditions(config); + this.reviewers = (_a = config.reviewers) !== null && _a !== void 0 ? _a : { users: [], teams: [] }; } _captureConditions(config) { if (config.conditions && this.groupName !== FALLBACK_GROUP_NAME) { @@ -5063,12 +5065,16 @@ function verify$1() { * Whether all group condition lines match at least one file and all files * are matched by at least one group. */ - const verificationSucceeded = resultsByGroup.every(r => !r.unmatchedCount) && !unmatchedFiles.length; + const allGroupConditionsValid = resultsByGroup.every(r => !r.unmatchedCount) && !unmatchedFiles.length; + /** Whether all groups have at least one reviewer user or team defined. */ + const groupsWithoutReviewers = groups.filter(group => Object.keys(group.reviewers).length === 0); + /** The overall result of the verifcation. */ + const overallResult = allGroupConditionsValid && groupsWithoutReviewers.length === 0; /** * Overall result */ logHeader('Overall Result'); - if (verificationSucceeded) { + if (overallResult) { info('PullApprove verification succeeded!'); } else { @@ -5078,6 +5084,16 @@ function verify$1() { info(`files/directories have owners and all patterns that appear in`); info(`the file correspond to actual files/directories in the repo.`); } + /** Reviewers check */ + logHeader(`Group Reviewers Check`); + if (groupsWithoutReviewers.length === 0) { + info('All group contain at least one reviewer user or team.'); + } + else { + info.group(`Discovered ${groupsWithoutReviewers.length} group(s) without a reviewer defined`); + groupsWithoutReviewers.forEach(g => info(g.groupName)); + info.groupEnd(); + } /** * File by file Summary */ @@ -5108,7 +5124,7 @@ function verify$1() { unverifiableConditionsInGroups.forEach(group => logGroup(group, 'unverifiableConditions')); info.groupEnd(); // Provide correct exit code based on verification success. - process.exit(verificationSucceeded ? 0 : 1); + process.exit(overallResult ? 0 : 1); } /** Build the parser for the pullapprove commands. */ diff --git a/dev-infra/pullapprove/group.ts b/dev-infra/pullapprove/group.ts index 3aaeaf1cf6..ec135d52a9 100644 --- a/dev-infra/pullapprove/group.ts +++ b/dev-infra/pullapprove/group.ts @@ -19,6 +19,11 @@ interface GroupCondition { unverifiable: boolean; } +interface GroupReviewers { + users?: string[]; + teams?: string[]; +} + /** Result of testing files against the group. */ export interface PullApproveGroupResult { groupName: string; @@ -40,12 +45,15 @@ const FALLBACK_GROUP_NAME = 'fallback'; /** A PullApprove group to be able to test files against. */ export class PullApproveGroup { /** List of conditions for the group. */ - conditions: GroupCondition[] = []; + readonly conditions: GroupCondition[] = []; + /** List of reviewers for the group. */ + readonly reviewers: GroupReviewers; constructor( public groupName: string, config: PullApproveGroupConfig, readonly precedingGroups: PullApproveGroup[] = []) { this._captureConditions(config); + this.reviewers = config.reviewers ?? {users: [], teams: []}; } private _captureConditions(config: PullApproveGroupConfig) { diff --git a/dev-infra/pullapprove/verify.ts b/dev-infra/pullapprove/verify.ts index 6b67a9a8f8..93bfe9948e 100644 --- a/dev-infra/pullapprove/verify.ts +++ b/dev-infra/pullapprove/verify.ts @@ -49,14 +49,18 @@ export function verify() { * Whether all group condition lines match at least one file and all files * are matched by at least one group. */ - const verificationSucceeded = + const allGroupConditionsValid = resultsByGroup.every(r => !r.unmatchedCount) && !unmatchedFiles.length; + /** Whether all groups have at least one reviewer user or team defined. */ + const groupsWithoutReviewers = groups.filter(group => Object.keys(group.reviewers).length === 0); + /** The overall result of the verifcation. */ + const overallResult = allGroupConditionsValid && groupsWithoutReviewers.length === 0; /** * Overall result */ logHeader('Overall Result'); - if (verificationSucceeded) { + if (overallResult) { info('PullApprove verification succeeded!'); } else { info(`PullApprove verification failed.`); @@ -65,6 +69,15 @@ export function verify() { info(`files/directories have owners and all patterns that appear in`); info(`the file correspond to actual files/directories in the repo.`); } + /** Reviewers check */ + logHeader(`Group Reviewers Check`); + if (groupsWithoutReviewers.length === 0) { + info('All group contain at least one reviewer user or team.'); + } else { + info.group(`Discovered ${groupsWithoutReviewers.length} group(s) without a reviewer defined`); + groupsWithoutReviewers.forEach(g => info(g.groupName)); + info.groupEnd(); + } /** * File by file Summary */ @@ -97,5 +110,5 @@ export function verify() { info.groupEnd(); // Provide correct exit code based on verification success. - process.exit(verificationSucceeded ? 0 : 1); + process.exit(overallResult ? 0 : 1); }