Skip to content

Commit

Permalink
Add decision manager to decide on final approval vote
Browse files Browse the repository at this point in the history
[changelog:added]
  • Loading branch information
cdupuis committed Nov 6, 2018
1 parent 21d8dd9 commit 68ff03e
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 16 deletions.
19 changes: 14 additions & 5 deletions lib/api-helper/machine/AbstractSoftwareDeliveryMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ import { ExtensionPack } from "../../api/machine/ExtensionPack";
import { registrableManager } from "../../api/machine/Registerable";
import { SoftwareDeliveryMachine } from "../../api/machine/SoftwareDeliveryMachine";
import { SoftwareDeliveryMachineConfiguration } from "../../api/machine/SoftwareDeliveryMachineOptions";
import {
GoalSetter,
GoalSettingStructure,
} from "../../api/mapping/GoalSetter";
import { GoalSetter } from "../../api/mapping/GoalSetter";
import { PushMapping } from "../../api/mapping/PushMapping";
import { PushTest } from "../../api/mapping/PushTest";
import { AnyPush } from "../../api/mapping/support/commonPushTests";
Expand All @@ -56,7 +53,11 @@ import { CodeTransformRegistration } from "../../api/registration/CodeTransformR
import { CommandHandlerRegistration } from "../../api/registration/CommandHandlerRegistration";
import { EventHandlerRegistration } from "../../api/registration/EventHandlerRegistration";
import { GeneratorRegistration } from "../../api/registration/GeneratorRegistration";
import { GoalApprovalRequestVoter } from "../../api/registration/GoalApprovalRequestVoter";
import {
GoalApprovalRequestVoteDecisionManager,
GoalApprovalRequestVoter,
UnanimousGoalApprovalRequestVoteDecisionManager,
} from "../../api/registration/GoalApprovalRequestVoter";
import { IngesterRegistration } from "../../api/registration/IngesterRegistration";
import { InterpretLog } from "../../spi/log/InterpretedLog";
import { DefaultGoalImplementationMapper } from "../goal/DefaultGoalImplementationMapper";
Expand Down Expand Up @@ -85,6 +86,9 @@ export abstract class AbstractSoftwareDeliveryMachine<O extends SoftwareDelivery

protected readonly goalApprovalRequestVoters: GoalApprovalRequestVoter[] = [];

private goalApprovalRequestVoteDecisionManager: GoalApprovalRequestVoteDecisionManager =
UnanimousGoalApprovalRequestVoteDecisionManager;

private pushMap: GoalSetter;

private fulfillmentMapper;
Expand Down Expand Up @@ -142,6 +146,11 @@ export abstract class AbstractSoftwareDeliveryMachine<O extends SoftwareDelivery
return this;
}

public setGoalApprovalRequestVoteDecisionManager(manager: GoalApprovalRequestVoteDecisionManager): this {
this.goalApprovalRequestVoteDecisionManager = manager;
return this;
}

public addCommand<P>(cmd: CommandHandlerRegistration<P>): this {
this.registrationManager.addCommand(cmd);
return this;
Expand Down
11 changes: 10 additions & 1 deletion lib/api/machine/GoalDrivenMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import { GoalImplementationMapper } from "../goal/support/GoalImplementationMapp
import { PushListenerInvocation } from "../listener/PushListener";
import { GoalSetter } from "../mapping/GoalSetter";
import { PushMapping } from "../mapping/PushMapping";
import { GoalApprovalRequestVoter } from "../registration/GoalApprovalRequestVoter";
import {
GoalApprovalRequestVoteDecisionManager,
GoalApprovalRequestVoter,
} from "../registration/GoalApprovalRequestVoter";
import { MachineConfiguration } from "./MachineConfiguration";
import { SoftwareDeliveryMachineConfiguration } from "./SoftwareDeliveryMachineOptions";

Expand Down Expand Up @@ -74,4 +77,10 @@ export interface GoalDrivenMachine<O extends SoftwareDeliveryMachineConfiguratio
*/
addGoalApprovalRequestVoter(vote: GoalApprovalRequestVoter): this;

/**
* Set the decision manager used to make final decision on GoalApprovalRequestVoteResult instances.
* @param manager
*/
setGoalApprovalRequestVoteDecisionManager(manager: GoalApprovalRequestVoteDecisionManager): this;

}
49 changes: 39 additions & 10 deletions lib/api/registration/GoalApprovalRequestVoter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,33 @@
* limitations under the License.
*/

import { logger } from "@atomist/automation-client";
import { RepoContext } from "../context/SdmContext";
import { SdmGoalEvent } from "../goal/SdmGoalEvent";

/**
* Represents a vote on a approval request.
* Represents a vote on a approval request
*/
export enum GoalApprovalRequestVote {

/**
* Voter decided to abstain from voting.
* Voter decided to abstain from voting
*/
Abstain,
Abstain = "abstain",

/**
* Voter decided to grant the approval request.
* Voter decided to grant the approval request
*/
Granted,
Granted = "granted",

/**
* Voter decided to deny the approval request.
* Voter decided to deny the approval request
*/
Denied,
Denied = "denied",
}

/**
* Result from executing GoalApprovalRequestVoter.
* Result from executing GoalApprovalRequestVoter
*/
export interface GoalApprovalRequestVoteResult {

Expand All @@ -60,13 +61,41 @@ export interface GoalApprovalRequestVoteResult {
export interface GoalApprovalRequestVoterInvocation extends RepoContext {

/**
* Goal that was requested for approval.
* Goal that was requested for approval
*/
goal: SdmGoalEvent;
}

/**
* Voter on a request to approve a goal.
* Voter on a request to approve a goal
*/
export type GoalApprovalRequestVoter =
(garvi: GoalApprovalRequestVoterInvocation) => Promise<GoalApprovalRequestVoteResult>;

/**
* Decide resulting vote on a set of votes
*/
export type GoalApprovalRequestVoteDecisionManager =
(votes: GoalApprovalRequestVoteResult[]) => GoalApprovalRequestVote;


/**
* Default GoalApprovalRequestVoteDecisionManager that decides unanimously on votes.
* One denied vote will deny the approval request; all granted votes with grant the request.
* All other votes with result in an abstained approval request.
* @param votes
*/
export const UnanimousGoalApprovalRequestVoteDecisionManager: GoalApprovalRequestVoteDecisionManager =
(votes: GoalApprovalRequestVoteResult[]) => {
logger.debug(`Deciding on provided votes '${votes.map(v => v.vote).join(", ")}'`);
if (votes.some(v => v.vote === GoalApprovalRequestVote.Denied)) {
logger.debug("At least one denied vote. Denying approval request");
return GoalApprovalRequestVote.Denied;
} else if (!votes.some(v => v.vote !== GoalApprovalRequestVote.Granted)) {
logger.debug("All votes granted. Granting approval request");
return GoalApprovalRequestVote.Granted;
} else {
logger.debug("Some abstain and granted votes. Abstaining approval request");
return GoalApprovalRequestVote.Abstain;
}
};

0 comments on commit 68ff03e

Please sign in to comment.