ninjalog_uploader: Add user email to ninjalog metadata

Bug: 348527311
Change-Id: Idb623a57a2374f4ed5461a9cf159b2eda62c94f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/5823448
Auto-Submit: Junji Watanabe <jwata@google.com>
Commit-Queue: Junji Watanabe <jwata@google.com>
Reviewed-by: Takuto Ikuta <tikuta@chromium.org>
changes/48/5823448/10
Junji Watanabe 9 months ago committed by LUCI CQ
parent 22f6c9d8e9
commit 4a08b97dd4

@ -5,6 +5,7 @@
import argparse import argparse
import json import json
import logging
import os import os
import subprocess import subprocess
import sys import sys
@ -44,11 +45,14 @@ class Config:
if not config: if not config:
config = { config = {
"is_googler": is_googler(), "user": check_auth().get("email", ""),
"status": None, "status": None,
"countdown": self._countdown, "countdown": self._countdown,
"version": VERSION, "version": VERSION,
} }
if not config.get("user"):
config["user"] = check_auth().get("email", "")
self._config = config self._config = config
@ -62,9 +66,14 @@ class Config:
@property @property
def is_googler(self): def is_googler(self):
return self.user.endswith("@google.com")
@property
def user(self):
if not self._config: if not self._config:
return return
return self._config.get("is_googler") == True return self._config.get("user", "")
@property @property
def countdown(self): def countdown(self):
@ -84,7 +93,7 @@ class Config:
self._config_path, self._config_path,
file=sys.stderr) file=sys.stderr)
return False return False
if not self._config.get("is_googler"): if not self.is_googler:
return False return False
if self._config.get("status") == "opt-out": if self._config.get("status") == "opt-out":
return False return False
@ -138,25 +147,22 @@ def load_config(cfg_path=_DEFAULT_CONFIG_PATH, countdown=_DEFAULT_COUNTDOWN):
return cfg return cfg
def is_googler(): def check_auth():
"""Checks whether this user is Googler or not.""" """Checks auth information."""
p = subprocess.run( p = subprocess.run(
"cipd auth-info", "cipd auth-info --json-output -",
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
text=True, text=True,
shell=True, shell=True,
) )
if p.returncode != 0: if p.returncode != 0:
return False return {}
lines = p.stdout.splitlines() try:
if len(lines) == 0: return json.loads(p.stdout)
return False except json.JSONDecodeError as e:
l = lines[0] logging.error(e)
# |l| will be like 'Logged in as <user>@google.com.' for googler using return {}
# reclient.
return l.startswith("Logged in as ") and l.endswith("@google.com.")
def enabled(): def enabled():
"""Checks whether the build can upload build telemetry.""" """Checks whether the build can upload build telemetry."""

@ -123,7 +123,7 @@ def GetJflag(cmdline):
return int(cmdline[i][len("-j"):]) return int(cmdline[i][len("-j"):])
def GetMetadata(cmdline, ninjalog, exit_code, build_duration): def GetMetadata(cmdline, ninjalog, exit_code, build_duration, user):
"""Get metadata for uploaded ninjalog. """Get metadata for uploaded ninjalog.
Returned metadata has schema defined in Returned metadata has schema defined in
@ -151,6 +151,7 @@ def GetMetadata(cmdline, ninjalog, exit_code, build_duration):
build_configs[k] = str(build_configs[k]) build_configs[k] = str(build_configs[k])
metadata = { metadata = {
"user": user,
"exit_code": exit_code, "exit_code": exit_code,
"build_duration_sec": build_duration, "build_duration_sec": build_duration,
"platform": platform.system(), "platform": platform.system(),
@ -278,7 +279,7 @@ def main():
return 0 return 0
metadata = GetMetadata(args.cmdline, ninjalog, args.exit_code, metadata = GetMetadata(args.cmdline, ninjalog, args.exit_code,
args.build_duration) args.build_duration, cfg.user)
exit_code = UploadNinjaLog(args.server, ninjalog, metadata) exit_code = UploadNinjaLog(args.server, ninjalog, metadata)
if exit_code == 0: if exit_code == 0:
last_upload_file.touch() last_upload_file.touch()

@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import json
import os import os
import sys import sys
import tempfile import tempfile
@ -17,33 +18,29 @@ import build_telemetry
class BuildTelemetryTest(unittest.TestCase): class BuildTelemetryTest(unittest.TestCase):
def test_is_googler(self): def test_check_auth(self):
with unittest.mock.patch('subprocess.run') as run_mock: with unittest.mock.patch('subprocess.run') as run_mock:
run_mock.return_value.returncode = 0 run_mock.return_value.returncode = 0
run_mock.return_value.stdout = 'Logged in as foo@google.com.\n' auth = {'email': 'bob@google.com'}
self.assertTrue(build_telemetry.is_googler()) run_mock.return_value.stdout = json.dumps(auth)
self.assertEqual(build_telemetry.check_auth(), auth)
with unittest.mock.patch('subprocess.run') as run_mock: with unittest.mock.patch('subprocess.run') as run_mock:
run_mock.return_value.returncode = 1 run_mock.return_value.returncode = 1
self.assertFalse(build_telemetry.is_googler()) self.assertEqual(build_telemetry.check_auth(), {})
with unittest.mock.patch('subprocess.run') as run_mock: with unittest.mock.patch('subprocess.run') as run_mock:
run_mock.return_value.returncode = 0 run_mock.return_value.returncode = 0
run_mock.return_value.stdout = '' run_mock.return_value.stdout = ''
self.assertFalse(build_telemetry.is_googler()) self.assertEqual(build_telemetry.check_auth(), {})
with unittest.mock.patch('subprocess.run') as run_mock:
run_mock.return_value.returncode = 0
run_mock.return_value.stdout = 'Logged in as foo@example.com.\n'
self.assertFalse(build_telemetry.is_googler())
def test_load_and_save_config(self): def test_load_and_save_config(self):
test_countdown = 2 test_countdown = 2
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
cfg_path = os.path.join(tmpdir, "build_telemetry.cfg") cfg_path = os.path.join(tmpdir, "build_telemetry.cfg")
with unittest.mock.patch( with unittest.mock.patch(
'build_telemetry.is_googler') as is_googler: 'build_telemetry.check_auth') as check_auth:
is_googler.return_value = True check_auth.return_value = {'email': 'bob@google.com'}
# Initial config load # Initial config load
cfg = build_telemetry.load_config(cfg_path, test_countdown) cfg = build_telemetry.load_config(cfg_path, test_countdown)
@ -61,9 +58,9 @@ class BuildTelemetryTest(unittest.TestCase):
self.assertEqual(cfg.countdown, test_countdown) self.assertEqual(cfg.countdown, test_countdown)
self.assertEqual(cfg.version, build_telemetry.VERSION) self.assertEqual(cfg.version, build_telemetry.VERSION)
# build_telemetry.is_googler() is an expensive call. # build_telemetry.check_auth() is an expensive call.
# The cached result should be reused. # The cached result should be reused.
is_googler.assert_called_once() check_auth.assert_called_once()
def test_enabled(self): def test_enabled(self):
test_countdown = 2 test_countdown = 2
@ -72,8 +69,8 @@ class BuildTelemetryTest(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
cfg_path = os.path.join(tmpdir, "build_telemetry.cfg") cfg_path = os.path.join(tmpdir, "build_telemetry.cfg")
with unittest.mock.patch( with unittest.mock.patch(
'build_telemetry.is_googler') as is_googler: 'build_telemetry.check_auth') as check_auth:
is_googler.return_value = True check_auth.return_value = {'email': 'bob@google.com'}
# Initial config load # Initial config load
cfg = build_telemetry.load_config(cfg_path, test_countdown) cfg = build_telemetry.load_config(cfg_path, test_countdown)
@ -115,8 +112,8 @@ class BuildTelemetryTest(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
cfg_path = os.path.join(tmpdir, "build_telemetry.cfg") cfg_path = os.path.join(tmpdir, "build_telemetry.cfg")
with unittest.mock.patch( with unittest.mock.patch(
'build_telemetry.is_googler') as is_googler: 'build_telemetry.check_auth') as check_auth:
is_googler.return_value = True check_auth.return_value = {'email': 'bob@google.com'}
# After opt-out, it should not display the notice and # After opt-out, it should not display the notice and
# change the countdown. # change the countdown.
cfg = build_telemetry.load_config(cfg_path, test_countdown) cfg = build_telemetry.load_config(cfg_path, test_countdown)
@ -143,8 +140,8 @@ class BuildTelemetryTest(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
cfg_path = os.path.join(tmpdir, "build_telemetry.cfg") cfg_path = os.path.join(tmpdir, "build_telemetry.cfg")
with unittest.mock.patch( with unittest.mock.patch(
'build_telemetry.is_googler') as is_googler: 'build_telemetry.check_auth') as check_auth:
is_googler.return_value = False check_auth.return_value = {'email': 'bob@example.com'}
cfg = build_telemetry.load_config(cfg_path) cfg = build_telemetry.load_config(cfg_path)
self.assertFalse(cfg.enabled()) self.assertFalse(cfg.enabled())

Loading…
Cancel
Save