blob: 982354cf8b896604bd2f81855f7b39a75e006e14 [file] [log] [blame]
Haibo Huang39aaab62019-01-25 12:23:03 -08001# Copyright (C) 2018 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Send notification email if new version is found.
15
16Example usage:
17external_updater_notifier \
Haibo Huang39aaab62019-01-25 12:23:03 -080018 --history ~/updater/history \
Haibo Huang39287b12019-01-30 15:48:27 -080019 --generate_change \
20 --recipients xxx@xxx.xxx \
21 googletest
Haibo Huang39aaab62019-01-25 12:23:03 -080022"""
23
24import argparse
25import json
26import os
Haibo Huang39287b12019-01-30 15:48:27 -080027import re
Haibo Huang39aaab62019-01-25 12:23:03 -080028import subprocess
29import time
30
31
32def parse_args():
33 """Parses commandline arguments."""
34
35 parser = argparse.ArgumentParser(
36 description='Check updates for third party projects in external/.')
37 parser.add_argument(
Haibo Huang39aaab62019-01-25 12:23:03 -080038 '--history',
39 help='Path of history file. If doesn'
40 't exist, a new one will be created.')
41 parser.add_argument(
42 '--recipients',
43 help='Comma separated recipients of notification email.')
Haibo Huang39287b12019-01-30 15:48:27 -080044 parser.add_argument(
45 '--generate_change',
46 help='If set, an upgrade change will be uploaded to Gerrit.',
47 action='store_true', required=False)
48 parser.add_argument(
49 'paths', nargs='*',
50 help='Paths of the project.')
Haibo Huang39aaab62019-01-25 12:23:03 -080051
52 return parser.parse_args()
53
54
Haibo Huang39287b12019-01-30 15:48:27 -080055CHANGE_URL_PATTERN = r'(https:\/\/[^\s]*android-review[^\s]*) Upgrade'
56CHANGE_URL_RE = re.compile(CHANGE_URL_PATTERN)
Haibo Huang39aaab62019-01-25 12:23:03 -080057
Haibo Huang39287b12019-01-30 15:48:27 -080058
59def _send_email(proj, latest_ver, recipient, upgrade_log):
60 print('Sending email for {}: {}'.format(proj, latest_ver))
61 msg = "New version: {}".format(latest_ver)
62 match = CHANGE_URL_RE.search(upgrade_log)
63 if match is not None:
64 msg += '\n\nAn upgrade change is generated at:\n{}'.format(
65 match.group(1))
66
67 msg += '\n\n'
68 msg += upgrade_log
69
Haibo Huang39aaab62019-01-25 12:23:03 -080070 subprocess.run(['sendgmr', '--to=' + recipient,
71 '--subject=' + proj], check=True,
72 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
73 input=msg, encoding='ascii')
74
75
Haibo Huang39287b12019-01-30 15:48:27 -080076def _process_results(args, history, results):
Haibo Huang39aaab62019-01-25 12:23:03 -080077 for proj, res in results.items():
78 if 'latest' not in res:
79 continue
80 latest_ver = res['latest']
81 current_ver = res['current']
82 if latest_ver == current_ver:
83 continue
84 proj_history = history.setdefault(proj, {})
85 if latest_ver not in proj_history:
Haibo Huang39287b12019-01-30 15:48:27 -080086 upgrade_log = _upgrade(proj) if args.generate_change else ""
Haibo Huang39aaab62019-01-25 12:23:03 -080087 try:
Haibo Huang39287b12019-01-30 15:48:27 -080088 _send_email(proj, latest_ver, args.recipients, upgrade_log)
Haibo Huang39aaab62019-01-25 12:23:03 -080089 proj_history[latest_ver] = int(time.time())
90 except subprocess.CalledProcessError as err:
91 msg = """Failed to send email for {} ({}).
92stdout: {}
93stderr: {}""".format(proj, latest_ver, err.stdout, err.stderr)
94 print(msg)
95
96
Haibo Huang39287b12019-01-30 15:48:27 -080097RESULT_FILE_PATH = '/tmp/update_check_result.json'
98
99
Haibo Huang39aaab62019-01-25 12:23:03 -0800100def send_notification(args):
101 """Compare results and send notification."""
102 results = {}
Haibo Huang39287b12019-01-30 15:48:27 -0800103 with open(RESULT_FILE_PATH, 'r') as f:
Haibo Huang39aaab62019-01-25 12:23:03 -0800104 results = json.load(f)
105 history = {}
106 try:
107 with open(args.history, 'r') as f:
108 history = json.load(f)
109 except FileNotFoundError:
110 pass
111
Haibo Huang39287b12019-01-30 15:48:27 -0800112 _process_results(args, history, results)
Haibo Huang39aaab62019-01-25 12:23:03 -0800113
114 with open(args.history, 'w') as f:
115 json.dump(history, f, sort_keys=True)
116
117
Haibo Huang39287b12019-01-30 15:48:27 -0800118def _upgrade(proj):
119 out = subprocess.run(['out/soong/host/linux-x86/bin/external_updater',
120 'update', '--branch_and_commit', '--push_change',
121 proj],
122 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
123 cwd=os.environ['ANDROID_BUILD_TOP'])
124 stdout = out.stdout.decode('utf-8')
125 stderr = out.stderr.decode('utf-8')
126 return """
127====================
128| Debug Info |
129====================
130-=-=-=-=stdout=-=-=-=-
131{}
132
133-=-=-=-=stderr=-=-=-=-
134{}
135""".format(stdout, stderr)
136
137
138def _check_updates(args):
139 subprocess.run(['out/soong/host/linux-x86/bin/external_updater',
140 'check',
141 '--json_output', RESULT_FILE_PATH,
142 '--delay', '0'] + args.paths,
143 cwd=os.environ['ANDROID_BUILD_TOP'])
144
145
Haibo Huang39aaab62019-01-25 12:23:03 -0800146def main():
147 """The main entry."""
148
149 args = parse_args()
Haibo Huang39287b12019-01-30 15:48:27 -0800150 _check_updates(args)
Haibo Huang39aaab62019-01-25 12:23:03 -0800151 send_notification(args)
152
153
154if __name__ == '__main__':
155 main()