|
11 | 11 | from sp_cli.compare import compare_runs, coverage_warnings |
12 | 12 | from sp_cli.constants import (ARTIFACT_TYPES, CANCEL_REASON_MIN_LENGTH, |
13 | 13 | COMMIT_SHA_LENGTH, ERROR_GROUP_BY, |
14 | | - ERROR_SEVERITIES, ERROR_TYPES, INFRA_ERROR_TYPES, |
15 | | - LOG_CONTAINS_MAX_LENGTH, LOG_LEVELS, LOG_SOURCES, |
16 | | - MAX_OFFSET, MAX_PAGE_LIMIT, |
17 | | - MAX_REGRESSION_TEST_IDS, PLATFORMS, |
18 | | - PR_SCAN_DEFAULT, PR_SCAN_MAX, |
| 14 | + ERROR_SEVERITIES, ERROR_TYPES, EXIT_TIMEOUT, |
| 15 | + INFRA_ERROR_TYPES, LOG_CONTAINS_MAX_LENGTH, |
| 16 | + LOG_LEVELS, LOG_SOURCES, MAX_OFFSET, |
| 17 | + MAX_PAGE_LIMIT, MAX_REGRESSION_TEST_IDS, |
| 18 | + PLATFORMS, PR_SCAN_DEFAULT, PR_SCAN_MAX, |
19 | 19 | RUN_PENDING_STATUSES, RUN_STATUSES, |
20 | 20 | RUN_UNSUCCESSFUL_STATUSES, SAMPLE_STATUSES, |
21 | 21 | WAIT_INTERVAL_DEFAULT, WAIT_INTERVAL_MAX, |
@@ -777,8 +777,13 @@ def run_wait(ctx: click.Context, run_ids: Tuple[int, ...], interval: int, |
777 | 777 | stays pipeable. |
778 | 778 |
|
779 | 779 | Exits 0 only if every run finished successfully; a failed or canceled run |
780 | | - exits 1 and a timeout exits 2, which lets a script gate on the result |
| 780 | + exits 1 and a timeout exits 9, which lets a script gate on the result |
781 | 781 | without parsing the output. |
| 782 | +
|
| 783 | + A run whose status is `pass` exits 0 even if it recorded results for only a |
| 784 | + fraction of its samples, because the API derives that status from the rows |
| 785 | + that exist rather than from the ones expected. Check `sp run summary`'s |
| 786 | + skipped_count before treating a green wait as full coverage. |
782 | 787 | """ |
783 | 788 | client = ctx.obj['client'] |
784 | 789 | output = ctx.obj['output'] |
@@ -806,7 +811,7 @@ def run_wait(ctx: click.Context, run_ids: Tuple[int, ...], interval: int, |
806 | 811 | click.echo(f'timed out after {timeout}s; still pending: ' |
807 | 812 | f'{", ".join(str(r) for r in pending)}', err=True) |
808 | 813 | _render_wait(ctx, run_ids, finished, output) |
809 | | - raise SystemExit(2) |
| 814 | + raise SystemExit(EXIT_TIMEOUT) |
810 | 815 | if not quiet: |
811 | 816 | click.echo(f'waiting on {", ".join(str(r) for r in pending)} ' |
812 | 817 | f'({interval}s)', err=True) |
@@ -834,5 +839,7 @@ def _render_wait(ctx: click.Context, run_ids: Tuple[int, ...], |
834 | 839 | :type output: str |
835 | 840 | """ |
836 | 841 | rows = [finished[run_id] for run_id in dict.fromkeys(run_ids) if run_id in finished] |
837 | | - payload: Any = rows[0] if len(rows) == 1 else {'data': rows} |
838 | | - render(payload, output, ctx.obj.get('color', False)) |
| 842 | + # Always a collection, even for one run. The shape must not depend on how |
| 843 | + # many ids the caller passed, or `sp run wait $IDS | jq '.data[]'` works |
| 844 | + # until the list happens to contain a single run. |
| 845 | + render({'data': rows, 'total': len(rows)}, output, ctx.obj.get('color', False)) |
0 commit comments