rtd.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2016 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals, absolute_import
  8. import sqlalchemy as sa
  9. import requests
  10. import wtforms
  11. try:
  12. from flask_wtf import FlaskForm
  13. except ImportError:
  14. from flask_wtf import Form as FlaskForm
  15. from sqlalchemy.orm import relation
  16. from sqlalchemy.orm import backref
  17. import pagure
  18. from pagure.hooks import BaseHook, BaseRunner
  19. from pagure.lib.model import BASE, Project
  20. _config = pagure.config.config
  21. class RtdTable(BASE):
  22. """ Stores information about the pagure hook deployed on a project.
  23. Table -- hook_rtd
  24. """
  25. __tablename__ = "hook_rtd"
  26. id = sa.Column(sa.Integer, primary_key=True)
  27. project_id = sa.Column(
  28. sa.Integer,
  29. sa.ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"),
  30. nullable=False,
  31. unique=True,
  32. index=True,
  33. )
  34. active = sa.Column(sa.Boolean, nullable=False, default=False)
  35. branches = sa.Column(sa.Text, nullable=True)
  36. api_url = sa.Column(sa.Text, nullable=False)
  37. api_token = sa.Column(sa.Text, nullable=False)
  38. project = relation(
  39. "Project",
  40. remote_side=[Project.id],
  41. backref=backref(
  42. "rtd_hook",
  43. cascade="delete, delete-orphan",
  44. single_parent=True,
  45. uselist=False,
  46. ),
  47. )
  48. class RtdForm(FlaskForm):
  49. """ Form to configure the pagure hook. """
  50. api_url = wtforms.StringField(
  51. "URL endpoint used to trigger the builds",
  52. [wtforms.validators.Optional()],
  53. )
  54. api_token = wtforms.StringField(
  55. "API token provided by readthedocs", [wtforms.validators.Optional()]
  56. )
  57. branches = wtforms.StringField(
  58. "Restrict build to these branches only (comma separated)",
  59. [wtforms.validators.Optional()],
  60. )
  61. active = wtforms.BooleanField("Active", [wtforms.validators.Optional()])
  62. DESCRIPTION = """
  63. Git hook to trigger building documentation on the readthedocs.org service
  64. when a commit is pushed to the repository.
  65. If you specify one or more branches (using commas `,` to separate them) only
  66. pushes made to these branches will trigger a new build of the documentation.
  67. To set up this hook, you will need to login to https://readthedocs.org/
  68. Go to your project's admin settings, and in the ``Integrations`` section
  69. add a new ``Generic API incoming webhook``.
  70. This will give you access to one URL and one API token, both of which you
  71. will have to provide below.
  72. """
  73. class RtdRunner(BaseRunner):
  74. @staticmethod
  75. def post_receive(session, username, project, repotype, repodir, changes):
  76. """ Perform the RTD Post Receive hook.
  77. For arguments, see BaseRunner.runhook.
  78. """
  79. # Get the list of branches
  80. branches = [
  81. branch.strip() for branch in project.rtd_hook.branches.split(",")
  82. ]
  83. # Remove empty branches
  84. branches = [branch.strip() for branch in branches if branch]
  85. url = project.rtd_hook.api_url
  86. if not url:
  87. print(
  88. "No API url specified to trigger the build, please update "
  89. "the configuration"
  90. )
  91. if not project.rtd_hook.api_token:
  92. print(
  93. "No API token specified to trigger the build, please update "
  94. "the configuration"
  95. )
  96. for refname in changes:
  97. oldrev, newrev = changes[refname]
  98. if _config.get("HOOK_DEBUG", False):
  99. print("%s: %s -> %s" % (refname, oldrev, newrev))
  100. refname = refname.replace("refs/heads/", "")
  101. if branches:
  102. if refname in branches:
  103. print("Starting RTD build at %s" % (url))
  104. requests.post(
  105. url,
  106. data={
  107. "branches": refname,
  108. "token": project.rtd_hook.api_token,
  109. },
  110. timeout=60,
  111. )
  112. else:
  113. print("Starting RTD build at %s" % (url))
  114. requests.post(
  115. url,
  116. data={
  117. "branches": refname,
  118. "token": project.rtd_hook.api_token,
  119. },
  120. timeout=60,
  121. )
  122. class RtdHook(BaseHook):
  123. """ Read The Doc hook. """
  124. name = "Read the Doc"
  125. description = DESCRIPTION
  126. form = RtdForm
  127. db_object = RtdTable
  128. runner = RtdRunner
  129. backref = "rtd_hook"
  130. form_fields = ["active", "api_url", "api_token", "branches"]