From 0bb91bc029597cbc4a0b1e577a352c01fb4fc84d Mon Sep 17 00:00:00 2001
From: mprahl <mprahl@redhat.com>
Date: Jan 11 2018 15:02:13 +0000
Subject: Stop allowing EPEL branches on official EL packages


Signed-off-by: mprahl <mprahl@redhat.com>

---

diff --git a/fedpkg/cli.py b/fedpkg/cli.py
index 0e8fb6b..2bf8b72 100644
--- a/fedpkg/cli.py
+++ b/fedpkg/cli.py
@@ -25,7 +25,7 @@ from pyrpkg import rpkgError
 from fedpkg.bugzilla import BugzillaClient
 from fedpkg.utils import (
     get_release_branches, sl_list_to_dict, verify_sls, new_pagure_issue,
-    get_pagure_token)
+    get_pagure_token, is_epel, assert_valid_epel_package)
 
 
 class fedpkgClient(cliClient):
@@ -321,6 +321,9 @@ suggest_reboot=False
 
         bodhi_url = self.config.get('{0}.bodhi'.format(self.name), 'url')
         if branch:
+            if is_epel(branch):
+                assert_valid_epel_package(self.cmd.module_name, branch)
+
             if self.cmd.ns in ['modules', 'test-modules']:
                 branch_valid = bool(re.match(r'^[a-zA-Z0-9.\-_+]+$', branch))
                 if not branch_valid:
diff --git a/fedpkg/utils.py b/fedpkg/utils.py
index a4bffc8..d241308 100644
--- a/fedpkg/utils.py
+++ b/fedpkg/utils.py
@@ -185,3 +185,61 @@ def get_pagure_token(config, cli_name):
         raise rpkgError('The "token" value must be set under the "{0}" '
                         'section in your "{1}" user configuration'
                         .format(conf_section, cli_name))
+
+
+def is_epel(branch):
+    """
+    Determines if this is or will be an epel branch
+    :param branch: a string of the branch name
+    :return: a boolean
+    """
+    return bool(re.match(r'^(?:el|epel)\d+$', branch))
+
+
+def assert_valid_epel_package(name, branch):
+    """
+    Determines if the package is allowed to have an EPEL branch. If it can't,
+    an rpkgError will be raised.
+    :param name: a string of the package name
+    :param branch: a string of the EPEL branch name (e.g. epel7)
+    :return: None or rpkgError
+    """
+    # Extract any digits in the branch name to determine the EL version
+    version = ''.join([i for i in branch if re.match(r'\d', i)])
+    url = ('https://infrastructure.fedoraproject.org/repo/json/pkg_el{0}.json'
+           .format(version))
+    error_msg = ('The connection to infrastructure.fedoraproject.org failed '
+                 'while trying to determine if this is a valid EPEL package.')
+    try:
+        rv = requests.get(url, timeout=60)
+    except ConnectionError as error:
+        error_msg += ' The error was: {0}'.format(str(error))
+        raise rpkgError(error_msg)
+
+    if not rv.ok:
+        raise rpkgError(error_msg + ' The status code was: {0}'.format(
+            rv.status_code))
+
+    rv_json = rv.json()
+    # Remove noarch from this because noarch is treated specially
+    all_arches = set(rv_json['arches']) - set(['noarch'])
+    # On EL6, also remove ppc and i386 as many packages will
+    # have these arches missing and cause false positives
+    if int(version) == 6:
+        all_arches = all_arches - set(['ppc', 'i386'])
+    # On EL7 and later, also remove ppc and i686 as many packages will
+    # have these arches missing and cause false positives
+    elif int(version) >= 7:
+        all_arches = all_arches - set(['ppc', 'i686'])
+
+    error_msg_two = (
+        'This package is already an EL package and is built on all supported '
+        'arches, therefore, it cannot be in EPEL. If this is a mistake or you '
+        'have an exception, please contact the Release Engineering team.')
+    for pkg_name, pkg_info in rv_json['packages'].items():
+        # If the EL package is noarch only or is available on all supported
+        # arches, then don't allow an EPEL branch
+        if pkg_name == name:
+            pkg_arches = set(pkg_info['arch'])
+            if pkg_arches == set(['noarch']) or not (all_arches - pkg_arches):
+                raise rpkgError(error_msg_two)
diff --git a/test/test_cli.py b/test/test_cli.py
index 7d177ca..c3e0a73 100644
--- a/test/test_cli.py
+++ b/test/test_cli.py
@@ -954,3 +954,32 @@ https://pagure.stg.example.com/releng/fedora-scm-requests/issue/3"""
             self.assertEqual(str(error), expected_error)
         finally:
             rmdir(tempdir)
+
+    @patch('requests.get')
+    def test_request_branch_invalid_epel_package(self, mock_get):
+        """Test request-branch raises an exception when an EPEL branch is
+        requested but ths package is already an EL package on all supported
+        arches"""
+        mock_rv = Mock()
+        mock_rv.ok = True
+        mock_rv.json.return_value = {
+            'arches': ['noarch', 'x86_64', 'i686', 'ppc64', 'ppc', 'ppc64le'],
+            'packages': {
+                'kernel': {'arch': [
+                    'noarch', 'x86_64', 'ppc64', 'ppc64le']},
+                'glibc': {'arch': [
+                    'i686', 'x86_64', 'ppc', 'ppc64', 'ppc64le']}
+            }
+        }
+        mock_get.return_value = mock_rv
+
+        cli_cmd = ['fedpkg-stage', '--path', self.cloned_repo_path,
+                   '--module-name', 'kernel', 'request-branch', 'epel7']
+        cli = self.get_cli(cli_cmd)
+        expected_error = (
+            'This package is already an EL package and is built on all '
+            'supported arches, therefore, it cannot be in EPEL. If this is a '
+            'mistake or you have an exception, please contact the Release '
+            'Engineering team.')
+        with six.assertRaisesRegex(self, rpkgError, expected_error):
+            cli.request_branch()

