"""
[![cloudcomponents Logo](https://raw.githubusercontent.com/cloudcomponents/cdk-constructs/master/logo.png)](https://github.com/cloudcomponents/cdk-constructs)

# @cloudcomponents/cdk-pull-request-check

[![Build Status](https://travis-ci.org/cloudcomponents/cdk-constructs.svg?branch=master)](https://travis-ci.org/cloudcomponents/cdk-constructs)
[![cdkdx](https://img.shields.io/badge/buildtool-cdkdx-blue.svg)](https://github.com/hupe1980/cdkdx)
[![typescript](https://img.shields.io/badge/jsii-typescript-blueviolet.svg)](https://www.npmjs.com/package/@cloudcomponents/cdk-pull-request-check)
[![python](https://img.shields.io/badge/jsii-python-blueviolet.svg)](https://pypi.org/project/cloudcomponents.cdk-pull-request-check/)

> Cdk component that automatically check pull requests

## Install

TypeScript/JavaScript:

```bash
npm install --save @cloudcomponents/cdk-pull-request-check
```

Python:

```bash
pip install cloudcomponents.cdk-pull-request-check
```

## How to use

```python
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
from aws_cdk.core import Construct, Stack, StackProps
from aws_cdk.aws_codecommit import Repository
from aws_cdk.aws_codebuild import BuildSpec
from cloudcomponents.cdk_pull_request_check import PullRequestCheck

class CodePipelineStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, synthesizer=None, terminationProtection=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, synthesizer=synthesizer, terminationProtection=terminationProtection)

        repository = Repository(self, "Repository",
            repository_name="MyRepositoryName"
        )

        # CodePipeline etc.

        PullRequestCheck(self, "PullRequestCheck",
            repository=repository,
            build_spec=BuildSpec.from_source_filename("prcheck.yml")
        )
```

## Approval Template Rules

```python
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
from aws_cdk.core import Construct, Stack, StackProps
from aws_cdk.aws_codecommit import Repository
from aws_cdk.aws_codebuild import BuildSpec
from cloudcomponents.cdk_pull_request_check import PullRequestCheck
from cloudcomponents.cdk_pull_request_approval_rule import ApprovalRuleTemplate, ApprovalRuleTemplateRepositoryAssociation

class CodePipelinePullRequestCheckStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, synthesizer=None, terminationProtection=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, synthesizer=synthesizer, terminationProtection=terminationProtection)

        repository = Repository(self, "Repository",
            repository_name="repository"
        )

        { approvalRuleTemplateName } = ApprovalRuleTemplate(self, "ApprovalRuleTemplate",
            approval_rule_template_name="Require 1 approver",
            template=Template(
                approvers=Approvers(
                    number_of_approvals_needed=1
                )
            )
        )

        ApprovalRuleTemplateRepositoryAssociation(self, "ApprovalRuleTemplateRepositoryAssociation",
            approval_rule_template_name=approval_rule_template_name,
            repository=repository
        )

        # Approves the pull request
        PullRequestCheck(self, "PullRequestCheck",
            repository=repository,
            build_spec=BuildSpec.from_source_filename("prcheck.yml")
        )
```

## Custom notifications

The component comments the pull request and sets the approval state by default. Custom notifications can be set up this way

```python
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
from aws_cdk.core import Construct, Stack, StackProps
from aws_cdk.aws_codecommit import Repository
from aws_cdk.aws_codebuild import BuildSpec
from aws_cdk.aws_events_targets import SnsTopic
from aws_cdk.aws_sns import Topic
from aws_cdk.aws_sns_subscriptions import EmailSubscription
from cloudcomponents.cdk_pull_request_check import PullRequestCheck

class CodePipelineStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, synthesizer=None, terminationProtection=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, synthesizer=synthesizer, terminationProtection=terminationProtection)

        repository = Repository(self, "Repository",
            repository_name="MyRepositoryName",
            description="Some description."
        )

        # Your CodePipeline...

        pr_check = PullRequestCheck(self, "PullRequestCheck",
            repository=repository,
            build_spec=BuildSpec.from_source_filename("buildspecs/prcheck.yml")
        )

        pr_topic = Topic(self, "PullRequestTopic")

        pr_topic.add_subscription(
            EmailSubscription(process.env.DEVSECOPS_TEAM_EMAIL))

        pr_check.on_check_started("started",
            target=SnsTopic(pr_topic)
        )

        pr_check.on_check_succeeded("succeeded",
            target=SnsTopic(pr_topic)
        )

        pr_check.on_check_failed("failed",
            target=SnsTopic(pr_topic)
        )
```

## API Reference

See [API.md](https://github.com/cloudcomponents/cdk-constructs/tree/master/packages/cdk-pull-request-check/API.md).

## Example

See more complete [examples](https://github.com/cloudcomponents/cdk-constructs/tree/master/examples).

## License

[MIT](https://github.com/cloudcomponents/cdk-constructs/tree/master/packages/cdk-pull-request-check/LICENSE)
"""
import abc
import builtins
import datetime
import enum
import typing

import jsii
import jsii.compat
import publication

from ._jsii import *

import aws_cdk.aws_codebuild
import aws_cdk.aws_codecommit
import aws_cdk.aws_events
import aws_cdk.aws_iam
import aws_cdk.core


class PullRequestCheck(
    aws_cdk.core.Construct,
    metaclass=jsii.JSIIMeta,
    jsii_type="@cloudcomponents/cdk-pull-request-check.PullRequestCheck",
):
    """Represents a reference to a PullRequestCheck."""

    def __init__(
        self,
        scope: aws_cdk.core.Construct,
        id: str,
        *,
        build_spec: aws_cdk.aws_codebuild.BuildSpec,
        repository: aws_cdk.aws_codecommit.IRepository,
        build_image: typing.Optional[aws_cdk.aws_codebuild.IBuildImage] = None,
        compute_type: typing.Optional[aws_cdk.aws_codebuild.ComputeType] = None,
        post_comment: typing.Optional[bool] = None,
        privileged: typing.Optional[bool] = None,
        project_name: typing.Optional[str] = None,
        role: typing.Optional[aws_cdk.aws_iam.IRole] = None,
        update_approval_state: typing.Optional[bool] = None,
    ) -> None:
        """
        :param scope: -
        :param id: -
        :param build_spec: Filename or contents of buildspec in JSON format.
        :param repository: The CodeCommit repository.
        :param build_image: Build environment to use for the build. Default: BuildEnvironment.LinuxBuildImage.STANDARD_2_0
        :param compute_type: The type of compute to use for this build. See the {@link ComputeType} enum for the possible values. Default: taken from {@link #buildImage#defaultComputeType}
        :param post_comment: Specifies whether comments should be written in the request. Default: true
        :param privileged: Indicates how the project builds Docker images. Specify true to enable running the Docker daemon inside a Docker container. This value must be set to true only if this build project will be used to build Docker images, and the specified build environment image is not one provided by AWS CodeBuild with Docker support. Otherwise, all associated builds that attempt to interact with the Docker daemon will fail. Default: false
        :param project_name: The human-visible name of this PullRequest-Project. - @default taken from {@link #repository:#repositoryName}-pull-request
        :param role: The IAM service Role of the Project.
        :param update_approval_state: Indicates whether the approval state [APPROVE, REVOKE] should be updated. Default: true
        """
        props = PullRequestCheckProps(
            build_spec=build_spec,
            repository=repository,
            build_image=build_image,
            compute_type=compute_type,
            post_comment=post_comment,
            privileged=privileged,
            project_name=project_name,
            role=role,
            update_approval_state=update_approval_state,
        )

        jsii.create(PullRequestCheck, self, [scope, id, props])

    @jsii.member(jsii_name="addToRolePolicy")
    def add_to_role_policy(self, statement: aws_cdk.aws_iam.PolicyStatement) -> None:
        """Add a permission only if there's a policy attached.

        :param statement: The permissions statement to add.
        """
        return jsii.invoke(self, "addToRolePolicy", [statement])

    @jsii.member(jsii_name="onCheckFailed")
    def on_check_failed(
        self,
        id: str,
        *,
        description: typing.Optional[str] = None,
        event_pattern: typing.Optional[aws_cdk.aws_events.EventPattern] = None,
        rule_name: typing.Optional[str] = None,
        target: typing.Optional[aws_cdk.aws_events.IRuleTarget] = None,
    ) -> aws_cdk.aws_events.Rule:
        """Defines an event rule which triggers when a check fails.

        :param id: -
        :param description: A description of the rule's purpose. Default: - No description
        :param event_pattern: Additional restrictions for the event to route to the specified target. The method that generates the rule probably imposes some type of event filtering. The filtering implied by what you pass here is added on top of that filtering. Default: - No additional filtering based on an event pattern.
        :param rule_name: A name for the rule. Default: AWS CloudFormation generates a unique physical ID.
        :param target: The target to register for the event. Default: - No target is added to the rule. Use ``addTarget()`` to add a target.
        """
        options = aws_cdk.aws_events.OnEventOptions(
            description=description,
            event_pattern=event_pattern,
            rule_name=rule_name,
            target=target,
        )

        return jsii.invoke(self, "onCheckFailed", [id, options])

    @jsii.member(jsii_name="onCheckStarted")
    def on_check_started(
        self,
        id: str,
        *,
        description: typing.Optional[str] = None,
        event_pattern: typing.Optional[aws_cdk.aws_events.EventPattern] = None,
        rule_name: typing.Optional[str] = None,
        target: typing.Optional[aws_cdk.aws_events.IRuleTarget] = None,
    ) -> aws_cdk.aws_events.Rule:
        """Defines an event rule which triggers when a check starts.

        :param id: -
        :param description: A description of the rule's purpose. Default: - No description
        :param event_pattern: Additional restrictions for the event to route to the specified target. The method that generates the rule probably imposes some type of event filtering. The filtering implied by what you pass here is added on top of that filtering. Default: - No additional filtering based on an event pattern.
        :param rule_name: A name for the rule. Default: AWS CloudFormation generates a unique physical ID.
        :param target: The target to register for the event. Default: - No target is added to the rule. Use ``addTarget()`` to add a target.
        """
        options = aws_cdk.aws_events.OnEventOptions(
            description=description,
            event_pattern=event_pattern,
            rule_name=rule_name,
            target=target,
        )

        return jsii.invoke(self, "onCheckStarted", [id, options])

    @jsii.member(jsii_name="onCheckSucceeded")
    def on_check_succeeded(
        self,
        id: str,
        *,
        description: typing.Optional[str] = None,
        event_pattern: typing.Optional[aws_cdk.aws_events.EventPattern] = None,
        rule_name: typing.Optional[str] = None,
        target: typing.Optional[aws_cdk.aws_events.IRuleTarget] = None,
    ) -> aws_cdk.aws_events.Rule:
        """Defines an event rule which triggers when a check complets successfully.

        :param id: -
        :param description: A description of the rule's purpose. Default: - No description
        :param event_pattern: Additional restrictions for the event to route to the specified target. The method that generates the rule probably imposes some type of event filtering. The filtering implied by what you pass here is added on top of that filtering. Default: - No additional filtering based on an event pattern.
        :param rule_name: A name for the rule. Default: AWS CloudFormation generates a unique physical ID.
        :param target: The target to register for the event. Default: - No target is added to the rule. Use ``addTarget()`` to add a target.
        """
        options = aws_cdk.aws_events.OnEventOptions(
            description=description,
            event_pattern=event_pattern,
            rule_name=rule_name,
            target=target,
        )

        return jsii.invoke(self, "onCheckSucceeded", [id, options])


@jsii.data_type(
    jsii_type="@cloudcomponents/cdk-pull-request-check.PullRequestCheckProps",
    jsii_struct_bases=[],
    name_mapping={
        "build_spec": "buildSpec",
        "repository": "repository",
        "build_image": "buildImage",
        "compute_type": "computeType",
        "post_comment": "postComment",
        "privileged": "privileged",
        "project_name": "projectName",
        "role": "role",
        "update_approval_state": "updateApprovalState",
    },
)
class PullRequestCheckProps:
    def __init__(
        self,
        *,
        build_spec: aws_cdk.aws_codebuild.BuildSpec,
        repository: aws_cdk.aws_codecommit.IRepository,
        build_image: typing.Optional[aws_cdk.aws_codebuild.IBuildImage] = None,
        compute_type: typing.Optional[aws_cdk.aws_codebuild.ComputeType] = None,
        post_comment: typing.Optional[bool] = None,
        privileged: typing.Optional[bool] = None,
        project_name: typing.Optional[str] = None,
        role: typing.Optional[aws_cdk.aws_iam.IRole] = None,
        update_approval_state: typing.Optional[bool] = None,
    ) -> None:
        """
        :param build_spec: Filename or contents of buildspec in JSON format.
        :param repository: The CodeCommit repository.
        :param build_image: Build environment to use for the build. Default: BuildEnvironment.LinuxBuildImage.STANDARD_2_0
        :param compute_type: The type of compute to use for this build. See the {@link ComputeType} enum for the possible values. Default: taken from {@link #buildImage#defaultComputeType}
        :param post_comment: Specifies whether comments should be written in the request. Default: true
        :param privileged: Indicates how the project builds Docker images. Specify true to enable running the Docker daemon inside a Docker container. This value must be set to true only if this build project will be used to build Docker images, and the specified build environment image is not one provided by AWS CodeBuild with Docker support. Otherwise, all associated builds that attempt to interact with the Docker daemon will fail. Default: false
        :param project_name: The human-visible name of this PullRequest-Project. - @default taken from {@link #repository:#repositoryName}-pull-request
        :param role: The IAM service Role of the Project.
        :param update_approval_state: Indicates whether the approval state [APPROVE, REVOKE] should be updated. Default: true
        """
        self._values = {
            "build_spec": build_spec,
            "repository": repository,
        }
        if build_image is not None:
            self._values["build_image"] = build_image
        if compute_type is not None:
            self._values["compute_type"] = compute_type
        if post_comment is not None:
            self._values["post_comment"] = post_comment
        if privileged is not None:
            self._values["privileged"] = privileged
        if project_name is not None:
            self._values["project_name"] = project_name
        if role is not None:
            self._values["role"] = role
        if update_approval_state is not None:
            self._values["update_approval_state"] = update_approval_state

    @builtins.property
    def build_spec(self) -> aws_cdk.aws_codebuild.BuildSpec:
        """Filename or contents of buildspec in JSON format.

        see
        :see: https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec-ref-example
        """
        return self._values.get("build_spec")

    @builtins.property
    def repository(self) -> aws_cdk.aws_codecommit.IRepository:
        """The CodeCommit repository."""
        return self._values.get("repository")

    @builtins.property
    def build_image(self) -> typing.Optional[aws_cdk.aws_codebuild.IBuildImage]:
        """Build environment to use for the build.

        default
        :default: BuildEnvironment.LinuxBuildImage.STANDARD_2_0
        """
        return self._values.get("build_image")

    @builtins.property
    def compute_type(self) -> typing.Optional[aws_cdk.aws_codebuild.ComputeType]:
        """The type of compute to use for this build.

        See the {@link ComputeType} enum for the possible values.

        default
        :default: taken from {@link #buildImage#defaultComputeType}
        """
        return self._values.get("compute_type")

    @builtins.property
    def post_comment(self) -> typing.Optional[bool]:
        """Specifies whether comments should be written in the request.

        default
        :default: true
        """
        return self._values.get("post_comment")

    @builtins.property
    def privileged(self) -> typing.Optional[bool]:
        """Indicates how the project builds Docker images.

        Specify true to enable
        running the Docker daemon inside a Docker container. This value must be
        set to true only if this build project will be used to build Docker
        images, and the specified build environment image is not one provided by
        AWS CodeBuild with Docker support. Otherwise, all associated builds that
        attempt to interact with the Docker daemon will fail.

        default
        :default: false
        """
        return self._values.get("privileged")

    @builtins.property
    def project_name(self) -> typing.Optional[str]:
        """The human-visible name of this PullRequest-Project.

        - @default taken from {@link #repository:#repositoryName}-pull-request
        """
        return self._values.get("project_name")

    @builtins.property
    def role(self) -> typing.Optional[aws_cdk.aws_iam.IRole]:
        """The IAM service Role of the Project."""
        return self._values.get("role")

    @builtins.property
    def update_approval_state(self) -> typing.Optional[bool]:
        """Indicates whether the approval state [APPROVE, REVOKE] should be updated.

        default
        :default: true
        """
        return self._values.get("update_approval_state")

    def __eq__(self, rhs) -> bool:
        return isinstance(rhs, self.__class__) and rhs._values == self._values

    def __ne__(self, rhs) -> bool:
        return not (rhs == self)

    def __repr__(self) -> str:
        return "PullRequestCheckProps(%s)" % ", ".join(
            k + "=" + repr(v) for k, v in self._values.items()
        )


__all__ = [
    "PullRequestCheck",
    "PullRequestCheckProps",
]

publication.publish()
