예제 #1
0
    def validate(self, attrs: Mapping[str, Any]) -> Mapping[str, Any]:
        # If it already exists, set default attrs with existing values
        if self.instance:
            attrs = {
                "raw": self.instance.raw,
                "code_mapping_id": self.instance.repository_project_path_config,
                **attrs,
            }

        if not attrs.get("raw", "").strip():
            return attrs

        # Ignore association errors and continue parsing CODEOWNERS for valid lines.
        # Allow users to incrementally fix association errors; for CODEOWNERS with many external mappings.
        associations, _ = ProjectCodeOwners.validate_codeowners_associations(
            attrs, self.context["project"]
        )

        issue_owner_rules = convert_codeowners_syntax(
            attrs["raw"], associations, attrs["code_mapping_id"]
        )

        # Convert IssueOwner syntax into schema syntax
        validated_data = ProjectOwnershipSerializer(context=self.context).validate(
            {"raw": issue_owner_rules}
        )

        return {**validated_data, **attrs}
예제 #2
0
    def validate(self, attrs: Mapping[str, Any]) -> Mapping[str, Any]:
        # If it already exists, set default attrs with existing values
        if self.instance:
            attrs = {
                "raw": self.instance.raw,
                "code_mapping_id":
                self.instance.repository_project_path_config,
                **attrs,
            }

        if not attrs.get("raw", "").strip():
            return attrs

        external_association_err: List[str] = []
        # Get list of team/user names from CODEOWNERS file
        team_names, usernames, emails = parse_code_owners(attrs["raw"])

        # Check if there exists Sentry users with the emails listed in CODEOWNERS
        user_emails = UserEmail.objects.filter(
            email__in=emails,
            user__sentry_orgmember_set__organization=self.context["project"].
            organization,
        )

        user_emails_diff = validate_association(emails, user_emails, "emails")
        external_association_err.extend(user_emails_diff)

        # Check if the usernames have an association
        external_actors = ExternalActor.objects.filter(
            external_name__in=usernames + team_names,
            organization=self.context["project"].organization,
        )

        external_users_diff = validate_association(usernames, external_actors,
                                                   "usernames")
        external_association_err.extend(external_users_diff)

        external_teams_diff = validate_association(team_names, external_actors,
                                                   "team names")
        external_association_err.extend(external_teams_diff)

        if len(external_association_err):
            raise serializers.ValidationError(
                {"raw": "\n".join(external_association_err)})

        # Convert CODEOWNERS into IssueOwner syntax
        users_dict = {}
        teams_dict = {}
        for external_actor in external_actors:
            type = actor_type_to_string(external_actor.actor.type)
            if type == "user":
                user = external_actor.actor.resolve()
                users_dict[external_actor.external_name] = user.email
            elif type == "team":
                team = external_actor.actor.resolve()
                teams_dict[external_actor.external_name] = f"#{team.slug}"

        emails_dict = {email: email for email in emails}
        associations = {**users_dict, **teams_dict, **emails_dict}

        issue_owner_rules = convert_codeowners_syntax(attrs["raw"],
                                                      associations,
                                                      attrs["code_mapping_id"])

        # Convert IssueOwner syntax into schema syntax
        validated_data = ProjectOwnershipSerializer(
            context=self.context).validate({"raw": issue_owner_rules})

        return {**validated_data, **attrs}
예제 #3
0
    def validate(self, attrs):
        # If it already exists, set default attrs with existing values
        if self.instance:
            attrs = {
                "raw": self.instance.raw,
                "code_mapping_id":
                self.instance.repository_project_path_config,
                **attrs,
            }

        if not attrs.get("raw", "").strip():
            return attrs
        external_association_err = []
        # Get list of team/user names from CODEOWNERS file
        teamnames, usernames, emails = parse_code_owners(attrs["raw"])

        # Check if there exists Sentry users with the emails listed in CODEOWNERS
        user_emails = UserEmail.objects.filter(email__in=emails)
        user_emails_diff = self._validate_association(emails, user_emails,
                                                      "emails")

        external_association_err.extend(user_emails_diff)

        # Check if the usernames have an association
        external_users = ExternalUser.objects.filter(
            external_name__in=usernames,
            organizationmember__organization=self.context["project"].
            organization,
        )

        external_users_diff = self._validate_association(
            usernames, external_users, "usernames")

        external_association_err.extend(external_users_diff)

        # Check if the team names have an association
        external_teams = ExternalTeam.objects.filter(
            external_name__in=teamnames,
            team__organization=self.context["project"].organization,
        )

        external_teams_diff = self._validate_association(
            teamnames, external_teams, "team names")

        external_association_err.extend(external_teams_diff)

        if len(external_association_err):
            raise serializers.ValidationError(
                {"raw": "\n".join(external_association_err)})

        # Convert CODEOWNERS into IssueOwner syntax
        users_dict = {
            user.external_name: user.organizationmember.user.email
            for user in external_users
        }
        teams_dict = {
            team.external_name: f"#{team.team.slug}"
            for team in external_teams
        }
        emails_dict = {email: email for email in emails}
        associations = {**users_dict, **teams_dict, **emails_dict}

        issue_owner_rules = convert_codeowners_syntax(attrs["raw"],
                                                      associations,
                                                      attrs["code_mapping_id"])

        # Convert IssueOwner syntax into schema syntax
        validated_data = ProjectOwnershipSerializer(
            context=self.context).validate({"raw": issue_owner_rules})

        return {**validated_data, **attrs}