Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: releaseAutomation.py

Issue 29508667: Issue 4354, 4355 - handle dirty/outdated repos on release (Closed)
Patch Set: Created Aug. 7, 2017, 3:40 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This Source Code Form is subject to the terms of the Mozilla Public 1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 4
5 import os 5 import os
6 import re 6 import re
7 import codecs 7 import codecs
8 import subprocess 8 import subprocess
9 import tarfile 9 import tarfile
10 import json 10 import json
11 11
Vasily Kuznetsov 2017/08/08 18:10:12 There's no need for this empty line. The imports f
tlucas 2017/08/09 08:12:35 Acknowledged.
tlucas 2017/08/15 14:40:12 Done.
12 from itertools import groupby
13
12 from packager import readMetadata, getDefaultFileName 14 from packager import readMetadata, getDefaultFileName
13 15
14 16
15 def get_dependencies(prefix, repos): 17 def get_dependencies(prefix, repos):
16 from ensure_dependencies import read_deps, safe_join 18 from ensure_dependencies import read_deps, safe_join
17 repo = repos[prefix] 19 repo = repos[prefix]
18 deps = read_deps(repo) 20 deps = read_deps(repo)
19 if deps: 21 if deps:
20 for subpath in deps: 22 for subpath in deps:
21 if subpath.startswith('_'): 23 if subpath.startswith('_'):
(...skipping 16 matching lines...) Expand all
38 if os.path.basename(fileinfo.name) in ('.hgtags', '.hgig nore'): 40 if os.path.basename(fileinfo.name) in ('.hgtags', '.hgig nore'):
39 continue 41 continue
40 filedata = repoarchive.extractfile(fileinfo) 42 filedata = repoarchive.extractfile(fileinfo)
41 fileinfo.name = re.sub(r'^[^/]+/', prefix, fileinfo.name ) 43 fileinfo.name = re.sub(r'^[^/]+/', prefix, fileinfo.name )
42 archive.addfile(fileinfo, filedata) 44 archive.addfile(fileinfo, filedata)
43 finally: 45 finally:
44 process.stdout.close() 46 process.stdout.close()
45 process.wait() 47 process.wait()
46 48
47 49
50 def repo_has_uncommitted(aborts_process=True):
51 """Checks if the given repository is clean"""
52 uncommitted = False
Vasily Kuznetsov 2017/08/08 18:10:12 You're spending quite some effort reformatting the
tlucas 2017/08/09 08:12:35 Acknowledged.
tlucas 2017/08/15 14:40:12 Done.
53 status_mapping = {
54 'M': 'modified',
55 'A': 'added',
56 'R': 'removed',
57 '!': 'missing',
58 '?': 'untracked',
59 }
60
61 # Check for any uncommitted changes
62 buff = subprocess.check_output(['hg', 'status'])
63 if len(buff):
64 uncommitted = True
65 dirty_files = buff.strip().split(os.linesep)
66 print('Dirty / uncommitted changes in repository!')
Vasily Kuznetsov 2017/08/08 18:10:11 Using print as a function only seems to work under
tlucas 2017/08/09 08:12:35 Acknowledged.
tlucas 2017/08/15 14:40:12 Done.
67 grouped_dirty = groupby(dirty_files, key=lambda x: x.split(' ')[0])
68 for dirty_grp in grouped_dirty:
69 print('{}:'.format(status_mapping[dirty_grp[0]]))
70 for dirty in dirty_grp[1]:
71 print(' {}'.format(dirty.split(' ')[1]))
72
73 return uncommitted, aborts_process
74
75
76 def repo_has_outgoing(aborts_process=False):
77 """Checks whether there would be outgoing changesets to the given path"""
78 try:
79 buff = subprocess.check_output(['hg', 'outgoing'])
80 print('Detected outgoing changesets:')
81 print(buff)
82 return True, aborts_process
83 except subprocess.CalledProcessError:
84 return False, aborts_process
85
86
87 def repo_has_incoming(repo_paths, aborts_process=True):
88 """Checks whether the local repositories are up-to-date"""
89 incoming = False
90
91 for repo_path in repo_paths:
92 try:
93 buff = subprocess.check_output(['hg', 'incoming', '-R', repo_path])
94 print('Detected incoming changesets:')
Vasily Kuznetsov 2017/08/08 18:10:12 Here we're printing the incoming changesets but ac
tlucas 2017/08/09 08:12:35 Acknowledged.
tlucas 2017/08/15 14:40:12 Done.
95 print(buff)
96 incoming = True
97 except subprocess.CalledProcessError:
98 pass
99
100 return incoming, aborts_process
101
102
103 def ask_to_continue():
104 """Asks the user if he wants to continue despite facing warnings"""
105 try:
106 input = raw_input
Vasily Kuznetsov 2017/08/08 18:10:11 AFAIK, this compatibility trick doesn't work (unde
tlucas 2017/08/09 08:12:34 I tested a snippet of this, but not in function-sc
Vasily Kuznetsov 2017/08/09 17:09:09 Yes, I think it would be the best to ignore Python
tlucas 2017/08/15 14:40:12 Done.
107 except NameError:
108 pass
109
110 print('The above error/s has/have been detected within the repositories.')
Vasily Kuznetsov 2017/08/08 18:10:11 I know that you took this from the ticket, but I'm
tlucas 2017/08/09 08:12:35 I like it (and it was actually me, who added this
tlucas 2017/08/15 14:40:12 Done.
111 print('You might want to check whether this is ok or not.')
112 print('Are you sure about continuing the release-process?')
113 while True:
Vasily Kuznetsov 2017/08/08 18:10:11 What do you think about rewriting this loop, and t
tlucas 2017/08/09 08:12:35 Acknowledged.
tlucas 2017/08/15 14:40:12 Done.
114 choice = input('Please choose (yes / no): ')
115 if choice.lower() not in ('yes', 'no'):
Vasily Kuznetsov 2017/08/08 18:10:11 ('yes', 'no') should be a set (this is error A102
tlucas 2017/08/09 08:12:35 This is removed while following your proposed appr
tlucas 2017/08/15 14:40:12 Done. Kept the reminder on what to specifically en
116 print('Please answer "yes" or "no"!')
117 else:
118 break
119
120 return choice.lower() == 'yes'
121
122
48 def run(baseDir, type, version, keyFile, downloadsRepo): 123 def run(baseDir, type, version, keyFile, downloadsRepo):
124 # run repository-checks and bail out early, in case the user does not
125 # explicitly want to continue OR if the check would cause the process to
126 # abort anyway
127 repo_checks = (
Vasily Kuznetsov 2017/08/08 18:10:11 I think the new code in this function is unnecessa
tlucas 2017/08/09 08:12:35 Acknowledged. I'll also rename the function accord
tlucas 2017/08/15 14:40:12 Done.
128 (repo_has_uncommitted, ()),
129 (repo_has_outgoing, ()),
130 (repo_has_incoming, ((baseDir, downloadsRepo),)),
131 )
132
133 check_results = [func(*args) for func, args in repo_checks]
134
135 if (
136 any(check and aborts for check, aborts in check_results)
137 or (
138 any(check and not aborts for check, aborts in check_results)
139 and not ask_to_continue()
140 )):
141 print('Aborting release.')
142 return 1
143
49 if type == 'gecko': 144 if type == 'gecko':
50 import buildtools.packagerGecko as packager 145 import buildtools.packagerGecko as packager
51 elif type == 'safari': 146 elif type == 'safari':
52 import buildtools.packagerSafari as packager 147 import buildtools.packagerSafari as packager
53 elif type == 'edge': 148 elif type == 'edge':
54 import buildtools.packagerEdge as packager 149 import buildtools.packagerEdge as packager
55 elif type == 'chrome': 150 elif type == 'chrome':
56 import buildtools.packagerChrome as packager 151 import buildtools.packagerChrome as packager
57 152
58 # Replace version number in metadata file "manually", ConfigParser will mess 153 # Replace version number in metadata file "manually", ConfigParser will mess
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 create_sourcearchive(baseDir, archivePath) 211 create_sourcearchive(baseDir, archivePath)
117 downloads.append(archivePath) 212 downloads.append(archivePath)
118 213
119 # Now add the downloads and commit 214 # Now add the downloads and commit
120 subprocess.check_call(['hg', 'add', '-R', downloadsRepo] + downloads) 215 subprocess.check_call(['hg', 'add', '-R', downloadsRepo] + downloads)
121 subprocess.check_call(['hg', 'commit', '-R', downloadsRepo, '-m', 'Releasing %s %s' % (extensionName, version)]) 216 subprocess.check_call(['hg', 'commit', '-R', downloadsRepo, '-m', 'Releasing %s %s' % (extensionName, version)])
122 217
123 # Push all changes 218 # Push all changes
124 subprocess.check_call(['hg', 'push', '-R', baseDir]) 219 subprocess.check_call(['hg', 'push', '-R', baseDir])
125 subprocess.check_call(['hg', 'push', '-R', downloadsRepo]) 220 subprocess.check_call(['hg', 'push', '-R', downloadsRepo])
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld