Add the request job, reuse boss-participant-requests
authorHasan Wan <hasan.wan@intel.com>
Fri, 10 Aug 2012 02:36:48 +0000 (10:36 +0800)
committerLin Yang <lin.a.yang@intel.com>
Tue, 28 Aug 2012 03:23:07 +0000 (11:23 +0800)
Change-Id: I0ca05a6e2a062d633b3d2b3e007a94fd28d21f62
Signed-off-by: Hasan Wan <hasan.wan@intel.com>
21 files changed:
request.py [new file with mode: 0644]
requests/__init__.py [new file with mode: 0644]
requests/email_templates/obs_request_accept [new file with mode: 0644]
requests/email_templates/obs_request_auto_reject [new file with mode: 0644]
requests/email_templates/obs_request_changedevel [new file with mode: 0644]
requests/email_templates/obs_request_changedevel_accept [new file with mode: 0644]
requests/email_templates/obs_request_changedevel_decline [new file with mode: 0644]
requests/email_templates/obs_request_changedevel_revoke [new file with mode: 0644]
requests/email_templates/obs_request_create [new file with mode: 0644]
requests/email_templates/obs_request_decline [new file with mode: 0644]
requests/email_templates/obs_request_delpkg [new file with mode: 0644]
requests/email_templates/obs_request_delpkg_accept [new file with mode: 0644]
requests/email_templates/obs_request_delpkg_decline [new file with mode: 0644]
requests/email_templates/obs_request_delpkg_revoke [new file with mode: 0644]
requests/email_templates/obs_request_maintainer [new file with mode: 0644]
requests/email_templates/obs_request_maintainer_accept [new file with mode: 0644]
requests/email_templates/obs_request_maintainer_decline [new file with mode: 0644]
requests/email_templates/obs_request_maintainer_revoke [new file with mode: 0644]
requests/email_templates/obs_request_newpkg [new file with mode: 0644]
requests/email_templates/obs_request_revoke [new file with mode: 0644]
requests/mailer.py [new file with mode: 0644]

diff --git a/request.py b/request.py
new file mode 100644 (file)
index 0000000..ea7ca66
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+
+from common.envparas import export
+from common import git
+from common import buildservice
+from requests.mailer import mailer
+
+import json
+import sys
+import os
+
+envparas = ['OBS_EVENT_STRING',
+            'OBS_OSCRC_PATH',
+            'OBS_API_URL',
+            'SR_ENABLE_USER',
+            'NOREPLY_EMAIL_SENDER',
+            'MAILINGLIST',
+            'BCC_MAILS',
+            'BUILD_TAG',
+            'EMAIL_TEMPLATES_DIR',
+            'GIT_CACHE_DIR'
+            'GIT_URL']
+
+export(envparas, locals())
+
+def tag_info(prjdir, tag):
+
+    git.update_git_project(GIT_CACHE_DIR, prjdir, GIT_URL)
+        
+    gitprj = git.Git(os.path.join(GIT_CACHE_DIR,prjdir))
+    if gitprj.find_tag(tag):
+        return gitprj.get_tagger(tag)
+
+    return {}
+
+def description_paser(description):
+
+    mapping = {"Submitter" : 'auth_email',
+               "Comments" : "comments",
+               "Tag" : "tag",
+               "Git project" : "prj",
+               "Commit" : "commit_subj"
+               }
+
+    ret_list = []
+    for section in description.split('\n\n'):
+        entry = {}
+        for line in section.split('\n'):
+            key, value = line.split(':')
+            entry[mapping[key.strip()]] = value.strip()
+
+        tag = tag_info(entry['prj'], entry['tag'])
+        entry.update(tag)
+        ret_list.append(entry)
+
+    return ret_list
+
+def request_accepted(event_fields):
+    print '====request accepted===================================='
+    print event_fields
+
+    gerrit.post_comment(prj, commit_id, msg)
+    git.create_tag('name', 'msg', commit_id)
+    invoke_mailsender()
+    
+def request_rejected(event_fields):
+    print '====request rejected===================================='
+    print event_fields
+
+    gerrit.post_comment(prj, commit_id, msg)
+    invoke_mailsender()
+    
+
+def request_created(event_fields):
+    print '====request created===================================='
+    print event_fields
+    gerrit.post_comment(prj, commit_id, msg)
+    invoke_mailsender()
+
+
+def notify_submiter(event_fields, desp):
+    print '====Notify the tag owner===================================='
+
+    mail_to = []
+    for entry in desp:
+        mail_to.append(entry['auth_email'])
+
+    status = True
+
+    bs = buildservice.BuildService(OBS_API_URL, OBS_OSCRC_PATH)
+
+    # step1: do reqeust policy checking
+    #if policy:
+    #    need_check = reduce(lambda r, k: r or policy[k] > 0, policy.keys(), False)
+    #    if need_check:
+    #        rejector(event_fields, bs, policy)
+
+    # step2: email notification to mailing list
+    if MAILINGLIST:
+        status = mailer(event_fields, bs, event_fields, NOREPLY_EMAIL_SENDER,
+                        MAILINGLIST, BCC_MAILS, SR_ENABLE_USER, EMAIL_TEMPLATES_DIR)
+
+    if status:
+        with open('%s.env' %(BUILD_TAG),'w') as f:
+            for a in status.keys():
+                f.write('%s=%s\n' %(a, status[a]))
+
+event = json.loads(' '.join(OBS_EVENT_STRING.split()))
+
+event_fields = event['fields']['obsEvent']
+
+if not event_fields:
+    print 'Invalid OBS event: %s' %(OBS_EVENT_STRING)
+    sys.exit(-1)
+
+desp = description_paser(event_fields['description'])
+notify_submiter(event_fields, desp)
+sys.exit(0)
+if event_fields['type'] == 'OBS_SRCSRV_REQUEST_STATECHANGE':
+    pass
+elif event_fields['type'] == 'OBS_SRCSRV_REQUEST_CREATE':
+    request_created(event_fields)
+elif event_fields['type'] == 'OBS_SRCSRV_REQUEST_ACCEPTED':
+    request_accepted(event_fields)
+
+
diff --git a/requests/__init__.py b/requests/__init__.py
new file mode 100644 (file)
index 0000000..06d2477
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+#    Copyright (c) 2009 Intel Corporation
+#
+#    This program is free software; you can redistribute it and/or modify it
+#    under the terms of the GNU General Public License as published by the Free
+#    Software Foundation; version 2 of the License
+#
+#    This program is distributed in the hope that it will be useful, but
+#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+#    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#    for more details.
+#
+#    You should have received a copy of the GNU General Public License along
+#    with this program; if not, write to the Free Software Foundation, Inc., 59
+#    Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
diff --git a/requests/email_templates/obs_request_accept b/requests/email_templates/obs_request_accept
new file mode 100644 (file)
index 0000000..b97500d
--- /dev/null
@@ -0,0 +1,13 @@
+Hi ${receipt},
+The following change has been accepted. See the changelog below.
+
+Comments:
+    ${comment}
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_auto_reject b/requests/email_templates/obs_request_auto_reject
new file mode 100644 (file)
index 0000000..3009a58
--- /dev/null
@@ -0,0 +1,20 @@
+Hi ${receipt},
+The following change has been rejected automatically.
+
+Reason: 
+
+  For current Tizen work model, OBS will not accept any merge requests from
+  developers. Instead, developers should submit the changes to gerrit(git),
+  whenever it was accepted. The content in git tree will be synced to OBS
+  automatically.
+
+  Please visit the following link for more details:
+    TBD
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_changedevel b/requests/email_templates/obs_request_changedevel
new file mode 100644 (file)
index 0000000..8277e2c
--- /dev/null
@@ -0,0 +1,15 @@
+Hi,
+I would like to change devel pkg of ${targetproject}/${targetpackage} to the following
+
+  ${sourcepackage}
+
+in project ${sourceproject}.
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_changedevel_accept b/requests/email_templates/obs_request_changedevel_accept
new file mode 100644 (file)
index 0000000..8230c72
--- /dev/null
@@ -0,0 +1,15 @@
+Hi ${receipt},
+The following change has been accepted. See the changelog below.
+
+${sourceproject}/${sourcepackage} is now the devel pkg of ${targetproject}/${targetpackage}
+
+Comments:
+    ${comment}
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_changedevel_decline b/requests/email_templates/obs_request_changedevel_decline
new file mode 100644 (file)
index 0000000..b917a05
--- /dev/null
@@ -0,0 +1,19 @@
+Hi ${receipt},
+I have rejected the request for change devel pkg of ${targetproject}/${targetpackage} to the following
+
+  ${sourcepackage}
+
+in project ${sourceproject}.
+
+Reason:
+    ${comment}
+
+Please fix the issues above and resubmit.
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_changedevel_revoke b/requests/email_templates/obs_request_changedevel_revoke
new file mode 100644 (file)
index 0000000..6a7cae3
--- /dev/null
@@ -0,0 +1,14 @@
+Hi,
+I have revoked the request for change devel pkg of ${targetproject}/${targetpackage}
+
+Comments:
+    ${comment}
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_create b/requests/email_templates/obs_request_create
new file mode 100644 (file)
index 0000000..a853e93
--- /dev/null
@@ -0,0 +1,11 @@
+Hi,
+I have made the following changes to ${targetpackage} in project ${targetproject}. Please review and accept ASAP.
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_decline b/requests/email_templates/obs_request_decline
new file mode 100644 (file)
index 0000000..8a93ece
--- /dev/null
@@ -0,0 +1,15 @@
+Hi ${receipt},
+The following change has been rejected.
+
+Reason:
+    ${comment}
+
+Please fix the issues above and resubmit.
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_delpkg b/requests/email_templates/obs_request_delpkg
new file mode 100644 (file)
index 0000000..e60457f
--- /dev/null
@@ -0,0 +1,14 @@
+Hi,
+Please remove package ${deletepackage} from project ${deleteproject}
+
+Reason:
+    ${description}
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+--
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_delpkg_accept b/requests/email_templates/obs_request_delpkg_accept
new file mode 100644 (file)
index 0000000..436c45a
--- /dev/null
@@ -0,0 +1,14 @@
+Hi ${receipt},
+The following change has been accepted. See the changelog below.
+The package ${deletepackage} from project ${deleteproject} has been deleted.
+
+Comments:
+    ${comment}
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_delpkg_decline b/requests/email_templates/obs_request_delpkg_decline
new file mode 100644 (file)
index 0000000..6627b47
--- /dev/null
@@ -0,0 +1,15 @@
+Hi ${receipt},
+I have rejected the request for remove package ${deletepackage} from project ${deleteproject}
+
+Reason:
+    ${comment}
+
+Please fix the issues above and resubmit.
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_delpkg_revoke b/requests/email_templates/obs_request_delpkg_revoke
new file mode 100644 (file)
index 0000000..5547005
--- /dev/null
@@ -0,0 +1,14 @@
+Hi,
+I have revoked the request for remove package ${deletepackage} in project ${deleteproject}.
+
+Comments:
+    ${comment}
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_maintainer b/requests/email_templates/obs_request_maintainer
new file mode 100644 (file)
index 0000000..aa0e3e4
--- /dev/null
@@ -0,0 +1,16 @@
+Hi,
+I would like to register ${person} as the ${role} for the following package
+
+  ${targetpackage}
+
+in project ${targetproject}.
+
+Reason: ${description}
+
+Thank You,
+${realname}
+
+See http://wiki.meego.com/Packaging/Guidelines#Maintaining_a_Package for more details.
+
+[This message was auto-generated]
+---
diff --git a/requests/email_templates/obs_request_maintainer_accept b/requests/email_templates/obs_request_maintainer_accept
new file mode 100644 (file)
index 0000000..d192603
--- /dev/null
@@ -0,0 +1,15 @@
+Hi ${receipt},
+The following change has been accepted.
+
+${person} is now the ${role} of ${targetproject}/${targetpackage}
+
+Comments:
+    ${comment}
+
+Thanks,
+Release Engineering Team
+
+See http://wiki.meego.com/Packaging/Guidelines#Maintaining_a_Package
+
+[This message was auto-generated]
+---
diff --git a/requests/email_templates/obs_request_maintainer_decline b/requests/email_templates/obs_request_maintainer_decline
new file mode 100644 (file)
index 0000000..daf14d9
--- /dev/null
@@ -0,0 +1,19 @@
+Hi ${receipt},
+I have rejected the request for register ${person} as the ${role} of the following package
+
+  ${targetpackage}
+
+in project ${targetproject}.
+
+Reason:
+    ${comment}
+
+Please fix the issues above and resubmit.
+
+Thanks,
+Release Engineering Team
+
+[This message was auto-generated]
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_maintainer_revoke b/requests/email_templates/obs_request_maintainer_revoke
new file mode 100644 (file)
index 0000000..d79f5eb
--- /dev/null
@@ -0,0 +1,18 @@
+Hi,
+I have revoked the request for register ${person} as the ${role} of the following package
+
+  ${targetpackage}
+
+in project ${targetproject}.
+
+Comments:
+    ${comment}
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_newpkg b/requests/email_templates/obs_request_newpkg
new file mode 100644 (file)
index 0000000..8b5267f
--- /dev/null
@@ -0,0 +1,15 @@
+Hi,
+Adding new package ${targetpackage} in project ${targetproject}. Please review and accept ASAP.
+
+Justification for this new package:
+
+${description}
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/email_templates/obs_request_revoke b/requests/email_templates/obs_request_revoke
new file mode 100644 (file)
index 0000000..7c823e1
--- /dev/null
@@ -0,0 +1,14 @@
+Hi,
+I have revoked the request for changes to ${targetpackage} in project ${targetproject}.
+
+Comments:
+    ${comment}
+
+Thank You,
+${realname}
+
+[This message was auto-generated]
+
+---
+
+${reqinfo}
diff --git a/requests/mailer.py b/requests/mailer.py
new file mode 100644 (file)
index 0000000..1a737cf
--- /dev/null
@@ -0,0 +1,429 @@
+#!/usr/bin/env python
+
+#    Copyright (c) 2009 Intel Corporation
+#
+#    This program is free software; you can redistribute it and/or modify it
+#    under the terms of the GNU General Public License as published by the Free
+#    Software Foundation; version 2 of the License
+#
+#    This program is distributed in the hope that it will be useful, but
+#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+#    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#    for more details.
+#
+#    You should have received a copy of the GNU General Public License along
+#    with this program; if not, write to the Free Software Foundation, Inc., 59
+#    Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+from string import Template
+import copy
+import os
+
+"""
+def := { event_name1: ( trigger, trigger ),
+         event_name2: ( trigger, ),
+       }
+trigger := { 'temp': 'template name',
+             'cond':  lambda incline function
+             'sub':   string template for subject
+             'to':    list of To:
+             'cc':    list of Cc:
+             'from':  From:
+             'fields': list of variables to be expand in template
+             'detail?': True/False, whether need detailed reqinfo
+             'tgtprj': the field name in obsEvent as the target prj
+           }
+NOTE: multiple triggers need be IN STRICT ORDER
+"""
+
+IGNORE_HOME = True
+
+AUTO_REJECT_COMMENT = 'You are not a valid submitrequest sender'
+
+MAIL_TRIGGERS = {
+        'OBS_SRCSRV_REQUEST_CREATE':
+            (
+             {
+                'temp':  'obs_request_delpkg',
+                'cond':  lambda bs, req: req['deleteproject'] and req['deletepackage'],
+                'sub':   '${reqid}: Remove package ${deleteproject}/${deletepackage}',
+                'to':    ['mailinglist'],
+                'cc':    ['who'],
+                'from':  'who',
+                'fields':['description', 'deleteproject', 'deletepackage'],
+                'detail?':False,
+                'tgtprj': 'deleteproject',
+             },
+             {
+                'temp':  'obs_request_maintainer',
+                'cond':  lambda bs, req: req['role'] and req['person'],
+                'sub':   '${reqid}: Maintainer request for ${targetproject}/${targetpackage}',
+                'to':    ['mailinglist'],
+                'cc':    ['who'],
+                'from':  'who',
+                'fields':['description', 'targetproject', 'targetpackage', 'role', 'person'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'temp':  'obs_request_changedevel',
+                'cond':  lambda bs, req: req['origintype'] == 'change_devel',
+                'sub':   '${reqid}: Change devel of ${targetproject}/${targetpackage} to ${sourceproject}/${sourcepackage}',
+                'to':    ['mailinglist'],
+                'cc':    ['who'],
+                'from':  'who',
+                'fields':['description', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'temp':  'obs_request_newpkg',
+                'cond':  lambda bs, req: bs.isNewPackage(req['targetproject'], req['targetpackage']),
+                'sub':   '${reqid}: New package ${targetproject}/${targetpackage}',
+                'to':    ['mailinglist'],
+                'cc':    ['who'],
+                'from':  'who',
+                'fields':['description', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':True,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'temp':  'obs_request_create',
+                'cond':  None,
+                'sub':   '${reqid}: Changes to ${targetproject}/${targetpackage}',
+                'to':    ['mailinglist'],
+                'cc':    ['who'],
+                'from':  'who',
+                'fields':['description', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':True,
+                'tgtprj': 'targetproject',
+             },
+            ),
+        'OBS_SRCSRV_REQUEST_ACCEPTED':
+            (
+             {
+                'temp':  'obs_request_maintainer_accept',
+                'cond':  lambda bs, req: req['state'] == 'accepted' and req['role'] and req['person'],
+                'sub':   '${reqid} accepted: ${role} request for ${targetproject}/${targetpackage}',
+                'to':    ['author', 'person'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage', 'role', 'person'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'temp':  'obs_request_delpkg_accept',
+                'cond':  lambda bs, req: req['state'] == 'accepted' and req['deleteproject'] and req['deletepackage'],
+                'sub':   '${reqid} accepted: ${deleteproject}/${deletepackage} was deleted',
+                'to':    ['author'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'deleteproject', 'deletepackage'],
+                'detail?':False,
+                'tgtprj': 'deleteproject',
+             },
+             {
+                'temp':  'obs_request_changedevel_accept',
+                'cond':  lambda bs, req: req['state'] == 'accepted' and req['origintype'] == 'change_devel',
+                'sub':   '${reqid} accepted: ${sourceproject}/${sourcepackage} is devel of ${targetproject}/${targetpackage}',
+                'to':    ['author', 'bugowners', 'devels'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'temp':  'obs_request_accept',
+                'cond':  lambda bs, req: req['state'] == 'accepted',
+                'sub':   '${reqid} accepted: ${targetproject}/${targetpackage}',
+                'to':    ['author', 'bugowners', 'devels'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+            ),
+        'OBS_SRCSRV_REQUEST_STATECHANGE':
+            (
+             {
+                'cond':  lambda bs, req: req['state'] == 'declined' and req['role'] and req['person'],
+                'temp':  'obs_request_maintainer_decline',
+                'sub':   '${reqid} declined: Request to maintain ${targetproject}/${targetpackage}',
+                'to':    ['author'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage', 'role', 'person'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'declined' and req['deleteproject'] and req['deletepackage'],
+                'temp':  'obs_request_delpkg_decline',
+                'sub':   '${reqid} declined: Request to delete ${deleteproject}/${deletepackge}',
+                'to':    ['author'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'deleteproject', 'deletepackage'],
+                'detail?':False,
+                'tgtprj': 'deleteproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'declined' and req['origintype'] == 'change_devel',
+                'temp':  'obs_request_changedevel_decline',
+                'sub':   '${reqid} declined: ${sourceproject}/${sourcepackage} as devel of ${targetproject}/${targetpackage}',
+                'to':    ['author'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'declined' and req['comment'] == AUTO_REJECT_COMMENT,
+                'temp':  'obs_request_auto_reject',
+                'sub':   '${reqid} auto rejected: ${sourceproject}/${sourcepackage} to ${targetproject}/${targetpackage}',
+                'to':    ['author'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'declined',
+                'temp':  'obs_request_decline',
+                'sub':   '${reqid} declined: ${sourceproject}/${sourcepackage} to ${targetproject}/${targetpackage}',
+                'to':    ['author'],
+                'cc':    ['mailinglist'],
+                'from':  'sender',
+                'fields':['comment', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'revoked' and req['role'] and req['person'],
+                'temp':  'obs_request_maintainer_revoke',
+                'sub':   '${reqid} revoked: Request to maintain ${targetproject}/${targetpackage}',
+                'to':    ['mailinglist'],
+                'cc':    [],
+                'from':  'who',
+                'fields':['comment', 'targetproject', 'targetpackage', 'role', 'person'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'revoked' and req['deleteproject'] and req['deletepackage'],
+                'temp':  'obs_request_delpkg_revoke',
+                'sub':   '${reqid} revoked: Request to delete ${deleteproject}/${deletepackage}',
+                'to':    ['mailinglist'],
+                'cc':    [],
+                'from':  'who',
+                'fields':['comment', 'deleteproject', 'deletepackage'],
+                'detail?':False,
+                'tgtprj': 'deleteproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'revoked' and req['origintype'] == 'change_devel',
+                'temp':  'obs_request_changedevel_revoke',
+                'sub':   '${reqid} revoked: Change devel of ${targetproject}/${targetpackage}',
+                'to':    ['mailinglist'],
+                'cc':    [],
+                'from':  'who',
+                'fields':['comment', 'targetproject', 'targetpackage', 'sourceproject', 'sourcepackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+             {
+                'cond':  lambda bs, req: req['state'] == 'revoked',
+                'temp':  'obs_request_revoke',
+                'sub':   '${reqid} revoked: Changes to ${targetproject}/${targetpackage}',
+                'to':    ['mailinglist'],
+                'cc':    [],
+                'from':  'who',
+                'fields':['comment', 'targetproject', 'targetpackage'],
+                'detail?':False,
+                'tgtprj': 'targetproject',
+             },
+            ),
+        }
+
+USERDATA_CACHE = {}
+
+def logger(level, msg):
+    print level, msg
+
+def _get_reqinfo(bs, rid, details):
+    try:
+        return bs.genRequestInfo(str(rid), show_detail=details)
+    except Exception, e:
+        logger('error', 'failed to get info for req: %s, abort!' %rid)
+        logger('error', str(e))
+        return ''
+
+def _get_userinfo(bs, uid):
+    try:
+        if uid in USERDATA_CACHE:
+            realname, email = USERDATA_CACHE[uid]
+        else:
+            realname, email = bs.getUserData(uid, "realname", "email")
+            USERDATA_CACHE[uid] = (realname, email)
+        if realname == '-':
+            realname = uid
+        return realname, '%s <%s>' % (realname, email)
+    except:
+        return uid, ''
+
+def _expand_addr(bs, req, mails, ml):
+    expanded = []
+
+    for m in set(mails):
+        if m == 'mailinglist':
+            expanded.append(ml)
+        elif m == 'bugowners':
+            bugowners = bs.getPackagePersons(req['targetproject'], req['targetpackage'], 'bugowner')
+            for bugowner in bugowners:
+                expanded.append(_get_userinfo(bs, bugowner)[1])
+        elif m == 'devels':
+            devel = bs.getPackageDevel(req['targetproject'], req['targetpackage'])
+
+            if not devel:
+                devel = bs.getProjectDevel(req['targetproject'])
+
+            if devel:
+                maintainers = bs.getProjectPersons(devel[0], 'maintainer')
+                for maintainer in maintainers:
+                    expanded.append(_get_userinfo(bs, maintainer)[1])
+        elif m in req:
+            expanded.append(_get_userinfo(bs, req[m])[1])
+        else:
+            # some real mailaddrs
+            expanded.append(m)
+
+    # uniquy -> filter out empty -> list
+    return [i for i in set(expanded) if i]
+
+def _is_valid_submitter(temp, author, enabled_users):
+    if temp in ('obs_request_newpkg', 'obs_request_create'):
+        if enabled_users:
+            if author not in enabled_users:
+                return False
+
+    return True
+
+def mailer(request, bs, wi, noreply_sender, ml, bccs,
+           sr_enabled_users = None, templates_dir = '.'):
+    """ Sending mail to mailing list for different kinds of reqs
+    """
+
+    if request['type'] not in MAIL_TRIGGERS.keys():
+        return False
+
+    rid = request['id']
+
+    for ev, triggers in MAIL_TRIGGERS.iteritems():
+        if request['type'] != ev:
+            continue
+
+        for tri in triggers:
+            if not tri['cond'] or tri['cond'](bs, request):
+                tgtprj = request[tri['tgtprj']]
+                if tgtprj is None:
+                    logger('info', 'ignore requests for empty targetproject: %s' % ev)
+                    return False
+
+                if IGNORE_HOME and tgtprj.startswith('home'):
+                    logger('info', 'ignore requests for home project: %s' % ev)
+                    return False
+
+                if not _is_valid_submitter(tri['temp'], request['author'], sr_enabled_users):
+                    bs.reqDecline(rid, msg=AUTO_REJECT_COMMENT)
+                    return False
+
+                logger('info', 'sending mail for %s %s' %(ev, tri['temp']))
+
+                tos = copy.copy(tri['to'])
+                ccs = copy.copy(tri['cc'])
+
+                reqinfo = _get_reqinfo(bs, rid, tri['detail?'])
+                wi['reqinfo'] = reqinfo
+
+                if tgtprj.startswith('devel:'):
+                    for alist in (tos, ccs):
+                        maintainers = bs.getProjectPersons(tgtprj, 'maintainer')
+                        if 'mailinglist' in alist:
+                            # if submitter is a maintainer, only send to other maintainers
+                            if request['author'] in maintainers:
+                                alist.remove('mailinglist')
+                                maintainers.remove(request['author'])
+
+                            for maintainer in maintainers:
+                                alist.append(_get_userinfo(bs, maintainer)[1])
+
+                mailto_list = _expand_addr(bs, request, tos, ml)
+                mailcc_list = _expand_addr(bs, request, ccs, ml)
+
+                has_noreply = False
+                for alist in (mailto_list, mailcc_list):
+                    for pair in alist:
+                        if noreply_sender in pair:
+                            alist.remove(pair)
+                            has_noreply = True
+
+                if has_noreply:
+                    if ml in mailcc_list:
+                        mailcc_list.remove(ml)
+                    if ml not in mailto_list:
+                        mailto_list.insert(0, ml)
+
+                wi['To'] = mailto_list
+                wi['Cc'] = mailcc_list
+
+                if bccs:
+                    wi['Bcc'] = bccs
+
+                if tri['from']:
+                    realname = _get_userinfo(bs, request[tri['from']])[0]
+                else:
+                    realname = 'Tizen OBS'
+                wi['realname'] = realname
+                wi['From'] = '%s <%s>' % (realname, noreply_sender)
+
+
+                first_to = tos[0]
+                if first_to == 'mailinglist':
+                    wi['receipt'] = 'List'
+                else:
+                    wi['receipt'] =  _get_userinfo(bs, request[first_to])[0]
+
+                wi['realname'] = realname
+
+                wi['template'] = tri['temp']
+                from string import Template
+                wi['subject'] = Template(tri['sub']).safe_substitute(request, reqid=str(rid))
+
+                # other items from obs_event
+                for var in tri['fields']:
+                    wi[var] = request[var]
+
+                break
+
+    if 'template' in wi.keys():
+        template_str = file(os.path.join(templates_dir, wi['template'])).read()
+        msg = []
+        try:
+            from Cheetah.Template import Template
+            template = Template(template_str, searchList = wi)
+            template.msg = "\n".join(msg)
+            body = str(template)
+        except ImportError:
+            from string import Template
+            template = Template(template_str)
+            body = template.safe_substitute(wi, msg="\n".join(msg))
+        wi['body'] = body.replace('\n','\\n')
+
+
+    return wi
+