Chromium Code Reviews| Index: tools/check_git_config.py |
| diff --git a/tools/check_git_push_access.py b/tools/check_git_config.py |
| similarity index 79% |
| rename from tools/check_git_push_access.py |
| rename to tools/check_git_config.py |
| index 90bb23d84bdc4ddda1374727730139245324dbc2..18b62ef378c195f3a603966564fe644726fd1bc5 100755 |
| --- a/tools/check_git_push_access.py |
| +++ b/tools/check_git_config.py |
| @@ -4,21 +4,19 @@ |
| # found in the LICENSE file. |
| """Script that attempts to push to a special git repository to verify that git |
| -credentials are configured correctly. It also attempts to fix misconfigurations |
| -if possible. |
| +credentials are configured correctly. It also verifies that gclient solution is |
| +configured to use git checkout. |
| It will be added as gclient hook shortly before Chromium switches to git and |
| removed after the switch. |
| When running as hook in *.corp.google.com network it will also report status |
| of the push attempt to the server (on appengine), so that chrome-infra team can |
| -collect information about misconfigured Git accounts (to fix them). |
| - |
| -When invoked manually will do the access test and submit the report regardless |
| -of where it is running. |
| +collect information about misconfigured Git accounts. |
| """ |
| import contextlib |
| +import datetime |
| import errno |
| import getpass |
| import json |
| @@ -26,6 +24,7 @@ import logging |
| import netrc |
| import optparse |
| import os |
| +import pprint |
| import shutil |
| import socket |
| import ssl |
| @@ -40,10 +39,16 @@ import urlparse |
| # Absolute path to src/ directory. |
| REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| +# Absolute path to a file with gclient solutions. |
| +GCLIENT_CONFIG = os.path.join(os.path.dirname(REPO_ROOT), '.gclient') |
| + |
| # Incremented whenever some changes to scrip logic are made. Change in version |
| # will cause the check to be rerun on next gclient runhooks invocation. |
| CHECKER_VERSION = 0 |
| +# Do not attempt to upload a report after this date. |
| +UPLOAD_DISABLE_TS = datetime.datetime(2014, 10, 1) |
| + |
| # URL to POST json with results to. |
| MOTHERSHIP_URL = ( |
| 'https://chromium-git-access.appspot.com/' |
| @@ -52,6 +57,14 @@ MOTHERSHIP_URL = ( |
| # Repository to push test commits to. |
| TEST_REPO_URL = 'https://chromium.googlesource.com/a/playground/access_test' |
| +# Git-compatible gclient solution. |
| +GOOD_GCLIENT_SOLUTION = { |
| + 'name': 'src', |
| + 'deps_file': '.DEPS.git', |
| + 'managed': False, |
| + 'url': 'https://chromium.googlesource.com/chromium/src.git', |
| +} |
| + |
| # Possible chunks of git push response in case .netrc is misconfigured. |
| BAD_ACL_ERRORS = ( |
| '(prohibited by Gerrit)', |
| @@ -125,6 +138,26 @@ def get_git_version(): |
| return '' |
| +def read_gclient_solution(): |
| + """Read information about 'src' gclient solution from .gclient file. |
| + |
| + Returns tuple: |
| + (url, deps_file, managed) |
| + or |
| + (None, None, None) if no such solution. |
| + """ |
| + try: |
| + env = {} |
| + execfile(GCLIENT_CONFIG, env, env) |
| + for sol in env['solutions']: |
| + if sol['name'] == 'src': |
| + return sol.get('url'), sol.get('deps_file'), sol.get('managed') |
|
Vadim Sh.
2014/08/18 23:29:21
I intentionally skip custom_deps and other stuff.
|
| + return None, None, None |
| + except Exception: |
| + logging.exception('Failed to read .gclient solution') |
| + return None, None, None |
| + |
| + |
| def scan_configuration(): |
| """Scans local environment for git related configuration values.""" |
| # Git checkout? |
| @@ -150,6 +183,9 @@ def scan_configuration(): |
| logging.exception('Failed to read netrc from %s', netrc_path) |
| netrc_obj = None |
| + # Read gclient 'src' solution. |
| + gclient_url, gclient_deps, gclient_managed = read_gclient_solution() |
| + |
| return { |
| 'checker_version': CHECKER_VERSION, |
| 'is_git': is_git, |
| @@ -165,6 +201,9 @@ def scan_configuration(): |
| read_netrc_user(netrc_obj, 'chromium.googlesource.com'), |
| 'chrome_internal_netrc_email': |
| read_netrc_user(netrc_obj, 'chrome-internal.googlesource.com'), |
| + 'gclient_deps': gclient_deps, |
| + 'gclient_managed': gclient_managed, |
| + 'gclient_url': gclient_url, |
| } |
| @@ -243,14 +282,12 @@ class Runner(object): |
| logging.warning(text) |
| -def check_git_access(conf, report_url, verbose): |
| +def check_git_config(conf, report_url, verbose): |
| """Attempts to push to a git repository, reports results to a server. |
| Returns True if the check finished without incidents (push itself may |
| have failed) and should NOT be retried on next invocation of the hook. |
| """ |
| - logging.warning('Checking push access to the git repository...') |
| - |
| # Don't even try to push if netrc is not configured. |
| if not conf['chromium_netrc_email']: |
| return upload_report( |
| @@ -268,6 +305,7 @@ def check_git_access(conf, report_url, verbose): |
| flake = False |
| started = time.time() |
| try: |
| + logging.warning('Checking push access to the git repository...') |
| with temp_directory() as tmp: |
| # Prepare a simple commit on a new timeline. |
| runner = Runner(tmp, verbose) |
| @@ -296,6 +334,12 @@ def check_git_access(conf, report_url, verbose): |
| logging.exception('Unexpected exception when pushing') |
| flake = True |
| + if push_works: |
| + logging.warning('Git push works!') |
| + else: |
| + logging.warning( |
| + 'Git push doesn\'t work, which is fine if you are not a committer.') |
| + |
| uploaded = upload_report( |
| conf, |
| report_url, |
| @@ -306,6 +350,28 @@ def check_git_access(conf, report_url, verbose): |
| return uploaded and not flake |
| +def check_gclient_config(conf): |
| + """Shows warning if gclient solution is not properly configured for git.""" |
| + current = { |
| + 'name': 'src', |
| + 'deps_file': conf['gclient_deps'], |
| + 'managed': conf['gclient_managed'], |
| + 'url': conf['gclient_url'], |
| + } |
| + if current != GOOD_GCLIENT_SOLUTION: |
| + print '-' * 80 |
| + print 'Your gclient solution is not set to use supported git workflow!' |
| + print 'Your \'src\' solution (in %s):' % GCLIENT_CONFIG |
| + print pprint.pformat(current, indent=2) |
| + print 'Correct \'src\' solution to use git:' |
| + print pprint.pformat(GOOD_GCLIENT_SOLUTION, indent=2) |
| + print 'Please update your .gclient file ASAP.' |
| + print '-' * 80 |
| + |
| + |
| def upload_report( |
| conf, report_url, verbose, push_works, push_log, push_duration_ms): |
| """Posts report to the server, returns True if server accepted it. |
| @@ -320,19 +386,12 @@ def upload_report( |
| push_duration_ms=push_duration_ms) |
| as_bytes = json.dumps({'access_check': report}, indent=2, sort_keys=True) |
| - |
| - if push_works: |
| - logging.warning('Git push works!') |
| - else: |
| - logging.warning( |
| - 'Git push doesn\'t work, which is fine if you are not a committer.') |
| - |
| if verbose: |
| print 'Status of git push attempt:' |
| print as_bytes |
| - # Do not upload it outside of corp. |
| - if not is_in_google_corp(): |
| + # Do not upload it outside of corp or if server side is already disabled. |
| + if not is_in_google_corp() or datetime.datetime.now() > UPLOAD_DISABLE_TS: |
| if verbose: |
| print ( |
| 'You can send the above report to chrome-git-migration@google.com ' |
| @@ -386,19 +445,27 @@ def main(args): |
| format='%(message)s', |
| level=logging.INFO if options.verbose else logging.WARN) |
| - # When invoked not as hook, always run the check. |
| + # When invoked not as a hook, always run the check. |
| if not options.running_as_hook: |
| - if check_git_access(scan_configuration(), options.report_url, True): |
| - return 0 |
| - return 1 |
| + config = scan_configuration() |
| + check_gclient_config(config) |
| + check_git_config(config, options.report_url, True) |
| + return 0 |
| - # Otherwise, do it only on google owned, non-bot machines. |
| - if is_on_bot() or not is_in_google_corp(): |
| - logging.info('Skipping the check: bot or non corp.') |
| + # Always do nothing on bots. |
| + if is_on_bot(): |
| return 0 |
| - # Skip the check if current configuration was already checked. |
| + # Read current config, verify gclient solution looks correct. |
| config = scan_configuration() |
| + check_gclient_config(config) |
| + |
| + # Do not attempt to push from non-google owned machines. |
| + if not is_in_google_corp(): |
| + logging.info('Skipping git push check: non *.corp.google.com machine.') |
| + return 0 |
| + |
| + # Skip git push check if current configuration was already checked. |
| if config == read_last_configuration(): |
| logging.info('Check already performed, skipping.') |
| return 0 |
| @@ -406,7 +473,7 @@ def main(args): |
| # Run the check. Mark configuration as checked only on success. Ignore any |
| # exceptions or errors. This check must not break gclient runhooks. |
| try: |
| - ok = check_git_access(config, options.report_url, False) |
| + ok = check_git_config(config, options.report_url, False) |
| if ok: |
| write_last_configuration(config) |
| else: |