Skip to content

Publish a metrics payload even when no design produced metrics - #4646

Merged
vvbandeira merged 4 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:upload-no-metrics-builds
Oct 21, 2026
Merged

vvbandeira merged 4 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:upload-no-metrics-builds

Conversation

@migueldalberto

Copy link
Copy Markdown
Contributor

Summary

flow/util/uploadMetadata.py used to skip the publish when no design produced a metadata.json. It only printed a warning, so those builds never reached the QoR dashboard. With this change it publishes the pipeline payload with "designs": [], so the dashboard can list the build and label it as having no metrics.

Contract

  • Empty builds are published. When design_records is empty, the pipeline payload (v2/v3/v4) goes out with "designs": [] through the normal publish_pipeline_report path. A failed publish still exits 1. INFO lines say that an empty (no-metrics) report is being published and that it was published.
  • New optional arguments:
    • --buildTime: sets root key build_time on every pipeline payload, empty or not. It defaults to datetime.now().strftime("%Y-%m-%d %H:%M"), the same format genMetrics.py uses for run__flow__generate_date.
    • --expectedDesigns N: sets root key design_count: N. palantir already reads this key.
    • --noMetricsReason REASON: sets root key no_metrics_reason, only when designs is empty and the value is non-blank (whitespace is trimmed).
  • No schema version bump. resolve_schema_version is unchanged. An invalid provenance file still drops v4 to v3, with or without designs.
  • v1 fallback messages are unchanged. dashboard reads every v1 root key it does not list in MetadataKeys as a metric, so new keys there would show up as bogus metrics. An empty build never takes the v1 path anyway, since its payload is far below the size cap.
  • The publisher init and the reports walk are unchanged.

uploadMetadata.py used to skip the publish when no design had a
metadata.json, so builds that generated no metrics never reached the QoR
dashboard. It now publishes the pipeline payload with an empty designs
list through the normal path, and a failed publish still exits 1.

Three optional arguments describe the build on the pipeline payload:
--buildTime (build_time, defaulting to now in genMetrics.py's format and
emitted on every pipeline payload), --expectedDesigns (design_count) and
--noMetricsReason (no_metrics_reason, only on an empty payload). v1
fallback messages are unchanged, since the backend reads their unknown
root keys as metrics.

Part of The-OpenROAD-Project-private/lembas#209.

Signed-off-by: Miguel Dalberto Pedro <miguel.pedro@precisioninno.com>
palantir reads build_time as UTC, but the default came from local time, so
a build published from a machine outside UTC was dated off by its offset.
A beta test from a UTC-3 machine showed the build three hours in the past.

Signed-off-by: Miguel Dalberto Pedro <miguel.pedro@precisioninno.com>
@migueldalberto migueldalberto self-assigned this Oct 7, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates uploadMetadata.py to allow publishing empty pipeline reports when no design records are collected, introducing new command-line arguments for --buildTime, --expectedDesigns, and --noMetricsReason. It also adds a comprehensive test suite to verify these changes. The review feedback suggests improving input validation by enforcing the correct format for --buildTime and ensuring --expectedDesigns is non-negative, as well as adding a warning if --noMetricsReason is provided alongside valid design records.

Comment thread flow/util/uploadMetadata.py
Comment thread flow/util/uploadMetadata.py
Comment thread flow/util/uploadMetadata.py Outdated
@openroad-ci

openroad-ci commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

🔍 QoR check

Metrics reflect the PR merge build — i.e. what will land on the target branch.

Commit debdb9a · Jenkins build #8 · Baseline: build · View build on dashboard

62 design(s) checked — 0 with regression(s), 0 without a comparable baseline.

@maliberty

Copy link
Copy Markdown
Member

Please address or resolve the gemini comments

Reject a --buildTime that does not match YYYY-MM-DD HH:MM and a negative
or non-integer --expectedDesigns at argument parsing, before anything is
published. A blank --buildTime still defaults to now in UTC. Warn when
--noMetricsReason is given but design records were collected, since the
reason is then dropped.

Signed-off-by: Miguel Dalberto Pedro <miguel.pedro@precisioninno.com>

@vvbandeira vvbandeira left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at ec5b59c. Approving; the comments below are non-blocking.

The empty payload matches what the backend accepts (build_time is always set), and the backend never uses an empty build as a baseline, so it cannot read as a passing run. Tests cover the empty case on v2/v3/v4 and a design_count larger than the designs collected.

  1. uploadMetadata.py:283: on the v1 fallback, --expectedDesigns is dropped silently, so an oversized build reports completeness as unknown. Leaving it off is right until the backend lists design_count as v1 metadata; a [WARN] line would make the drop visible.
  2. uploadMetadata.py:101-106: the backend expects a short code (e.g. no_reports_found) and drops reasons over 100 characters without an error. Suggest saying so in the help, and rejecting or warning on longer values.
  3. test_uploadMetadata.py: no test has a report directory without metadata.json next to one with it, or only skipped platforms. That is how a real partial or failed flow reaches the new empty publish.
  4. uploadMetadata.py:340-342: the v1 rationale is only true for design_count; the backend already treats build_time and no_metrics_reason as metadata on v1.
  5. uploadMetadata.py:44: --expectedDesigns 0 is accepted, but the backend ignores a count of 0.
  6. uploadMetadata.py:25-36: _build_time accepts "2026-1-5 1:3" and passes it through unpadded. Returning strptime(...).strftime(BUILD_TIME_FORMAT) would normalize it.
  7. uploadMetadata.py:452: a build with no records was a [WARN] and is now [INFO]. Keeping [WARN] for "no records collected" keeps it visible in log sweeps.
  8. uploadMetadata.py:289-293: nit, the ignored-reason warning could print at the call site instead of inside build_pipeline_payload.

Heads-up: #4574 conflicts in two places with this PR, so the second one to merge will need a rebase.

Normalize --buildTime to zero-padded fields, leave a zero --expectedDesigns
off the payload since it carries no completeness claim, and drop a
--noMetricsReason longer than 100 characters with a warning instead of
sending a value that would be discarded. Warnings about an ignored reason
now print at the call site, a build with no records logs at WARN again,
and the v1 fallback warns when it drops --expectedDesigns.

Correct the v1 fallback docstring: only design_count would be read as a
metric there. Add tests for report directories without metadata.json,
builds with only skipped platforms, and the v1 fallback warning.

Signed-off-by: Miguel Dalberto Pedro <miguel.pedro@precisioninno.com>
@migueldalberto

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I've addressed the eight points in a337ac6:

  1. v1 fallback drops --expectedDesigns. It's still left off the v1 messages, but the fallback now prints [WARN] --expectedDesigns is not sent on the v1 fallback; the backend will report this build's completeness as unknown. A test pushes a payload over the 8 MB cap and checks for the warning.
  2. Reason length. The help text now asks for a short code such as no_reports_found, at most 100 characters. A longer reason is dropped with a warning rather than rejected, so a long reason can't fail an otherwise good upload. The tests cover exactly 100 characters (kept) and 101 (dropped, with the warning).
  3. Partial and failed flows. There are three new tests:
    • a report directory without metadata.json next to one that has it, which publishes only the good design and keeps design_count;
    • a flow where no directory has metadata.json, which publishes an empty report with the reason;
    • a build with only skipped platforms, which publishes an empty report with the WARN line.
  4. v1 docstring. Fixed. It now says only design_count would be read as a metric. build_time and no_metrics_reason are metadata on v1 but aren't needed there: each design carries run__flow__generate_date, and a reason only applies to an empty build, which never hits the size cap.
  5. --expectedDesigns 0. It's still accepted but no longer sent, since it carries no completeness claim. The help text says so.
  6. Unpadded --buildTime. It now returns strptime(...).strftime(BUILD_TIME_FORMAT), so 2026-1-5 1:3 is sent as 2026-01-05 01:03.
  7. Log level. "No design records were collected" is back to [WARN].
  8. Ignored-reason warning. Moved to the call site. A new resolve_no_metrics_reason decides whether the reason is sent, and build_pipeline_payload just takes the result.

@vvbandeira
vvbandeira merged commit 222f133 into The-OpenROAD-Project:master Oct 21, 2026
12 of 13 checks passed
@vvbandeira
vvbandeira deleted the upload-no-metrics-builds branch October 21, 2026 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants