Skip to content

Commit

Permalink
Fixed user OR teams to users AND teams (#30)
Browse files Browse the repository at this point in the history
Fixed the `XOR` condition for a `OR` condition.

Updated tests.

Closes #28
  • Loading branch information
Bullrich authored Aug 1, 2023
1 parent f253d2c commit 2fca6de
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/file/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ActionLogger } from "../github/types";
import { BasicRule, ConfigurationFile, Rule } from "./types";

/** For the users or team schema. Will be recycled A LOT
* Remember to add `.xor("users", "teams")` to force one of the two to be picked up
* Remember to add `.or("users", "teams")` to force at least one of the two to be defined
*/
const reviewersObj = {
users: Joi.array().items(Joi.string()).optional().empty(null),
Expand Down Expand Up @@ -39,7 +39,7 @@ export const generalSchema = Joi.object<ConfigurationFile>().keys({
*/
export const basicRuleSchema = Joi.object<BasicRule>()
.keys({ min_approvals: Joi.number().empty(1), ...reviewersObj })
.xor("users", "teams");
.or("users", "teams");

/**
* Evaluates a config thoroughly. If there is a problem with it, it will throw.
Expand Down
14 changes: 8 additions & 6 deletions src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { validateConfig, validateRegularExpressions } from "./file/validator";
import { PullRequestApi } from "./github/pullRequest";
import { TeamApi } from "./github/teams";
import { ActionLogger } from "./github/types";
import { concatArraysUniquely } from "./util";

type ReviewReport = {
/** The amount of missing reviews to fulfill the requirements */
Expand Down Expand Up @@ -88,7 +89,7 @@ export class ActionRunner {
*/
async evaluateCondition(rule: { min_approvals: number } & Reviewers): Promise<ReviewState> {
// This is a list of all the users that need to approve a PR
const requiredUsers: string[] = [];
let requiredUsers: string[] = [];
// If team is set, we fetch the members of such team
if (rule.teams) {
for (const team of rule.teams) {
Expand All @@ -101,11 +102,12 @@ export class ActionRunner {
}
}
// If, instead, users are set, we simply push them to the array as we don't need to scan a team
} else if (rule.users) {
requiredUsers.push(...rule.users);
} else {
// This should be captured before by the validation
throw new Error("Teams and Users field are not set for rule.");
}
if (rule.users) {
requiredUsers = concatArraysUniquely(requiredUsers, rule.users);
}
if (requiredUsers.length === 0) {
throw new Error("No users have been found in the required reviewers");
}

if (requiredUsers.length < rule.min_approvals) {
Expand Down
19 changes: 18 additions & 1 deletion src/test/runner/conditions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("evaluateCondition tests", () => {

test("should throw if no teams or users were set", async () => {
await expect(runner.evaluateCondition({ min_approvals: 99 })).rejects.toThrowError(
"Teams and Users field are not set for rule.",
"No users have been found in the required reviewers",
);
});

Expand Down Expand Up @@ -131,6 +131,23 @@ describe("evaluateCondition tests", () => {
expect(report?.missingUsers).toEqual([...team1.users, team2.users[0]]);
expect(report?.teamsToRequest).toEqual([team1.name, team2.name]);
});

describe("teams and users combined", () => {
test("should not duplicate users if they belong to team and user list", async () => {
teamsApi.getTeamMembers.calledWith(team).mockResolvedValue(users);
api.listApprovedReviewsAuthors.mockResolvedValue([]);
const [result, report] = await runner.evaluateCondition({
min_approvals: 1,
teams: [team],
users: [users[0]],
});
expect(result).toBeFalsy();
// Should not send required users more than once
expect(report?.missingUsers).toEqual(users);
expect(report?.teamsToRequest).toEqual([team]);
expect(report?.usersToRequest).toEqual([users[0]]);
});
});
});
});
});
8 changes: 8 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ import { ActionLogger } from "./github/types";
export function generateCoreLogger(): ActionLogger {
return { info, debug, warn: warning, error };
}

/** Concats two arrays and remove the duplicates */
export function concatArraysUniquely<T>(arr1?: T[], arr2?: T[]): T[] {
// We concat the two arrays
const concatedArray = (arr1 ?? []).concat(arr2 ?? []);
// We remove the duplicated values and return the array
return concatedArray.filter((item, pos) => concatedArray.indexOf(item) === pos);
}

0 comments on commit 2fca6de

Please sign in to comment.