Skip to content

Commit

Permalink
Add an mb audit command to track the GYP->GN progress.
Browse files Browse the repository at this point in the history
This adds a command by which we can track
  - which builders no longer exist but are in the config file
    and should be purged
  - which builders aren't in the config file, meaning we haven't
    looked at them
  - which builders still need to have their flags checked.
  - which builders are still on GYP

R=estaab@chromium.org
BUG=432967, 481692

Review URL: https://codereview.chromium.org/1794573002

Cr-Commit-Position: refs/heads/master@{#381094}
  • Loading branch information
dpranke authored and Commit bot committed Mar 14, 2016
1 parent aa97e28 commit 867bcf4
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 0 deletions.
7 changes: 7 additions & 0 deletions tools/mb/docs/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ differences can be subtle. We won't even go into how the `targets` and
The `-b/--builder`, `-c/--config`, `-f/--config-file`, `-m/--master`,
`-q/--quiet`, and `-v/--verbose` flags work as documented for `mb gen`.

### `mb audit`

`mb audit` is used to track the progress of the GYP->GN migration. You can
use it to check a single master, or all the masters we care about. See
`mb help audit` for more details (most people are not expected to care about
this).

### `mb gen`

`mb gen` is responsible for generating the Ninja files by invoking either GYP
Expand Down
133 changes: 133 additions & 0 deletions tools/mb/mb.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
import sys
import subprocess
import tempfile
import urllib2

from collections import OrderedDict

def main(args):
mbw = MetaBuildWrapper()
Expand Down Expand Up @@ -142,6 +145,24 @@ def AddCommonOptions(subp):
'(default is //tools/mb/mb_config.pyl)')
subp.set_defaults(func=self.CmdValidate)

subp = subps.add_parser('audit',
help='Audit the config file to track progress')
subp.add_argument('-f', '--config-file', metavar='PATH',
default=self.default_config,
help='path to config file '
'(default is //tools/mb/mb_config.pyl)')
subp.add_argument('-i', '--internal', action='store_true',
help='check internal masters also')
subp.add_argument('-m', '--master', action='append',
help='master to audit (default is all non-internal '
'masters in file)')
subp.add_argument('-u', '--url-template', action='store',
default='https://build.chromium.org/p/'
'{master}/json/builders',
help='URL scheme for JSON APIs to buildbot '
'(default: %(default)s) ')
subp.set_defaults(func=self.CmdAudit)

subp = subps.add_parser('help',
help='Get help on a subcommand.')
subp.add_argument(nargs='?', action='store', dest='subcommand',
Expand Down Expand Up @@ -334,6 +355,111 @@ def RecurseMixins(current_mixin):
self.Print('mb config file %s looks ok.' % self.args.config_file)
return 0

def CmdAudit(self):
"""Track the progress of the GYP->GN migration on the bots."""

stats = OrderedDict()
STAT_MASTER_ONLY = 'Master only'
STAT_CONFIG_ONLY = 'Config only'
STAT_TBD = 'Still TBD'
STAT_GYP = 'Still GYP'
STAT_DONE = 'Done (on GN)'
stats[STAT_MASTER_ONLY] = 0
stats[STAT_CONFIG_ONLY] = 0
stats[STAT_TBD] = 0
stats[STAT_GYP] = 0
stats[STAT_DONE] = 0

def PrintBuilders(heading, builders):
stats.setdefault(heading, 0)
stats[heading] += len(builders)
if builders:
self.Print(' %s:' % heading)
for builder in sorted(builders):
self.Print(' %s' % builder)

self.ReadConfigFile()

masters = self.args.master or self.masters
for master in sorted(masters):
url = self.args.url_template.replace('{master}', master)

self.Print('Auditing %s' % master)

MASTERS_TO_SKIP = (
'client.skia',
'client.v8.fyi',
'tryserver.v8',
)
if master in MASTERS_TO_SKIP:
# Skip these bots because converting them is the responsibility of
# those teams and out of scope for the Chromium migration to GN.
self.Print(' Skipped (out of scope)')
self.Print('')
continue

INTERNAL_MASTERS = (
'chrome',
'chrome.continuous',
'official.desktop',
'official.desktop.continuous',
)
if master in INTERNAL_MASTERS and not self.args.internal:
# Skip these because the servers aren't accessible by default ...
self.Print(' Skipped (internal)')
self.Print('')
continue

try:
# Fetch the /builders contents from the buildbot master. The
# keys of the dict are the builder names themselves.
json_contents = self.Fetch(url)
d = json.loads(json_contents)
except Exception as e:
self.Print(str(e))
return 1

config_builders = set(self.masters[master])
master_builders = set(d.keys())
both = master_builders & config_builders
master_only = master_builders - config_builders
config_only = config_builders - master_builders
tbd = set()
gyp = set()
done = set()

for builder in both:
config = self.masters[master][builder]
if config == 'tbd':
tbd.add(builder)
else:
# TODO(dpranke): Check if MB is actually running?
vals = self.FlattenConfig(config)
if vals['type'] == 'gyp':
gyp.add(builder)
else:
done.add(builder)

if master_only or config_only or tbd or gyp:
PrintBuilders(STAT_MASTER_ONLY, master_only)
PrintBuilders(STAT_CONFIG_ONLY, config_only)
PrintBuilders(STAT_TBD, tbd)
PrintBuilders(STAT_GYP, gyp)
else:
self.Print(' ... ok')

stats[STAT_DONE] += len(done)

self.Print('')

fmt = '{:<27} {:>4}'
self.Print(fmt.format('Totals', str(sum(int(v) for v in stats.values()))))
self.Print(fmt.format('-' * 27, '----'))
for stat, count in stats.items():
self.Print(fmt.format(stat, str(count)))

return 0

def GetConfig(self):
build_dir = self.args.path[0]

Expand Down Expand Up @@ -1096,6 +1222,13 @@ def Exists(self, path):
# This function largely exists so it can be overridden for testing.
return os.path.exists(path)

def Fetch(self, url):

f = urllib2.urlopen(url)
contents = f.read()
f.close()
return contents

def GNTargetName(self, target):
return target[:-len('_apk')] if target.endswith('_apk') else target

Expand Down

0 comments on commit 867bcf4

Please sign in to comment.