#5491 Refactoring: Make current Pagure CI hook / plugin system generic
Merged 6 months ago by ngompa. Opened 6 months ago by wombelix.

file modified
+11 -9
@@ -19,6 +19,7 @@ 

  import codecs

  import enum

  import functools

+ import importlib

  import logging

  import os

  
@@ -344,9 +345,6 @@ 

  from pagure.api import project  # noqa: E402, I202

  from pagure.api import user  # noqa: E402, I202

  

- if pagure_config.get("PAGURE_CI_SERVICES", False):

-     from pagure.api.ci import jenkins  # noqa: E402, F401

- 

  

  @API.route("/version/")

  @API.route("/version")
@@ -630,12 +628,16 @@ 

  

      if pagure_config.get("PAGURE_CI_SERVICES", False):

          ci_methods = []

-         if "jenkins" in pagure_config["PAGURE_CI_SERVICES"]:

-             if "jenkins" not in locals():

-                 # We run into this situation in the tests

-                 from pagure.api.ci import jenkins  # noqa: E402, F811

-             ci_methods.append(jenkins.jenkins_ci_notification)

- 

+         for ci_type in pagure_config["PAGURE_CI_SERVICES"]:

+             if ci_type not in locals():

+                 # Necessary to pass the tests and avoid:

+                 # AttributeError: 'str' object has no attribute '__name__'

+                 # 'build_docs_section' expects type function down the line.

+                 ci = importlib.import_module(

+                     f"pagure.api.ci.{ci_type}"

+                 )  # noqa: E402, F811

+                 ci_notification = getattr(ci, f"{ci_type}_ci_notification")

+             ci_methods.append(ci_notification)

          if ci_methods:

              sections.append(

                  build_docs_section(

@@ -7,3 +7,12 @@ 

     Pierre-Yves Chibon <pingou@pingoured.fr>

  

  """

+ 

+ from pagure.config import config as pagure_config

+ 

+ BUILD_STATS = {

+     "SUCCESS": ("Build #%s successful", pagure_config["FLAG_SUCCESS"], 100),

+     "FAILURE": ("Build #%s failed", pagure_config["FLAG_FAILURE"], 0),

+     "ABORTED": ("Build #%s aborted", "error", 0),

+     "BUILDING": ("Build #%s in progress", pagure_config["FLAG_PENDING"], 0),

+ }

file modified
+154 -2
@@ -18,10 +18,14 @@ 

  

  import pagure

  import pagure.exceptions

- import pagure.lib.lib_ci as lib_ci

+ import pagure.lib.query

+ from pagure.config import config as pagure_config

  import pagure.lib.plugins

  import pagure.lib.query

  from pagure.api import API, APIERROR, api_method

+ from pagure.api.ci import BUILD_STATS

+ 

+ import time

  

  _log = logging.getLogger(__name__)

  
@@ -43,6 +47,8 @@ 

      methods=["POST"],

  )

  @api_method

+ # <ci_type>_ci_notification

+ # convention required to ensure unique names in API namespace

  def jenkins_ci_notification(

      repo, pagure_ci_token, username=None, namespace=None

  ):
@@ -96,7 +102,7 @@ 

          raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)

  

      try:

-         lib_ci.process_jenkins_build(flask.g.session, project, build_id)

+         _process_build(flask.g.session, project, build_id)

      except pagure.exceptions.NoCorrespondingPR as err:

          raise pagure.exceptions.APIError(

              400, error_code=APIERROR.ENOCODE, error=str(err)
@@ -109,3 +115,149 @@ 

  

      _log.info("Successfully proccessed jenkins notification")

      return ("", 204)

+ 

+ 

+ def _process_build(session, project, build_id, iteration=0):

+     """Gets the build info from jenkins and flags that particular

+     pull-request.

+     """

+     import jenkins

+ 

+     # This import is needed as pagure.lib relies on Project.ci_hook to be

+     # defined and accessible and this happens in pagure.hooks.pagure_ci

+     from pagure.hooks import pagure_ci  # noqa: E402,F401

+ 

+     # Jenkins Base URL

+     _log.info("Querying jenkins at: %s", 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

+     )

+     try:

+         build_info = jenk.get_build_info(jenkins_name, build_id)

+     except jenkins.NotFoundException:

+         _log.debug("Could not find build %s at: %s", build_id, jenkins_name)

+         raise pagure.exceptions.PagureException(

+             "Could not find build %s at: %s" % (build_id, jenkins_name)

+         )

+ 

+     if build_info.get("building") is True:

+         if iteration < 5:

+             _log.info("Build is still going, let's wait a sec and try again")

+             time.sleep(1)

+             return _process_build(

+                 session, project, build_id, iteration=iteration + 1

+             )

+         _log.info(

+             "We've been waiting for 5 seconds and the build is still "

+             "not finished, so let's keep going."

+         )

+ 

+     result = build_info.get("result")

+     if not result and build_info.get("building") is True:

+         result = "BUILDING"

+ 

+     _log.info("Result from jenkins: %s", result)

+     url = build_info["url"]

+     _log.info("URL from jenkins: %s", url)

+ 

+     pr_id = None

+     for action in build_info["actions"]:

+         for cause in action.get("causes", []):

+             try:

+                 pr_id = int(cause["note"])

+             except (KeyError, ValueError):

+                 continue

+ 

+     if not pr_id:

+         raise pagure.exceptions.NoCorrespondingPR("No corresponding PR found")

+ 

+     if not result or result not in BUILD_STATS:

+         raise pagure.exceptions.PagureException(

+             "Unknown build status: %s" % result

+         )

+ 

+     request = pagure.lib.query.search_pull_requests(

+         session, project_id=project.id, requestid=pr_id

+     )

+ 

+     if not request:

+         raise pagure.exceptions.PagureException("Request not found")

+ 

+     comment, state, percent = BUILD_STATS[result]

+     comment = comment % build_id

+     # Adding build ID to the CI type

+     username = "%s" % project.ci_hook.ci_type

+     if request.commit_stop:

+         comment += " (commit: %s)" % (request.commit_stop[:8])

+ 

+     uid = None

+     for flag in request.flags:

+         if (

+             flag.status == pagure_config["FLAG_PENDING"]

+             and flag.username == username

+         ):

+             uid = flag.uid

+             break

+ 

+     _log.info("Flag's UID: %s", uid)

+     pagure.lib.query.add_pull_request_flag(

+         session,

+         request=request,

+         username=username,

+         percent=percent,

+         comment=comment,

+         url=url,

+         status=state,

+         uid=uid,

+         user=project.user.username,

+         token=None,

+     )

+     session.commit()

+ 

+ 

+ def trigger_build(

+     project_path,

+     url,

+     job,

+     token,

+     branch,

+     branch_to,

+     cause,

+     ci_username=None,

+     ci_password=None,

+ ):

+     """Trigger a build on a jenkins instance."""

+     try:

+         import jenkins

+     except ImportError:

+         _log.error("Pagure-CI: Failed to load the jenkins module, bailing")

+         return

+ 

+     _log.info("Jenkins CI")

+ 

+     repo = "%s/%s" % (pagure_config["GIT_URL_GIT"].rstrip("/"), project_path)

+ 

+     data = {

+         "cause": cause,

+         "REPO": repo,

+         "BRANCH": branch,

+         "BRANCH_TO": branch_to,

+     }

+ 

+     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

+     )

+     try:

+         server.build_job(name=job, parameters=data, token=token)

+         _log.info("Pagure-CI: Build triggered")

+     except Exception as err:

+         _log.info("Pagure-CI:An error occured: %s", err)

file modified
+1 -1
@@ -77,7 +77,7 @@ 

  {% if repo | hasattr('ci_hook') and repo.ci_hook and

      repo.ci_hook.pagure_ci_token %}

  

- The token to be used by jenkins to trigger the build is:

+ The token to be used by the CI to trigger the build is:

  <pre>

  {{ repo.ci_hook.pagure_ci_token}}

  </pre>

file removed
-176
@@ -1,176 +0,0 @@ 

- # -*- coding: utf-8 -*-

- 

- """

-  (c) 2016 - Copyright Red Hat Inc

- 

-  Authors:

-    Lubomír Sedlář <lubomir.sedlar@gmail.com>

-    Farhaan Bukhsh <farhaan.bukhsh@gmail.com>

-    Pierre-Yves Chibon <pingou@pingoured.fr>

- 

- """

- 

- from __future__ import absolute_import, unicode_literals

- 

- # pylint: disable=too-many-locals

- import logging

- import time

- 

- import pagure.exceptions

- import pagure.lib.query

- from pagure.config import config as pagure_config

- 

- _log = logging.getLogger(__name__)

- 

- BUILD_STATS = {

-     "SUCCESS": ("Build #%s successful", pagure_config["FLAG_SUCCESS"], 100),

-     "FAILURE": ("Build #%s failed", pagure_config["FLAG_FAILURE"], 0),

-     "ABORTED": ("Build #%s aborted", "error", 0),

-     "BUILDING": ("Build #%s in progress", pagure_config["FLAG_PENDING"], 0),

- }

- 

- 

- def process_jenkins_build(session, project, build_id, iteration=0):

-     """Gets the build info from jenkins and flags that particular

-     pull-request.

-     """

-     import jenkins

- 

-     # This import is needed as pagure.lib relies on Project.ci_hook to be

-     # defined and accessible and this happens in pagure.hooks.pagure_ci

-     from pagure.hooks import pagure_ci  # noqa: E402,F401

- 

-     # Jenkins Base URL

-     _log.info("Querying jenkins at: %s", 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

-     )

-     try:

-         build_info = jenk.get_build_info(jenkins_name, build_id)

-     except jenkins.NotFoundException:

-         _log.debug("Could not find build %s at: %s", build_id, jenkins_name)

-         raise pagure.exceptions.PagureException(

-             "Could not find build %s at: %s" % (build_id, jenkins_name)

-         )

- 

-     if build_info.get("building") is True:

-         if iteration < 5:

-             _log.info("Build is still going, let's wait a sec and try again")

-             time.sleep(1)

-             return process_jenkins_build(

-                 session, project, build_id, iteration=iteration + 1

-             )

-         _log.info(

-             "We've been waiting for 5 seconds and the build is still "

-             "not finished, so let's keep going."

-         )

- 

-     result = build_info.get("result")

-     if not result and build_info.get("building") is True:

-         result = "BUILDING"

- 

-     _log.info("Result from jenkins: %s", result)

-     url = build_info["url"]

-     _log.info("URL from jenkins: %s", url)

- 

-     pr_id = None

-     for action in build_info["actions"]:

-         for cause in action.get("causes", []):

-             try:

-                 pr_id = int(cause["note"])

-             except (KeyError, ValueError):

-                 continue

- 

-     if not pr_id:

-         raise pagure.exceptions.NoCorrespondingPR("No corresponding PR found")

- 

-     if not result or result not in BUILD_STATS:

-         raise pagure.exceptions.PagureException(

-             "Unknown build status: %s" % result

-         )

- 

-     request = pagure.lib.query.search_pull_requests(

-         session, project_id=project.id, requestid=pr_id

-     )

- 

-     if not request:

-         raise pagure.exceptions.PagureException("Request not found")

- 

-     comment, state, percent = BUILD_STATS[result]

-     comment = comment % build_id

-     # Adding build ID to the CI type

-     username = "%s" % project.ci_hook.ci_type

-     if request.commit_stop:

-         comment += " (commit: %s)" % (request.commit_stop[:8])

- 

-     uid = None

-     for flag in request.flags:

-         if (

-             flag.status == pagure_config["FLAG_PENDING"]

-             and flag.username == username

-         ):

-             uid = flag.uid

-             break

- 

-     _log.info("Flag's UID: %s", uid)

-     pagure.lib.query.add_pull_request_flag(

-         session,

-         request=request,

-         username=username,

-         percent=percent,

-         comment=comment,

-         url=url,

-         status=state,

-         uid=uid,

-         user=project.user.username,

-         token=None,

-     )

-     session.commit()

- 

- 

- def trigger_jenkins_build(

-     project_path,

-     url,

-     job,

-     token,

-     branch,

-     branch_to,

-     cause,

-     ci_username=None,

-     ci_password=None,

- ):

-     """Trigger a build on a jenkins instance."""

-     try:

-         import jenkins

-     except ImportError:

-         _log.error("Pagure-CI: Failed to load the jenkins module, bailing")

-         return

- 

-     _log.info("Jenkins CI")

- 

-     repo = "%s/%s" % (pagure_config["GIT_URL_GIT"].rstrip("/"), project_path)

- 

-     data = {

-         "cause": cause,

-         "REPO": repo,

-         "BRANCH": branch,

-         "BRANCH_TO": branch_to,

-     }

- 

-     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

-     )

-     try:

-         server.build_job(name=job, parameters=data, token=token)

-         _log.info("Pagure-CI: Build triggered")

-     except Exception as err:

-         _log.info("Pagure-CI:An error occured: %s", err)

file modified
+16 -16
@@ -13,8 +13,8 @@ 

  import datetime

  import hashlib

  import hmac

+ import importlib

  import json

- import os

  import os.path

  import time

  import uuid
@@ -29,7 +29,6 @@ 

  

  import pagure.lib.query

  from pagure.config import config as pagure_config

- from pagure.lib.lib_ci import trigger_jenkins_build

  from pagure.lib.tasks_utils import pagure_task

  from pagure.mail_logging import format_callstack

  from pagure.utils import set_up_logging, split_project_fullname
@@ -474,25 +473,26 @@ 

          branch,

      )

  

-     if ci_type == "jenkins":

- 

-         jenk_project = project

+     try:

+         ci_project = project

          if project.is_fork:

-             jenk_project = project.parent

- 

-         trigger_jenkins_build(

+             ci_project = project.parent

+         ci = importlib.import_module(f"pagure.api.ci.{ci_type}")

+         ci.trigger_build(

              project_path=project.path,

-             url=jenk_project.ci_hook.ci_url,

-             job=jenk_project.ci_hook.ci_job,

-             token=jenk_project.ci_hook.pagure_ci_token,

+             url=ci_project.ci_hook.ci_url,

+             job=ci_project.ci_hook.ci_job,

+             token=ci_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,

+             ci_username=ci_project.ci_hook.ci_username,

+             ci_password=ci_project.ci_hook.ci_password,

+         )

+     except Exception as e:

+         _log.error(

+             f"Pagure-CI: Un-supported CI type {ci_type}. "

+             f"Error while loading CI plugin: {e}"

          )

- 

-     else:

-         _log.warning("Pagure-CI:Un-supported CI type")

  

      _log.info("Pagure-CI: Ready for another")

file modified
+1 -1
@@ -33,7 +33,7 @@ 

  def fas_user_from_oidc():

      if "oidc_cached_userdata" in flask.session:

          flask.g.fas_user = munch.Munch(**flask.session["oidc_cached_userdata"])

-         # Edge case, avoid 'KeyError' after pagure update if a cached session is used

+         # Edge case, avoid 'KeyError' after pagure update with cached sessions

          flask.g.fas_user.can_create = flask.g.fas_user.get("can_create", False)

      elif oidc.user_loggedin and "oidc_logintime" in flask.session:

          email_key, fulln_key, usern_key, ssh_key, groups_key = [

@@ -369,7 +369,7 @@ 

                  output_text,

              )

  

-     @mock.patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @mock.patch("pagure.api.ci.jenkins.trigger_build")

      def test_plugin_pagure_ci_namespaced_auth(self, trigger_jenk):

          """Test the pagure ci plugin on/off endpoint."""

  

@@ -125,7 +125,7 @@ 

              "/path/to/git", ANY, "master", ["hash1", "hash2"]

          )

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_build")

      def test_trigger_ci_build_invalid_project(self, trigger_jenk):

          """Test the trigger_ci_build method."""

          output = pagure.lib.tasks_services.trigger_ci_build(
@@ -138,7 +138,7 @@ 

          self.assertIsNone(output)

          trigger_jenk.assert_not_called()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_build")

      def test_trigger_ci_build_not_configured_project(self, trigger_jenk):

          """Test the trigger_ci_build method."""

          self.assertRaises(
@@ -152,7 +152,7 @@ 

          )

          trigger_jenk.assert_not_called()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_build")

      def test_trigger_ci_build_not_configured_project_fork(self, trigger_jenk):

          """Test the trigger_ci_build method."""

          self.assertRaises(
@@ -595,7 +595,7 @@ 

          self.session.add(item)

          self.session.commit()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -608,7 +608,7 @@ 

          self.assertIsNone(output)

          trigger_jenk.assert_not_called()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -621,7 +621,7 @@ 

          self.assertIsNone(output)

          trigger_jenk.assert_not_called()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -644,7 +644,7 @@ 

              branch_to="master",

          )

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -714,7 +714,7 @@ 

          self.session.add(item)

          self.session.commit()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -727,7 +727,7 @@ 

          self.assertIsNone(output)

          trigger_jenk.assert_not_called()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -740,7 +740,7 @@ 

          self.assertIsNone(output)

          trigger_jenk.assert_not_called()

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(
@@ -763,7 +763,7 @@ 

              branch_to="master",

          )

  

-     @patch("pagure.lib.tasks_services.trigger_jenkins_build")

+     @patch("pagure.api.ci.jenkins.trigger_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(

First step to support additional CI types other than Jenkins.
This should make it generic enough that adding a new file to pagure/api/ci/ and adjusting PAGURE_CI_SERVICES enables it.
The tests still use Jenkins, it's the currently available CI type and testing the general Pagure CI functionality with it is fine.
New CI type should then define additional tests, specific to themselves, in tests/test_<ci_type>.py.

Problem
Currently pagure supports only Jenkins out-of-the-box.
A plugin system is in place but there is Jenkins specific code in global libraries.

Solution
Refactor the code to move all Jenkins specific parts into pagure/api/ci/jenkins.py

Affected files:
- pagure/lib/tasks_services.py
- pagure/api/init.py
- pagure/hooks/pagure_ci.py
- pagure/lib/lib_ci.py

Goal
Pagure core handles all CI types generic.
Specific code is only located in a single file pagure/api/ci/<ci_type>.py.
They are loaded by adding the name to the config Parameter PAGURE_CI_SERVICES.

Tests failing because of https://pagure.io/pagure/issue/5492 (breaking changes in latest pygit2 release)
Workaround applied via https://pagure.io/pagure/pull-request/5493

rebased onto 0c13cf0

6 months ago

pretty please pagure-ci rebuild

6 months ago

Duplicate run manually cancelled:

jenkins
Build #333 aborted (commit: d4ebb632)

Build 332 failed, I never saw AssertionError: datetime.date(2024, 12, 2) != datetime.date(2024, 12, 3) before. Let's run the CI again, I have a theory that it's a problem if we run a job over midnight in UTC.

The py 39 tests started at 01:53:17 CEST, this was 7 minutes before midnight in UTC.
And the test failed around 02:05:00 - 02:06:00 CEST, 5 till 6 minutes after midnight UTC.
Could explain that a datetime assertion for something like "today + x" then fails.

py39:

02:09:12  =========================== short test summary info ============================
02:09:12  FAILED tests/test_pagure_flask_ui_repo.py::PagureFlaskRepotests::test_renew_api_token - AssertionError: datetime.date(2024, 12, 2) != datetime.date(2024, 12, 3)
02:09:12  FAILED tests/test_pagure_flask_ui_repo.py::PagureFlaskRepotests::test_revoke_api_token - AssertionError: datetime.date(2024, 12, 2) != datetime.date(2024, 12, 3)
02:09:12  ===== 2 failed, 1664 passed, 3 skipped, 8413 warnings in 917.67s (0:15:17) =====

Anything else was fine, which makes me think that it was just an edge case.

02:58:07  py312: exit 0 (959.51 seconds) /pagure> pytest -n auto tests/ pid=50577
02:58:07    py39: FAIL code 1 (955.61=setup[37.39]+cmd[918.22] seconds)
02:58:07    py310: OK (955.28=setup[35.05]+cmd[920.23] seconds)
02:58:07    py311: OK (928.84=setup[37.55]+cmd[891.29] seconds)
02:58:07    py312: OK (1050.32=setup[90.82]+cmd[959.51] seconds)
02:58:07    evaluation failed :( (3890.13 seconds)

pretty please pagure-ci rebuild

6 months ago

Failures are not related to the PR. AssertionError: unexpectedly None is a problem that randomly happens sometimes and should get better when https://pagure.io/pagure/issue/5466 is implemented.

10:40:41  =========================== short test summary info ============================

10:40:41  FAILED tests/test_pagure_flask_ui_fork.py::PagureFlaskForktests::test_merge_request_pull_merge - AssertionError: unexpectedly None

10:40:41  FAILED tests/test_pagure_flask_ui_fork.py::PagureFlaskForktests::test_merge_request_pull_merge_with_comment - AssertionError: unexpectedly None

10:40:41  === 2 failed, 1664 passed, 3 skipped, 136245 warnings in 1743.65s (0:29:03) ====

10:40:42  py312: exit 1 (1745.37 seconds) /pagure> pytest -n auto tests/ pid=50566
10:40:42    py39: OK (924.98=setup[35.95]+cmd[889.03] seconds)
10:40:42    py310: OK (917.41=setup[33.36]+cmd[884.06] seconds)
10:40:42    py311: OK (893.40=setup[35.37]+cmd[858.03] seconds)
10:40:42    py312: FAIL code 1 (1832.53=setup[87.16]+cmd[1745.37] seconds)
10:40:42    evaluation failed :( (4568.39 seconds)

Can you please fix your commit message in cb11d4f? It's too long in the first line.

rebased onto 0c13cf0

6 months ago

rebased onto 0c13cf0

6 months ago

Can you please fix your commit message in cb11d4f? It's too long in the first line.

done.

Tests are fine, just the know flappy behavior.

15:14:13  =========================== short test summary info ============================

15:14:13  FAILED tests/test_pagure_flask_ui_fork.py::PagureFlaskForktests::test_merge_request_pull_nochange - AssertionError: unexpectedly None

15:14:13  FAILED tests/test_pagure_flask_ui_fork.py::PagureFlaskForktests::test_merge_request_pull_FF - AssertionError: unexpectedly None

15:14:13  FAILED tests/test_pagure_flask_ui_fork.py::PagureFlaskForktests::test_request_pull_patch_close - AssertionError: unexpectedly None

15:14:13  === 3 failed, 1663 passed, 3 skipped, 136260 warnings in 2651.19s (0:44:11) ====

15:14:14  py312: exit 1 (2653.10 seconds) /pagure> pytest -n auto tests/ pid=50566
15:14:14    py39: OK (933.26=setup[36.68]+cmd[896.58] seconds)
15:14:14    py310: OK (932.82=setup[33.78]+cmd[899.04] seconds)
15:14:14    py311: OK (907.32=setup[36.51]+cmd[870.81] seconds)
15:14:14    py312: FAIL code 1 (2741.26=setup[88.16]+cmd[2653.10] seconds)
15:14:14    evaluation failed :( (5514.74 seconds)
14:46:20  ========= 1666 passed, 3 skipped, 136245 warnings in 941.36s (0:15:41) =========

14:46:20  py312: exit 0 (942.84 seconds) /pagure> pytest -n auto tests/ pid=50553
14:46:20    py39: OK (941.40=setup[37.75]+cmd[903.66] seconds)
14:46:20    py310: OK (933.39=setup[34.19]+cmd[899.20] seconds)
14:46:20    py311: OK (910.65=setup[36.35]+cmd[874.30] seconds)
14:46:20    py312: OK (1031.96=setup[89.12]+cmd[942.84] seconds)
14:46:20    congratulations :) (3817.48 seconds)

Pull-Request has been merged by ngompa

6 months ago