jenkins.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2016-2017 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals
  8. import logging
  9. import flask
  10. from cryptography.hazmat.primitives import constant_time
  11. from kitchen.text.converters import to_bytes
  12. import pagure
  13. import pagure.exceptions
  14. import pagure.lib
  15. import pagure.lib.lib_ci as lib_ci
  16. from pagure.api import API, APIERROR, api_method
  17. _log = logging.getLogger(__name__)
  18. @API.route(
  19. "/ci/jenkins/<repo>/<pagure_ci_token>/build-finished", methods=["POST"]
  20. )
  21. @API.route(
  22. "/ci/jenkins/<namespace>/<repo>/<pagure_ci_token>/build-finished",
  23. methods=["POST"],
  24. )
  25. @API.route(
  26. "/ci/jenkins/forks/<username>/<repo>/" "<pagure_ci_token>/build-finished",
  27. methods=["POST"],
  28. )
  29. @API.route(
  30. "/ci/jenkins/forks/<username>/<namespace>/<repo>/"
  31. "<pagure_ci_token>/build-finished",
  32. methods=["POST"],
  33. )
  34. @api_method
  35. def jenkins_ci_notification(
  36. repo, pagure_ci_token, username=None, namespace=None
  37. ):
  38. """
  39. Jenkins Build Notification
  40. --------------------------
  41. At the end of a build on Jenkins, this URL is used (if the project is
  42. rightly configured) to flag a pull-request with the result of the build.
  43. ::
  44. POST /api/0/ci/jenkins/<repo>/<token>/build-finished
  45. """
  46. project = pagure.lib._get_project(
  47. flask.g.session, repo, user=username, namespace=namespace
  48. )
  49. flask.g.repo_locked = True
  50. flask.g.repo = project
  51. if not project:
  52. raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT)
  53. if not constant_time.bytes_eq(
  54. to_bytes(pagure_ci_token), to_bytes(project.ci_hook.pagure_ci_token)
  55. ):
  56. raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK)
  57. data = flask.request.get_json()
  58. if not data:
  59. _log.debug("Bad Request: No JSON retrieved")
  60. raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)
  61. build_id = data.get("build", {}).get("number")
  62. if not build_id:
  63. _log.debug("Bad Request: No build ID retrieved")
  64. raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)
  65. build_phase = data.get("build", {}).get("phase")
  66. if not build_phase:
  67. _log.debug("Bad Request: No build phase retrieved")
  68. raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)
  69. if build_phase not in ["STARTED", "FINALIZED"]:
  70. _log.debug(
  71. "Ignoring phase: %s - not in the list: STARTED, FINALIZED",
  72. build_phase,
  73. )
  74. raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ)
  75. try:
  76. lib_ci.process_jenkins_build(flask.g.session, project, build_id)
  77. except pagure.exceptions.NoCorrespondingPR as err:
  78. raise pagure.exceptions.APIError(
  79. 400, error_code=APIERROR.ENOCODE, error=str(err)
  80. )
  81. except pagure.exceptions.PagureException as err:
  82. _log.error("Error processing jenkins notification", exc_info=err)
  83. raise pagure.exceptions.APIError(
  84. 400, error_code=APIERROR.ENOCODE, error=str(err)
  85. )
  86. _log.info("Successfully proccessed jenkins notification")
  87. return ("", 204)