| |
@@ -0,0 +1,750 @@
|
| |
+ # -*- coding: utf-8 -*-
|
| |
+
|
| |
+ # SPDX-FileCopyrightText: 2024 Dominik Wombacher <dominik@wombacher.cc>
|
| |
+ #
|
| |
+ # SPDX-License-Identifier: GPL-2.0-or-later
|
| |
+
|
| |
+ import json
|
| |
+ import os
|
| |
+
|
| |
+ import sys
|
| |
+ from mock import patch, Mock, ANY
|
| |
+
|
| |
+ sys.path.insert(
|
| |
+ 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
| |
+ )
|
| |
+
|
| |
+ from pagure.config import config as pagure_config
|
| |
+ from pagure.lib import model
|
| |
+ import pagure.api.ci.generic
|
| |
+ import pagure.lib.tasks_services
|
| |
+ import pagure.lib.query
|
| |
+ import tests
|
| |
+ from pagure.api.ci import BUILD_STATS
|
| |
+
|
| |
+ from pagure.lib.query import get_authorized_project, get_request_by_uid
|
| |
+ _unpatched_get_authorized_project = get_authorized_project
|
| |
+ _unpatched_get_request_by_uid = get_request_by_uid
|
| |
+
|
| |
+
|
| |
+ class PagureApiCiGenerictests(tests.Modeltests):
|
| |
+ """Tests for pagure.lib.task_services"""
|
| |
+
|
| |
+ maxDiff = None
|
| |
+
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ """Set up the environnment, ran before every tests."""
|
| |
+ super(PagureApiCiGenerictests, 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)
|
| |
+
|
| |
+ # Use of '_unpatched_get_authorized_project' because
|
| |
+ # 'pagure.lib.query.get_authorized_project' is mocked for some tests
|
| |
+ project = _unpatched_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.example.com/"
|
| |
+ dbobj.ci_job = "pagure"
|
| |
+ dbobj.pagure_ci_token = "random_token"
|
| |
+ dbobj.project_id = project.id
|
| |
+ dbobj.ci_type = "generic"
|
| |
+ 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()
|
| |
+
|
| |
+ # Create Pull Request in test project
|
| |
+ pr_test = pagure.lib.model.PullRequest(
|
| |
+ id=1,
|
| |
+ uid="720a0568c1274e74966e54b433b2003e",
|
| |
+ title="pr1",
|
| |
+ project_id=item.id,
|
| |
+ project_id_from=project.id,
|
| |
+ branch="main",
|
| |
+ branch_from="feature",
|
| |
+ user_id=project.user_id,
|
| |
+ commit_start="96df1145c3466fb33edbbde327c6f8705627d2eb",
|
| |
+ commit_stop="96df1145c3466fb33edbbde327c6f8705627d2eb",
|
| |
+ )
|
| |
+ self.session.add(pr_test)
|
| |
+ self.session.commit()
|
| |
+
|
| |
+
|
| |
+ def _response_url(self, project: model.Project) -> str:
|
| |
+ return f"%s/api/0/ci/generic/%s" % (pagure_config["APP_URL"][:-1], project.url_path)
|
| |
+
|
| |
+
|
| |
+ def _values_for_required_parameters(self):
|
| |
+ # Use of '_unpatched_get_authorized_project' because
|
| |
+ # 'pagure.lib.query.get_authorized_project' is mocked for some tests
|
| |
+ project = _unpatched_get_authorized_project(self.session, "test")
|
| |
+ ci_url = "https://ci.example.com/"
|
| |
+ ci_job = "pagure"
|
| |
+ ci_token = "random_token"
|
| |
+ branch = "feature"
|
| |
+ branch_to = "main"
|
| |
+
|
| |
+ return project, ci_url, ci_job, ci_token, branch, branch_to
|
| |
+
|
| |
+
|
| |
+ def _values_for_required_parameters_fork(self, user: str):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+
|
| |
+ # Use of '_unpatched_get_authorized_project' because
|
| |
+ # 'pagure.lib.query.get_authorized_project' is mocked for some tests
|
| |
+ project = _unpatched_get_authorized_project(self.session, "test", user=user)
|
| |
+
|
| |
+ return project, ci_url, ci_job, ci_token, branch, branch_to
|
| |
+
|
| |
+
|
| |
+ def test_trigger_ci_build_without_required_args(self,):
|
| |
+ """
|
| |
+ If the mandatory args are not passed, there should be a TypeError exception
|
| |
+ when 'pagure.lib.task_services.trigger_ci_build' eventually calls
|
| |
+ 'pagure.api.ci.generic.trigger_build'
|
| |
+ """
|
| |
+ self.assertRaises(
|
| |
+ TypeError,
|
| |
+ pagure.lib.tasks_services.trigger_ci_build
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def test_trigger_ci_build_pull_request(self,):
|
| |
+ """
|
| |
+ Test that pagure.lib.tasks_services.trigger_ci_build calls
|
| |
+ pagure.api.ci.generic.trigger_build without throwing an Exception.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ cause = "1"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+
|
| |
+ output = pagure.lib.tasks_services.trigger_ci_build(
|
| |
+ cause=cause,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ ci_type="generic",
|
| |
+ project_name = project.name,
|
| |
+ pr_uid = pr_uid,
|
| |
+ )
|
| |
+
|
| |
+ self.assertIsNone(output)
|
| |
+
|
| |
+
|
| |
+ def test_trigger_ci_build_commit(self):
|
| |
+ """
|
| |
+ Test that pagure.lib.tasks_services.trigger_ci_build calls
|
| |
+ pagure.api.ci.generic.trigger_build without throwing an Exception.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ cause = "9c0110e671ffb1e76b629fd23d6a08414ffb44ab"
|
| |
+
|
| |
+ output = pagure.lib.tasks_services.trigger_ci_build(
|
| |
+ cause=cause,
|
| |
+ branch=branch,
|
| |
+ branch_to=None,
|
| |
+ ci_type="generic",
|
| |
+ project_name = project.name,
|
| |
+ pr_uid = None,
|
| |
+ )
|
| |
+
|
| |
+ self.assertIsNone(output)
|
| |
+
|
| |
+
|
| |
+ @patch("pagure.lib.query.get_request_by_uid")
|
| |
+ @patch("pagure.lib.query.get_authorized_project")
|
| |
+ @patch("pagure.api.ci.generic.trigger_build")
|
| |
+ def test_trigger_ci_build_pull_request_called_once(self, trigger_build, get_authorized_project, get_request_by_uid):
|
| |
+ """
|
| |
+ Test that pagure.lib.tasks_services.trigger_ci_build calls
|
| |
+ pagure.api.ci.generic.trigger_build once.
|
| |
+ No further evaluation of failure or success.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ cause = "1"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ pull_request = _unpatched_get_request_by_uid(self.session, pr_uid)
|
| |
+
|
| |
+ # Ensure that the same project obj is used across the test
|
| |
+ get_authorized_project.return_value = project
|
| |
+
|
| |
+ # Ensure that the same pull_request obj is used across the test
|
| |
+ get_request_by_uid.return_value = pull_request
|
| |
+
|
| |
+ output = pagure.lib.tasks_services.trigger_ci_build(
|
| |
+ cause=cause,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ ci_type="generic",
|
| |
+ project_name = project.name,
|
| |
+ pr_uid = pr_uid,
|
| |
+ )
|
| |
+
|
| |
+ self.assertIsNone(output)
|
| |
+
|
| |
+ trigger_build.assert_called_once_with(
|
| |
+ project=project,
|
| |
+ ci_url=project.ci_hook.ci_url,
|
| |
+ ci_job=project.ci_hook.ci_job,
|
| |
+ ci_token=project.ci_hook.pagure_ci_token,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_pull_request=True,
|
| |
+ is_commit=False,
|
| |
+ commit_hash=None,
|
| |
+ pull_request=pull_request,
|
| |
+ ci_username=None,
|
| |
+ ci_password=None
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ @patch("pagure.lib.query.get_authorized_project")
|
| |
+ @patch("pagure.api.ci.generic.trigger_build")
|
| |
+ def test_trigger_ci_build_commit_called_once(self, trigger_build, get_authorized_project):
|
| |
+ """
|
| |
+ Test that pagure.lib.tasks_services.trigger_ci_build calls
|
| |
+ pagure.api.ci.generic.trigger_build once.
|
| |
+ No further evaluation of failure or success.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ cause = "9c0110e671ffb1e76b629fd23d6a08414ffb44ab"
|
| |
+
|
| |
+ # Ensure that the same project obj is used across the test
|
| |
+ get_authorized_project.return_value = project
|
| |
+
|
| |
+ output = pagure.lib.tasks_services.trigger_ci_build(
|
| |
+ cause=cause,
|
| |
+ branch=branch,
|
| |
+ branch_to=None,
|
| |
+ ci_type="generic",
|
| |
+ project_name = project.name,
|
| |
+ pr_uid = None,
|
| |
+ )
|
| |
+
|
| |
+ self.assertIsNone(output)
|
| |
+
|
| |
+ trigger_build.assert_called_once_with(
|
| |
+ project=project,
|
| |
+ ci_url=project.ci_hook.ci_url,
|
| |
+ ci_job=project.ci_hook.ci_job,
|
| |
+ ci_token=project.ci_hook.pagure_ci_token,
|
| |
+ branch=branch,
|
| |
+ branch_to=None,
|
| |
+ is_pull_request=False,
|
| |
+ is_commit=True,
|
| |
+ commit_hash=cause,
|
| |
+ pull_request=None,
|
| |
+ ci_username=None,
|
| |
+ ci_password=None
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def test_outgoing_payload_pull_request(self):
|
| |
+ """
|
| |
+ Validated generated payload for a pull request
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ is_pull_request = True
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ pull_request = _unpatched_get_request_by_uid(self.session, pr_uid)
|
| |
+
|
| |
+ want = {
|
| |
+ "is_pull_request": is_pull_request,
|
| |
+ "is_commit": False,
|
| |
+ "pull_request_id": pull_request.id,
|
| |
+ "pull_request_uid": pull_request.uid,
|
| |
+ "pull_request_url": pull_request.full_url,
|
| |
+ "commit_hash": None,
|
| |
+ "repo_name": project.name,
|
| |
+ "repo_url": project.full_url,
|
| |
+ "fork_name": None,
|
| |
+ "fork_url": None,
|
| |
+ "branch": branch,
|
| |
+ "branch_to": branch_to,
|
| |
+ "response_url": self._response_url(project),
|
| |
+ }
|
| |
+
|
| |
+ got = pagure.api.ci.generic._outgoing_payload(
|
| |
+ project=project,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_pull_request=is_pull_request,
|
| |
+ pull_request=pull_request,
|
| |
+ )
|
| |
+
|
| |
+ self.assertJSONEqual(got, json.dumps(want))
|
| |
+
|
| |
+
|
| |
+ def test_outgoing_payload_pull_request_fork(self):
|
| |
+ """
|
| |
+ Validated generated payload for a pull request from a fork
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters_fork(user="foo")
|
| |
+ is_pull_request = True
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ pull_request = _unpatched_get_request_by_uid(self.session, pr_uid)
|
| |
+
|
| |
+ want = {
|
| |
+ "is_pull_request": is_pull_request,
|
| |
+ "is_commit": False,
|
| |
+ "pull_request_id": pull_request.id,
|
| |
+ "pull_request_uid": pull_request.uid,
|
| |
+ "pull_request_url": pull_request.full_url,
|
| |
+ "commit_hash": None,
|
| |
+ "repo_name": project.parent.name,
|
| |
+ "repo_url": project.parent.full_url,
|
| |
+ "fork_name": project.name,
|
| |
+ "fork_url": project.full_url,
|
| |
+ "branch": branch,
|
| |
+ "branch_to": branch_to,
|
| |
+ "response_url": self._response_url(project),
|
| |
+ }
|
| |
+
|
| |
+ got = pagure.api.ci.generic._outgoing_payload(
|
| |
+ project=project,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_pull_request=is_pull_request,
|
| |
+ pull_request=pull_request,
|
| |
+ )
|
| |
+
|
| |
+ self.assertJSONEqual(got, json.dumps(want))
|
| |
+
|
| |
+
|
| |
+ def test_outgoing_payload_commit(self):
|
| |
+ """
|
| |
+ Validated generated payload for a commit
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ is_commit = True
|
| |
+ commit_hash = "96df1145c3466fb33edbbde327c6f8705627d2eb"
|
| |
+
|
| |
+ want = {
|
| |
+ "is_pull_request": False,
|
| |
+ "is_commit": is_commit,
|
| |
+ "pull_request_id": None,
|
| |
+ "pull_request_uid": None,
|
| |
+ "pull_request_url": None,
|
| |
+ "commit_hash": commit_hash,
|
| |
+ "repo_name": project.name,
|
| |
+ "repo_url": project.full_url,
|
| |
+ "fork_name": None,
|
| |
+ "fork_url": None,
|
| |
+ "branch": branch,
|
| |
+ "branch_to": branch_to,
|
| |
+ "response_url": self._response_url(project),
|
| |
+ }
|
| |
+
|
| |
+ got = pagure.api.ci.generic._outgoing_payload(
|
| |
+ project=project,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_commit=is_commit,
|
| |
+ commit_hash=commit_hash
|
| |
+ )
|
| |
+
|
| |
+ self.assertJSONEqual(got, json.dumps(want))
|
| |
+
|
| |
+
|
| |
+ def test_outgoing_payload_commit_fork(self):
|
| |
+ """
|
| |
+ Validated generated payload for a commit from a fork
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters_fork(user="foo")
|
| |
+ is_commit = True
|
| |
+ commit_hash = "96df1145c3466fb33edbbde327c6f8705627d2eb"
|
| |
+
|
| |
+ want = {
|
| |
+ "is_pull_request": False,
|
| |
+ "is_commit": is_commit,
|
| |
+ "pull_request_id": None,
|
| |
+ "pull_request_uid": None,
|
| |
+ "pull_request_url": None,
|
| |
+ "commit_hash": commit_hash,
|
| |
+ "repo_name": project.parent.name,
|
| |
+ "repo_url": project.parent.full_url,
|
| |
+ "fork_name": project.name,
|
| |
+ "fork_url": project.full_url,
|
| |
+ "branch": branch,
|
| |
+ "branch_to": branch_to,
|
| |
+ "response_url": self._response_url(project),
|
| |
+ }
|
| |
+
|
| |
+ got = pagure.api.ci.generic._outgoing_payload(
|
| |
+ project=project,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_commit=is_commit,
|
| |
+ commit_hash=commit_hash
|
| |
+ )
|
| |
+
|
| |
+ self.assertJSONEqual(got, json.dumps(want))
|
| |
+
|
| |
+
|
| |
+ def test_trigger_build_commit_and_pull_request(self):
|
| |
+ """
|
| |
+ Failing with PagureException expected when 'is_commit' and 'is_pull_request' are True
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ is_commit = True
|
| |
+ commit_hash = "96df1145c3466fb33edbbde327c6f8705627d2eb"
|
| |
+ is_pull_request = True
|
| |
+
|
| |
+ self.assertRaises(
|
| |
+ pagure.exceptions.PagureException,
|
| |
+ pagure.api.ci.generic.trigger_build,
|
| |
+ project=project,
|
| |
+ ci_url=ci_url,
|
| |
+ ci_job=ci_job,
|
| |
+ ci_token=ci_token,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_commit=is_commit,
|
| |
+ commit_hash=commit_hash,
|
| |
+ is_pull_request=is_pull_request
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def test_trigger_build_commit_without_hash(self):
|
| |
+ """
|
| |
+ Failing with PagureException expected when 'is_commit' but no 'commit_hash' was provided
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ is_commit = True
|
| |
+
|
| |
+ self.assertRaises(
|
| |
+ pagure.exceptions.PagureException,
|
| |
+ pagure.api.ci.generic.trigger_build,
|
| |
+ project=project,
|
| |
+ ci_url=ci_url,
|
| |
+ ci_job=ci_job,
|
| |
+ ci_token=ci_token,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_commit=is_commit,
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def test_trigger_build_pull_request_without_pull_request_object(self):
|
| |
+ """
|
| |
+ Failing with PagureException expected when 'is_pull_request' but no 'pull_request' object was provided
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ is_pull_request = True
|
| |
+
|
| |
+ self.assertRaises(
|
| |
+ pagure.exceptions.PagureException,
|
| |
+ pagure.api.ci.generic.trigger_build,
|
| |
+ project=project,
|
| |
+ ci_url=ci_url,
|
| |
+ ci_job=ci_job,
|
| |
+ ci_token=ci_token,
|
| |
+ branch=branch,
|
| |
+ branch_to=branch_to,
|
| |
+ is_pull_request=is_pull_request,
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_no_json(self):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ want = 400
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_json_missing_arg_ci_token(self):
|
| |
+ """
|
| |
+ Expecting a bad request response when mandatory arg 'ci_token' is missing.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ build_status = "SUCCESS"
|
| |
+
|
| |
+ want = 400
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_json_missing_arg_pull_request_uid(self):
|
| |
+ """
|
| |
+ Expecting a bad request response when mandatory arg 'pull_request_uid' is missing.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ ci_token = "random_token"
|
| |
+ build_status = "SUCCESS"
|
| |
+
|
| |
+ want = 400
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_json_missing_arg_build_status(self):
|
| |
+ """
|
| |
+ Expecting a bad request response when mandatory arg 'build_status' is missing.
|
| |
+ """
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ ci_token = "random_token"
|
| |
+
|
| |
+ want = 400
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "ci_token": ci_token,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_no_project_found(self):
|
| |
+ ci_token = "random_token"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ build_status = "SUCCESS"
|
| |
+
|
| |
+ want = 404
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/invalid_repo_name",
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_invalid_ci_token(self):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ ci_token = "InvalidToken"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ build_status = "SUCCESS"
|
| |
+
|
| |
+ want = 401
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_no_pull_request_found(self):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ ci_token = "random_token"
|
| |
+ pr_uid = "InvalidPullRequestUID"
|
| |
+ build_status = "SUCCESS"
|
| |
+
|
| |
+ want = 404
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ def test_generic_ci_notification_post_invalid_build_status(self):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ ci_token = "random_token"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ build_status = "InvalidBuildStatus"
|
| |
+
|
| |
+ want = 400
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ "build_id_external": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+
|
| |
+ @patch("pagure.lib.query.get_authorized_project")
|
| |
+ @patch("pagure.lib.query.get_request_by_uid")
|
| |
+ @patch("pagure.lib.query.add_pull_request_flag")
|
| |
+ def test_generic_ci_add_pull_request_flag_called_once(self, add_pull_request_flag, get_request_by_uid, get_authorized_project):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ ci_token = "random_token"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ build_status = "SUCCESS"
|
| |
+ build_id_external = "1234"
|
| |
+ comment_display_name = "pagure ci - generic"
|
| |
+ build_url = "https://ci.example.com/1234"
|
| |
+
|
| |
+ pull_request = _unpatched_get_request_by_uid(self.session, pr_uid)
|
| |
+
|
| |
+ # Needs some improvement, quite some duplicate code and logic from the plugin
|
| |
+ comment, build_state, build_percent = BUILD_STATS[build_status]
|
| |
+ comment = comment % build_id_external
|
| |
+ if pull_request.commit_stop:
|
| |
+ comment += " (commit: %s)" % (pull_request.commit_stop[:8])
|
| |
+
|
| |
+ flag_uid = None
|
| |
+ for flag in pull_request.flags:
|
| |
+ if (
|
| |
+ flag.status == pagure_config["FLAG_PENDING"]
|
| |
+ and flag.username == comment_display_name
|
| |
+ ):
|
| |
+ flag_uid = flag.uid
|
| |
+ break
|
| |
+
|
| |
+ # Ensure that the same project obj is used across the test
|
| |
+ get_authorized_project.return_value = project
|
| |
+
|
| |
+ # Ensure that the same pull_request obj is used across the test
|
| |
+ get_request_by_uid.return_value = pull_request
|
| |
+
|
| |
+ want = 200
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": comment_display_name,
|
| |
+ "build_url": build_url,
|
| |
+ "build_id_external": build_id_external,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want)
|
| |
+
|
| |
+ add_pull_request_flag.assert_called_once_with(
|
| |
+ ANY,
|
| |
+ request=pull_request,
|
| |
+ username=comment_display_name,
|
| |
+ percent=build_percent,
|
| |
+ comment=comment,
|
| |
+ url=build_url,
|
| |
+ status=build_state,
|
| |
+ uid=flag_uid,
|
| |
+ user=project.user.username,
|
| |
+ token=None
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ @patch("pagure.lib.query.get_authorized_project")
|
| |
+ @patch("pagure.lib.query.get_request_by_uid")
|
| |
+ def test_generic_ci_notification_post_response(self, get_request_by_uid, get_authorized_project):
|
| |
+ project, ci_url, ci_job, ci_token, branch, branch_to = self._values_for_required_parameters()
|
| |
+ ci_token = "random_token"
|
| |
+ pr_uid = "720a0568c1274e74966e54b433b2003e"
|
| |
+ build_status = "SUCCESS"
|
| |
+
|
| |
+ pull_request = _unpatched_get_request_by_uid(self.session, pr_uid)
|
| |
+
|
| |
+ # Ensure that the same project obj is used across the test
|
| |
+ get_authorized_project.return_value = project
|
| |
+
|
| |
+ # Ensure that the same pull_request obj is used across the test
|
| |
+ get_request_by_uid.return_value = pull_request
|
| |
+
|
| |
+ want = {
|
| |
+ "status_code": 200,
|
| |
+ "body": {
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "result": "Status update successful."
|
| |
+ }
|
| |
+ }
|
| |
+
|
| |
+ got = self.app.post(
|
| |
+ f"/api/0/ci/generic/%s" % project.url_path,
|
| |
+ json={
|
| |
+ "ci_token": ci_token,
|
| |
+ "pull_request_uid": pr_uid,
|
| |
+ "build_status": build_status,
|
| |
+ "comment_display_name": None,
|
| |
+ "build_url": None,
|
| |
+ }
|
| |
+ )
|
| |
+
|
| |
+ self.assertEqual(got.status_code, want["status_code"])
|
| |
+
|
| |
+ self.assertJSONEqual(
|
| |
+ got.get_data(as_text=True),
|
| |
+ json.dumps(want["body"])
|
| |
+ )
|
| |
\ No newline at end of file
|
| |
It started with the idea of a pagure ci plugin for AWS CodePipeline but then I realized a more generic approach might be better.
AWS CodePipeline and / or AWS CodeBuild require a bit of custom implementation within the individual AWS Account, for example with AWS Lambda.
So I have to send some json payload via HTTPs to trigger that and can't move all AWS related logic into pagure.
There will be an AWS based reference implementation, but the plugin can be leverage by other implementations as well.
The related SUSE Hack Week project, the majority of work was done as part of it: https://hackweek.opensuse.org/projects/aws-codepipeline-ci-plugin-for-pagure-on-code-dot-opensuse-dot-org
I wrote some stuff down in my SUSE Hack Week recaps: