diff --git a/pagure/hooks/pagure_ci.py b/pagure/hooks/pagure_ci.py index ee999a8..795a050 100644 --- a/pagure/hooks/pagure_ci.py +++ b/pagure/hooks/pagure_ci.py @@ -46,6 +46,8 @@ class PagureCITable(BASE): ci_type = sa.Column(sa.String(255), nullable=True) ci_url = sa.Column(sa.String(255), nullable=True, unique=False) ci_job = sa.Column(sa.String(255), nullable=True, unique=False) + ci_username = sa.Column(sa.String(255), nullable=True, unique=False) + ci_password = sa.Column(sa.String(255), nullable=True, unique=False) active = sa.Column(sa.Boolean, nullable=False, default=False) active_commit = sa.Column(sa.Boolean, nullable=False, default=False) active_pr = sa.Column(sa.Boolean, nullable=False, default=False) @@ -114,6 +116,16 @@ class PagureCiForm(FlaskForm): ], ) + ci_username = wtforms.StringField( + "Username to authenticate with if needed", + [wtforms.validators.Optional(), wtforms.validators.Length(max=255)], + ) + + ci_password = wtforms.StringField( + "Password to authenticate with if needed", + [wtforms.validators.Optional(), wtforms.validators.Length(max=255)], + ) + ci_job = wtforms.StringField( "Name of the job to trigger", [ diff --git a/pagure/lib/lib_ci.py b/pagure/lib/lib_ci.py index f2a30ec..eba958a 100644 --- a/pagure/lib/lib_ci.py +++ b/pagure/lib/lib_ci.py @@ -42,7 +42,11 @@ def process_jenkins_build(session, project, build_id, iteration=0): # Jenkins Base URL _log.info("Querying jenkins at: %s", project.ci_hook.ci_url) - jenk = jenkins.Jenkins(project.ci_hook.ci_url) + jenk = jenkins.Jenkins( + project.ci_hook.ci_url, + username=project.ci_hook.ci_username or None, + password=project.ci_hook.ci_password or None, + ) jenkins_name = project.ci_hook.ci_job _log.info( "Querying jenkins for project: %s, build: %s", jenkins_name, build_id @@ -130,7 +134,15 @@ def process_jenkins_build(session, project, build_id, iteration=0): def trigger_jenkins_build( - project_path, url, job, token, branch, branch_to, cause + project_path, + url, + job, + token, + branch, + branch_to, + cause, + ci_username=None, + ci_password=None, ): """ Trigger a build on a jenkins instance.""" try: @@ -150,7 +162,9 @@ def trigger_jenkins_build( "BRANCH_TO": branch_to, } - server = jenkins.Jenkins(url) + server = jenkins.Jenkins( + url, username=ci_username or None, password=ci_password or None + ) _log.info( "Pagure-CI: Triggering at: %s for: %s - data: %s", url, job, data ) diff --git a/pagure/lib/tasks_services.py b/pagure/lib/tasks_services.py index 4cef4e9..eb78d0a 100644 --- a/pagure/lib/tasks_services.py +++ b/pagure/lib/tasks_services.py @@ -463,23 +463,20 @@ def trigger_ci_build( if ci_type == "jenkins": + jenk_project = project if project.is_fork: - url = project.parent.ci_hook.ci_url - job = project.parent.ci_hook.ci_job - token = project.parent.ci_hook.pagure_ci_token - else: - url = project.ci_hook.ci_url - job = project.ci_hook.ci_job - token = project.ci_hook.pagure_ci_token + jenk_project = project.parent trigger_jenkins_build( project_path=project.path, - url=url, - job=job, - token=token, + url=jenk_project.ci_hook.ci_url, + job=jenk_project.ci_hook.ci_job, + token=jenk_project.ci_hook.pagure_ci_token, branch=branch, branch_to=branch_to, cause=cause, + ci_username=jenk_project.ci_hook.ci_username, + ci_password=jenk_project.ci_hook.ci_password, ) else: diff --git a/tests/test_pagure_flask_ui_plugins_pagure_ci.py b/tests/test_pagure_flask_ui_plugins_pagure_ci.py index 1604dc2..a32aaa1 100644 --- a/tests/test_pagure_flask_ui_plugins_pagure_ci.py +++ b/tests/test_pagure_flask_ui_plugins_pagure_ci.py @@ -6,6 +6,12 @@ import unittest import sys import os +import mock + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import pagure.lib.tasks_services import tests @@ -277,6 +283,101 @@ class PagureFlaskPluginPagureCItests(tests.SimplePagureTest): '
\nhttp://localhost.localdomain/api/0/ci/jenkins/somenamespace/test3/',
                 output_text)
 
+    @mock.patch('pagure.lib.tasks_services.trigger_jenkins_build')
+    def test_plugin_pagure_ci_namespaced_auth(self, trigger_jenk):
+        """ Test the pagure ci plugin on/off endpoint. """
+
+        tests.create_projects(self.session)
+        tests.create_projects_git(os.path.join(self.path, 'repos'))
+
+        user = tests.FakeUser(username='pingou')
+        with tests.user_set(self.app.application, user):
+            output = self.app.get('/somenamespace/test3/settings/Pagure CI')
+            self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
+            self.assertIn(
+                'Settings Pagure CI - somenamespace/test3 - '
+                'Pagure', output_text)
+            self.assertIn(
+                '', output_text)
+            self.assertIn(
+                '', output_text)
+            self.assertIn(
+                '', output_text)
+
+            csrf_token = output_text.split(
+                'name="csrf_token" type="hidden" value="')[1].split('">')[0]
+
+            # Activate hook
+            data = {
+                'active_pr': 'y',
+                'ci_url': 'https://jenkins.fedoraproject.org',
+                'ci_job': 'test/job',
+                'ci_type': 'jenkins',
+                'ci_username': 'jenkins_username',
+                'ci_password': 'jenkins_password',
+                'csrf_token': csrf_token,
+            }
+
+            # Activate hook
+            output = self.app.post(
+                '/somenamespace/test3/settings/Pagure CI', data=data, follow_redirects=True)
+            self.assertEqual(output.status_code, 200)
+            output_text = output.get_data(as_text=True)
+            self.assertIn(
+                '
' + 'Project Settings
\n', output_text) + self.assertIn( + 'Settings - somenamespace/test3 - Pagure', + output_text) + self.assertIn( + '
' + 'Project Settings
\n', output_text) + self.assertIn( + 'Hook Pagure CI activated', + output_text) + + output = self.app.get('/somenamespace/test3/settings/Pagure CI') + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn( + 'Settings Pagure CI - somenamespace/test3 - ' + 'Pagure', output_text) + self.assertIn( + '', output_text) + self.assertIn( + '', output_text) + self.assertIn( + '', output_text) + self.assertIn( + '
\nhttp://localhost.localdomain/api/0/ci/jenkins/somenamespace/test3/',
+                output_text)
+
+        output = pagure.lib.tasks_services.trigger_ci_build(
+            project_name='somenamespace/test3',
+            cause='PR#ID',
+            branch='feature',
+            branch_to='master',
+            ci_type='jenkins')
+        self.assertIsNone(output)
+        trigger_jenk.assert_called_once_with(
+           branch=u'feature',
+           cause=u'PR#ID',
+           ci_password="jenkins_password",
+           ci_username="jenkins_username",
+           job=u'test/job',
+           project_path=u'somenamespace/test3.git',
+           token=mock.ANY,
+           url=u'https://jenkins.fedoraproject.org',
+           branch_to='master',
+        )
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/tests/test_pagure_lib_task_services.py b/tests/test_pagure_lib_task_services.py
index a5063bd..866bbeb 100644
--- a/tests/test_pagure_lib_task_services.py
+++ b/tests/test_pagure_lib_task_services.py
@@ -587,6 +587,8 @@ class PagureLibTaskServicesJenkinsCItests(tests.Modeltests):
         trigger_jenk.assert_called_once_with(
            branch=u'feature',
            cause=u'PR#ID',
+           ci_password=None,
+           ci_username=None,
            job=u'pagure',
            project_path=u'test.git',
            token=u'random_token',
@@ -607,6 +609,118 @@ class PagureLibTaskServicesJenkinsCItests(tests.Modeltests):
         trigger_jenk.assert_called_once_with(
            branch=u'feature',
            cause=u'PR#ID',
+           ci_password=None,
+           ci_username=None,
+           job=u'pagure',
+           project_path=u'forks/foo/test.git',
+           token=u'random_token',
+           url=u'https://ci.server.org/',
+           branch_to='master',
+        )
+
+
+class PagureLibTaskServicesJenkinsCIAuthtests(tests.Modeltests):
+    """ Tests for pagure.lib.task_services """
+
+    maxDiff = None
+
+    def setUp(self):
+        """ Set up the environnment, ran before every tests. """
+        super(PagureLibTaskServicesJenkinsCIAuthtests, self).setUp()
+
+        pagure.config.config['REQUESTS_FOLDER'] = None
+        self.sshkeydir = os.path.join(self.path, 'sshkeys')
+        pagure.config.config['MIRROR_SSHKEYS_FOLDER'] = self.sshkeydir
+
+        tests.create_projects(self.session)
+        project = pagure.lib.query.get_authorized_project(self.session, 'test')
+
+        # Install the plugin at the DB level
+        plugin = pagure.lib.plugins.get_plugin('Pagure CI')
+        dbobj = plugin.db_object()
+        dbobj.ci_url = 'https://ci.server.org/'
+        dbobj.ci_job = 'pagure'
+        dbobj.ci_username = 'jenkins_username'
+        dbobj.ci_password = 'jenkins_password'
+        dbobj.pagure_ci_token = 'random_token'
+        dbobj.project_id = project.id
+        self.session.add(dbobj)
+        self.session.commit()
+
+        # Create a fork of test for foo
+        item = pagure.lib.model.Project(
+            user_id=2,  # foo
+            name='test',
+            is_fork=True,
+            parent_id=1,
+            description='test project #1',
+            hook_token='aaabbbccc_foo',
+        )
+        item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
+        self.session.add(item)
+        self.session.commit()
+
+    @patch('pagure.lib.tasks_services.trigger_jenkins_build')
+    def test_trigger_ci_build_invalid_ci(self, trigger_jenk):
+        """ Test the trigger_ci_build method. """
+        output = pagure.lib.tasks_services.trigger_ci_build(
+            project_name='test',
+            cause='PR#ID',
+            branch='feature',
+            branch_to='master',
+            ci_type='travis')
+        self.assertIsNone(output)
+        trigger_jenk.assert_not_called()
+
+    @patch('pagure.lib.tasks_services.trigger_jenkins_build')
+    def test_trigger_ci_build_invalid_ci_fork(self, trigger_jenk):
+        """ Test the trigger_ci_build method. """
+        output = pagure.lib.tasks_services.trigger_ci_build(
+            project_name='forks/foo/test',
+            cause='PR#ID',
+            branch='feature',
+            branch_to='master',
+            ci_type='travis')
+        self.assertIsNone(output)
+        trigger_jenk.assert_not_called()
+
+    @patch('pagure.lib.tasks_services.trigger_jenkins_build')
+    def test_trigger_ci_build_valid_project(self, trigger_jenk):
+        """ Test the trigger_ci_build method. """
+        output = pagure.lib.tasks_services.trigger_ci_build(
+            project_name='test',
+            cause='PR#ID',
+            branch='feature',
+            branch_to='master',
+            ci_type='jenkins')
+        self.assertIsNone(output)
+        trigger_jenk.assert_called_once_with(
+           branch=u'feature',
+           cause=u'PR#ID',
+           ci_password="jenkins_password",
+           ci_username="jenkins_username",
+           job=u'pagure',
+           project_path=u'test.git',
+           token=u'random_token',
+           url=u'https://ci.server.org/',
+           branch_to='master',
+        )
+
+    @patch('pagure.lib.tasks_services.trigger_jenkins_build')
+    def test_trigger_ci_build_valid_project_fork(self, trigger_jenk):
+        """ Test the trigger_ci_build method. """
+        output = pagure.lib.tasks_services.trigger_ci_build(
+            project_name='forks/foo/test',
+            cause='PR#ID',
+            branch='feature',
+            branch_to='master',
+            ci_type='jenkins')
+        self.assertIsNone(output)
+        trigger_jenk.assert_called_once_with(
+           branch=u'feature',
+           cause=u'PR#ID',
+           ci_password="jenkins_password",
+           ci_username="jenkins_username",
            job=u'pagure',
            project_path=u'forks/foo/test.git',
            token=u'random_token',