announce.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. """module to send announcements for processed packages
  2. @contact: Debian FTP Master <ftpmaster@debian.org>
  3. @copyright: 2012, Ansgar Burchardt <ansgar@debian.org>
  4. @license: GPL-2+
  5. """
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License along
  17. # with this program; if not, write to the Free Software Foundation, Inc.,
  18. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. import os
  20. from daklib.config import Config
  21. from daklib.textutils import fix_maintainer
  22. from daklib.utils import mail_addresses_for_upload, TemplateSubst, send_mail
  23. class ProcessedUpload(object):
  24. # people
  25. maintainer = None
  26. changed_by = None
  27. fingerprint = None
  28. # suites
  29. suites = []
  30. from_policy_suites = []
  31. # package
  32. changes = None
  33. changes_filename = None
  34. sourceful = None
  35. source = None
  36. architecture = None
  37. version = None
  38. bugs = None
  39. # program
  40. program = "unknown-program"
  41. warnings = []
  42. def _subst_for_upload(upload):
  43. cnf = Config()
  44. maintainer = upload.maintainer or cnf['Dinstall::MyEmailAddress']
  45. changed_by = upload.changed_by or maintainer
  46. if upload.sourceful:
  47. maintainer_to = mail_addresses_for_upload(maintainer, changed_by, upload.fingerprint)
  48. else:
  49. maintainer_to = mail_addresses_for_upload(maintainer, maintainer, upload.fingerprint)
  50. bcc = 'X-DAK: dak {0}'.format(upload.program)
  51. if 'Dinstall::Bcc' in cnf:
  52. bcc = '{0}\nBcc: {1}'.format(bcc, cnf['Dinstall::Bcc'])
  53. subst = {
  54. '__DISTRO__': cnf['Dinstall::MyDistribution'],
  55. '__BUG_SERVER__': cnf.get('Dinstall::BugServer'),
  56. '__ADMIN_ADDRESS__': cnf['Dinstall::MyAdminAddress'],
  57. '__DAK_ADDRESS__': cnf['Dinstall::MyEmailAddress'],
  58. '__REJECTOR_ADDRESS__': cnf['Dinstall::MyEmailAddress'],
  59. '__MANUAL_REJECT_MESSAGE__': '',
  60. '__BCC__': bcc,
  61. '__MAINTAINER__': changed_by,
  62. '__MAINTAINER_FROM__': fix_maintainer(changed_by)[1],
  63. '__MAINTAINER_TO__': ', '.join(maintainer_to),
  64. '__CHANGES_FILENAME__': upload.changes_filename,
  65. '__FILE_CONTENTS__': upload.changes,
  66. '__SOURCE__': upload.source,
  67. '__VERSION__': upload.version,
  68. '__ARCHITECTURE__': upload.architecture,
  69. '__WARNINGS__': '\n'.join(upload.warnings),
  70. }
  71. override_maintainer = cnf.get('Dinstall::OverrideMaintainer')
  72. if override_maintainer:
  73. subst['__MAINTAINER_FROM__'] = subst['__MAINTAINER_TO__'] = override_maintainer
  74. return subst
  75. def _whitelists(upload):
  76. return [s.mail_whitelist for s in upload.suites]
  77. def announce_reject(upload, reason, rejected_by=None):
  78. cnf = Config()
  79. subst = _subst_for_upload(upload)
  80. whitelists = _whitelists(upload)
  81. automatic = rejected_by is None
  82. subst['__CC__'] = 'X-DAK-Rejection: {0}'.format('automatic' if automatic else 'manual')
  83. subst['__REJECT_MESSAGE__'] = reason
  84. if rejected_by:
  85. subst['__REJECTOR_ADDRESS__'] = rejected_by
  86. if not automatic:
  87. subst['__BCC__'] = '{0}\nBcc: {1}'.format(subst['__BCC__'], subst['__REJECTOR_ADDRESS__'])
  88. message = TemplateSubst(subst, os.path.join(cnf['Dir::Templates'], 'queue.rejected'))
  89. send_mail(message, whitelists=whitelists)
  90. def announce_accept(upload):
  91. cnf = Config()
  92. subst = _subst_for_upload(upload)
  93. whitelists = _whitelists(upload)
  94. accepted_to_real_suite = any(suite.policy_queue is None or suite in upload.from_policy_suites for suite in upload.suites)
  95. suite_names = []
  96. for suite in upload.suites:
  97. if suite.policy_queue:
  98. suite_names.append("{0}->{1}".format(suite.suite_name, suite.policy_queue.queue_name))
  99. else:
  100. suite_names.append(suite.suite_name)
  101. suite_names.extend(suite.suite_name for suite in upload.from_policy_suites)
  102. subst['__SUITE__'] = ', '.join(suite_names) or '(none)'
  103. message = TemplateSubst(subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.accepted'))
  104. send_mail(message, whitelists=whitelists)
  105. if accepted_to_real_suite and upload.sourceful:
  106. # send mail to announce lists and tracking server
  107. announce = set()
  108. for suite in upload.suites:
  109. if suite.policy_queue is None or suite in upload.from_policy_suites:
  110. announce.update(suite.announce or [])
  111. announce_list_address = ", ".join(announce)
  112. # according to #890944 this email shall be sent to dispatch@<TrackingServer> to avoid
  113. # bouncing emails
  114. # the package email alias is not yet created shortly after accepting the package
  115. tracker = cnf.get('Dinstall::TrackingServer')
  116. if tracker:
  117. announce_list_address = "{0}\nBcc: dispatch@{1}".format(announce_list_address, tracker)
  118. if len(announce_list_address) != 0:
  119. my_subst = subst.copy()
  120. my_subst['__ANNOUNCE_LIST_ADDRESS__'] = announce_list_address
  121. message = TemplateSubst(my_subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.announce'))
  122. send_mail(message, whitelists=whitelists)
  123. close_bugs_default = cnf.find_b('Dinstall::CloseBugs')
  124. close_bugs = any(s.close_bugs if s.close_bugs is not None else close_bugs_default for s in upload.suites)
  125. if accepted_to_real_suite and upload.sourceful and close_bugs:
  126. for bug in upload.bugs:
  127. my_subst = subst.copy()
  128. my_subst['__BUG_NUMBER__'] = str(bug)
  129. message = TemplateSubst(my_subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.bug-close'))
  130. send_mail(message, whitelists=whitelists)
  131. def announce_new(upload):
  132. cnf = Config()
  133. subst = _subst_for_upload(upload)
  134. whitelists = _whitelists(upload)
  135. message = TemplateSubst(subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.new'))
  136. send_mail(message, whitelists=whitelists)