xref: /aosp_15_r20/external/webrtc/tools_webrtc/version_updater/update_version.py (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1#!/usr/bin/env vpython3
2
3# Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
4#
5# Use of this source code is governed by a BSD-style license
6# that can be found in the LICENSE file in the root of the source
7# tree. An additional intellectual property rights grant can be found
8# in the file PATENTS.  All contributing project authors may
9# be found in the AUTHORS file in the root of the source tree.
10
11"""Script to auto-update the WebRTC source version in call/version.cc"""
12
13import argparse
14import datetime
15import logging
16import os
17import re
18import subprocess
19import sys
20
21
22def FindSrcDirPath():
23  """Returns the abs path to the src/ dir of the project."""
24  src_dir = os.path.dirname(os.path.abspath(__file__))
25  while os.path.basename(src_dir) != 'src':
26    src_dir = os.path.normpath(os.path.join(src_dir, os.pardir))
27  return src_dir
28
29
30UPDATE_BRANCH_NAME = 'webrtc_version_update'
31CHECKOUT_SRC_DIR = FindSrcDirPath()
32
33NOTIFY_EMAIL = '[email protected]'
34
35
36def _RemovePreviousUpdateBranch():
37  active_branch, branches = _GetBranches()
38  if active_branch == UPDATE_BRANCH_NAME:
39    active_branch = 'main'
40  if UPDATE_BRANCH_NAME in branches:
41    logging.info('Removing previous update branch (%s)', UPDATE_BRANCH_NAME)
42    subprocess.check_call(['git', 'checkout', active_branch])
43    subprocess.check_call(['git', 'branch', '-D', UPDATE_BRANCH_NAME])
44  logging.info('No branch to remove')
45
46
47def _GetLastAuthor():
48  """Returns a string with the author of the last commit."""
49  author = subprocess.check_output(
50      ['git', 'log', '-1', '--pretty=format:"%an"'],
51      universal_newlines=True).splitlines()
52  return author
53
54
55def _GetBranches():
56  """Returns a tuple (active, branches).
57
58    'active' is a string with name of the currently active branch, while
59     'branches' is the list of all branches.
60    """
61  lines = subprocess.check_output(['git', 'branch'],
62                                  universal_newlines=True).splitlines()
63  branches = []
64  active = ''
65  for line in lines:
66    if '*' in line:
67      # The assumption is that the first char will always be the '*'.
68      active = line[1:].strip()
69      branches.append(active)
70    else:
71      branch = line.strip()
72      if branch:
73        branches.append(branch)
74  return active, branches
75
76
77def _CreateUpdateBranch():
78  logging.info('Creating update branch: %s', UPDATE_BRANCH_NAME)
79  subprocess.check_call(['git', 'checkout', '-b', UPDATE_BRANCH_NAME])
80
81
82def _UpdateWebRTCVersion(filename):
83  with open(filename, 'rb') as f:
84    content = f.read().decode('utf-8')
85  d = datetime.datetime.utcnow()
86  # pylint: disable=line-too-long
87  new_content = re.sub(
88      r'WebRTC source stamp [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}',
89      r'WebRTC source stamp %02d-%02d-%02dT%02d:%02d:%02d' %
90      (d.year, d.month, d.day, d.hour, d.minute, d.second),
91      content,
92      flags=re.MULTILINE)
93  # pylint: enable=line-too-long
94  with open(filename, 'wb') as f:
95    f.write(new_content.encode('utf-8'))
96
97
98def _IsTreeClean():
99  stdout = subprocess.check_output(['git', 'status', '--porcelain'],
100                                   universal_newlines=True)
101  if len(stdout) == 0:
102    return True
103  return False
104
105
106def _LocalCommit():
107  logging.info('Committing changes locally.')
108  d = datetime.datetime.utcnow()
109
110  commit_msg = ('Update WebRTC code version (%02d-%02d-%02dT%02d:%02d:%02d).'
111                '\n\nBug: None')
112  commit_msg = commit_msg % (d.year, d.month, d.day, d.hour, d.minute, d.second)
113  subprocess.check_call(['git', 'add', '--update', '.'])
114  subprocess.check_call(['git', 'commit', '-m', commit_msg])
115
116
117def _UploadCL(commit_queue_mode):
118  """Upload the committed changes as a changelist to Gerrit.
119
120  commit_queue_mode:
121    - 2: Submit to commit queue.
122    - 1: Run trybots but do not submit to CQ.
123    - 0: Skip CQ, upload only.
124  """
125  cmd = [
126      'git', 'cl', 'upload', '--force', '--bypass-hooks', '--bypass-watchlist'
127  ]
128  if commit_queue_mode >= 2:
129    logging.info('Sending the CL to the CQ...')
130    cmd.extend(['-o', 'label=Bot-Commit+1'])
131    cmd.extend(['-o', 'label=Commit-Queue+2'])
132    cmd.extend(['--send-mail', '--cc', NOTIFY_EMAIL])
133  elif commit_queue_mode >= 1:
134    logging.info('Starting CQ dry run...')
135    cmd.extend(['-o', 'label=Commit-Queue+1'])
136  subprocess.check_call(cmd)
137
138
139def main():
140  logging.basicConfig(level=logging.INFO)
141  p = argparse.ArgumentParser()
142  p.add_argument('--clean',
143                 action='store_true',
144                 default=False,
145                 help='Removes any previous local update branch.')
146  opts = p.parse_args()
147
148  if opts.clean:
149    _RemovePreviousUpdateBranch()
150
151  if _GetLastAuthor() == 'webrtc-version-updater':
152    logging.info('Last commit is a version change, skipping CL.')
153    return 0
154
155  version_filename = os.path.join(CHECKOUT_SRC_DIR, 'call', 'version.cc')
156  _CreateUpdateBranch()
157  _UpdateWebRTCVersion(version_filename)
158  if _IsTreeClean():
159    logging.info('No WebRTC version change detected, skipping CL.')
160  else:
161    _LocalCommit()
162    logging.info('Uploading CL...')
163    _UploadCL(2)
164  return 0
165
166
167if __name__ == '__main__':
168  sys.exit(main())
169