[libcxx] [llvm] [libc++] Report the runs created by dispatch-benchmarks (PR #216029)
Louis Dionne via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 13 05:31:31 PDT 2026
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/216029
Also, axe the jsonl output which was not used by anything in the pipeline and simply created confusion.
Fixes #215924
>From 0fbf45ac66e6939fa2214b8850defe3ceab91e15 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 13 Aug 2026 07:51:34 -0400
Subject: [PATCH] [libc++] Report the runs created by dispatch-benchmarks
Also, axe the jsonl output which was not used by anything in the pipeline
and simply created confusion.
Fixes #215924
---
.github/workflows/libcxx-benchmark-cron.yml | 3 +-
libcxx/utils/ci/lnt/dispatch-benchmarks | 52 +++++++++------------
2 files changed, 23 insertions(+), 32 deletions(-)
diff --git a/.github/workflows/libcxx-benchmark-cron.yml b/.github/workflows/libcxx-benchmark-cron.yml
index 1bc224eb7fc74..9162aa4ace138 100644
--- a/.github/workflows/libcxx-benchmark-cron.yml
+++ b/.github/workflows/libcxx-benchmark-cron.yml
@@ -133,5 +133,4 @@ jobs:
fi
libcxx/utils/ci/lnt/dispatch-benchmarks --work-items plan.jsonl --lnt-url "${LNT_URL}" \
- --max-in-flight "${MAX_IN_FLIGHT}" \
- --output dispatched.jsonl "${dry_run[@]}"
+ --max-in-flight "${MAX_IN_FLIGHT}" "${dry_run[@]}"
diff --git a/libcxx/utils/ci/lnt/dispatch-benchmarks b/libcxx/utils/ci/lnt/dispatch-benchmarks
index b022008799ad4..a7a51c6bf26e0 100755
--- a/libcxx/utils/ci/lnt/dispatch-benchmarks
+++ b/libcxx/utils/ci/lnt/dispatch-benchmarks
@@ -11,10 +11,8 @@ from typing import Dict, List, NamedTuple, Optional, Sequence, Set, TextIO
import argparse
import common
import github
-import json
import logging
import os
-import pathlib
import re
import sys
import tabulate
@@ -52,9 +50,11 @@ class Runs(NamedTuple):
return sum(n for (target, n) in self.in_flight.items() if target.machine == machine)
-# The repository and the workflow this tool drives.
+# The repository and the workflow driven by this tool, and the ref to use for the
+# definition of the workflow.
REPOSITORY = 'llvm/llvm-project'
WORKFLOW = 'libcxx-benchmark-commit.yml'
+WORKFLOW_REF = 'main'
# The name the benchmark workflow gives its runs. What a run is benchmarking can
# only be recovered from its name (the inputs a workflow was dispatched with are
@@ -163,21 +163,25 @@ def workflow_runs(workflow: github.Workflow.Workflow) -> List[WorkflowRun]:
return list(runs.values())
-def dispatch(workflow: github.Workflow.Workflow, inputs: Dict[str, str]) -> None:
+def dispatch(workflow: github.Workflow.Workflow, inputs: Dict[str, str]) -> str:
"""
- Request one run of a workflow.
+ Request one run of a workflow and return the URL of the run that was created.
- The definition on `main` is always the one that runs, whatever commit is being
+ The definition on WORKFLOW_REF is always the one that runs, whatever commit is being
benchmarked.
"""
logging.debug(f'dispatching {workflow.path} with {inputs}')
try:
- # A refused dispatch is reported by returning False rather than by raising, and
- # the refusal reason is not surfaced. The request is all we can report.
- if not workflow.create_dispatch(ref='main', inputs=inputs):
- raise GithubError(f'the API refused to dispatch a run for {inputs["commit"]} on {inputs["lnt-machine"]}')
+ # Don't go through PyGithub's create_dispatch() since it doesn't support return_run_details
+ # until https://github.com/PyGithub/PyGithub/issues/3474 is fixed.
+ (_, details) = workflow.requester.requestJsonAndCheck(
+ 'POST', f'{workflow.url}/dispatches',
+ input={'ref': WORKFLOW_REF, 'inputs': inputs, 'return_run_details': True})
except github.GithubException as error:
raise GithubError(f'could not dispatch a run for {inputs["commit"]} on {inputs["lnt-machine"]}: {error}')
+ if not isinstance(details, dict) or not details.get('html_url'):
+ raise GithubError(f'failed to dispatch a workflow run for {inputs["commit"]} on {inputs["lnt-machine"]}: {details}')
+ return details['html_url']
def summarize(runs: Sequence[WorkflowRun]) -> Runs:
@@ -344,9 +348,6 @@ def main(argv: List[str]) -> int:
'variable. `gh auth token` can be used to print the token registered locally.')
parser.add_argument('--dry-run', action='store_true',
help='Do not request anything, just report what would be requested.')
- parser.add_argument('--output', type=pathlib.Path, default=None,
- help='Where to write the record of what was requested, one JSON object per line. Defaults '
- 'to standard output.')
parser.add_argument('-q', '--quiet', action='store_true',
help='Do not print the human-readable summary to standard error.')
parser.add_argument('-v', '--verbose', action='count', default=0,
@@ -378,9 +379,7 @@ def main(argv: List[str]) -> int:
if not args.quiet:
report(args, decisions, runs)
- # Requests are made one at a time and recorded as they succeed. A failure halfway through must still
- # leave an accurate record, since the runs already requested actually exist in Github.
- records: List[str] = []
+ # Requests are made one at a time and reported as they succeed.
dispatched = 0
try:
for decision in decisions:
@@ -389,24 +388,17 @@ def main(argv: List[str]) -> int:
inputs = workflow_inputs(args, decision.item)
for _ in range(decision.jobs):
if not args.dry_run:
- dispatch(workflow, inputs)
+ url = dispatch(workflow, inputs)
+ if not args.quiet:
+ # Print heading with the first run to avoid clutter in the "nothing dispatched" case.
+ if dispatched == 0:
+ print('', file=sys.stderr)
+ print('Requested runs:', file=sys.stderr)
+ print(f' {decision.item.commit[:12]} on {decision.item.machine}: {url}', file=sys.stderr)
dispatched += 1
- records.append(json.dumps({'commit': decision.item.commit,
- 'machine': decision.item.machine,
- 'reason': decision.item.reason,
- 'dry_run': args.dry_run,
- 'inputs': inputs}, sort_keys=True) + '\n')
except GithubError:
logging.error(f'requested {dispatched} runs before failing')
raise
- finally:
- # Write what we managed to do even when we fail: those runs exist and will
- # consume machine time, so we want to report them.
- contents = ''.join(records)
- if args.output is None:
- sys.stdout.write(contents)
- else:
- args.output.write_text(contents)
if not args.quiet and not args.dry_run:
print(f'Requested {dispatched} runs.', file=sys.stderr)
More information about the llvm-commits
mailing list