Skip to content

Commit 9332f3b

Browse files
committed
ci: retain JSON CLI failures for vlt transport retries
1 parent b06c36c commit 9332f3b

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

‎scripts/backtest-vlt.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -992,13 +992,20 @@ def __init__(self, ctx, version, mode, shape_name):
992992
self.record = ctx['record']
993993
self.envelopes = []
994994
self.fresh_patched = {}
995+
self.cli_failures = []
995996

996997
# CLI -------------------------------------------------------------------
997998
def cli(self, args, cwd=None):
998999
command = [self.ctx['cli'], *args, '--json', '--no-telemetry']
9991000
if self.ctx.get('patch_server_url'):
10001001
command += ['--patch-server-url', self.ctx['patch_server_url']]
1001-
return run(command, cwd or self.project, self.ctx['cli_env'], self.log)
1002+
code, out, err = run(command, cwd or self.project, self.ctx['cli_env'], self.log)
1003+
if code:
1004+
# --json errors go to stdout, including on repeat/revert calls.
1005+
# Keep them on the result row so the transport retry sees them.
1006+
self.cli_failures.append(dict(command=str(args[0]), exitCode=code,
1007+
envelope=parse_envelope(out), stderr=tail(err, 3000)))
1008+
return code, out, err
10021009

10031010
def patch_run(self, mode, cwd=None):
10041011
cwd = cwd or self.project
@@ -1195,6 +1202,8 @@ def blocked_refusal(self, row, envelopes, reference):
11951202
return clean
11961203

11971204
def finish(self, row, checks, started):
1205+
if self.cli_failures:
1206+
row['cliFailures'] = self.cli_failures
11981207
row['failingChecks'] = [k for k, v in checks.items() if v is False]
11991208
row['notEvaluated'] = [k for k, v in checks.items() if v is None]
12001209
row.setdefault('codes', [])

‎scripts/tests/test_backtest_harnesses.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,29 @@ def test_snapshot_never_follows_a_link(self):
608608

609609

610610
class VltRetryTests(unittest.TestCase):
611+
def test_json_cli_failures_reach_the_retry_classifier(self):
612+
for phase in ('initial', 'repeat', 'rollback'):
613+
for status in (504, 404):
614+
with self.subTest(phase=phase, status=status), tempfile.TemporaryDirectory() as temp:
615+
cell = vlt.Cell({'out': Path(temp), 'record': {}, 'cli': 'socket-patch',
616+
'cli_env': {}}, '1.2.0', 'hosted', 'direct')
617+
cell.project.mkdir(parents=True)
618+
row = dict(cell=cell.name, expectedVerdict='patched', passed=False, checks={})
619+
envelope = {'status': 'error',
620+
'error': f'API request failed with status {status}: error code: {status}'}
621+
with patch.object(vlt, 'run', return_value=(1, json.dumps(envelope), '')):
622+
if phase == 'initial':
623+
cell.patch_run('hosted')
624+
elif phase == 'repeat':
625+
cell.repeat(row, row['checks'], b'')
626+
else:
627+
cell.revert()
628+
with patch('sys.stdout'):
629+
cell.finish(row, row['checks'], vlt.time.time())
630+
captured = json.loads((cell.case / 'result.json').read_text())
631+
self.assertEqual(captured['cliFailures'][0]['envelope'], envelope)
632+
self.assertEqual(vlt.transient(captured), status == 504)
633+
611634
def test_only_transport_failures_retry(self):
612635
self.assertFalse(vlt.transient({'matchesExpectation': True, 'serveProbe': {'curlExit': 7}}))
613636
self.assertTrue(vlt.transient({'serveProbe': {'curlExit': 7}}))

0 commit comments

Comments
 (0)