Skip to content

compare: scope PR-comment upsert per (deployment, triggering_env)#545

Merged
kei-nan merged 1 commit into
redis-performance:masterfrom
kei-nan:fix/per-deployment-pr-comment-upsert
Jun 1, 2026
Merged

compare: scope PR-comment upsert per (deployment, triggering_env)#545
kei-nan merged 1 commit into
redis-performance:masterfrom
kei-nan:fix/per-deployment-pr-comment-upsert

Conversation

@kei-nan
Copy link
Copy Markdown
Collaborator

@kei-nan kei-nan commented Jun 1, 2026

Summary

check_regression_comment matches on the literal substrings "Comparison between" and "Time Period from" — strings that appear in every regression-table comment regardless of which deployment or triggering env produced it. So when several matrix entries (e.g. oss-standalone + oss-cluster-02-primaries, or msmarco + ftsb) each run compare --pull-request N against the same PR, the second invocation finds the first's comment via that generic predicate and calls regression_comment.edit(comment_body) (compare.py:876), silently overwriting the previous setup's results. Net effect on the PR: only whichever setup finishes last is visible.

This PR scopes the upsert per (deployment, triggering_env) tuple so each setup gets its own comment.

Changes

  • New helper build_upsert_marker(baseline_deployment_name, comparison_deployment_name, tf_triggering_env) returns a stable hidden HTML comment string, e.g.

    <!-- redisbench-admin:upsert baseline_deployment=oss-standalone-threads-8 comparison_deployment=oss-standalone-threads-8 triggering_env=circleci -->
    

    Architecture is intentionally not part of the key — in multi-arch mode a single comment renders one H2 section per arch and we want it to converge to a single upsertable comment as each arch finishes.

  • check_regression_comment(comments, marker=None) now filters on the marker when provided. When no comment carries the marker the function returns (False, -1) so the caller posts a fresh comment; any pre-fix legacy comment is left in place as a one-time orphan rather than overwritten with a body for a different setup. When marker=None the legacy generic predicate is preserved, so out-of-tree callers that don't yet pass a marker keep their existing behavior.

  • compare_command_logic computes the marker once right after baseline_deployment_name/comparison_deployment_name are resolved (already done at compare.py:364-371), threads it into the existing matcher call, and appends it to comment_body before posting when is_actionable_pr is true. The same marker is added on both create and edit paths so the equality short-circuit at the diff comparison (the comment_body == old_regression_comment_body check) continues to work — the previously-posted body already contains the marker.

Backward compatibility

  • Out-of-tree callers of check_regression_comment(comments) (no marker= kwarg) hit the legacy generic predicate — unchanged.
  • PRs with a pre-fix orphan comment from an older redisbench-admin will gain one fresh marker-tagged comment alongside the orphan the first time the new code runs. From that point on, repeat runs of the same (deployment, triggering_env) find their marker and update in place.
  • Multi-arch single-deployment workflows are unaffected: same marker on each matrix entry → single comment, upsert preserved.

Test plan

  • python -m pytest tests/test_compare.py tests/test_compare_validation.py → 20 passed, 9 skipped (the 9 skipped are RTS-dependent integration tests; the 8 new unit tests are pure and all pass).
  • black --check redisbench_admin clean.
  • python -m flake8 redisbench_admin clean.
  • Smoke import: from redisbench_admin.compare.compare import compare_command_logic, build_upsert_marker, check_regression_comment succeeds.

New unit tests cover:

  • Marker determinism + HTML-hidden shape.
  • Distinctness by deployment and by triggering_env.
  • Prefix-collision safety (oss-standalone is not a substring of oss-standalone-threads-8's marker, even though their deployment names share a prefix).
  • Legacy-predicate fallback when marker=None.
  • (False, -1) returned when no comment carries the marker.
  • Legacy pre-fix comments are NOT matched when a marker is provided (so we don't overwrite them with a body for a different setup).
  • Last match wins on duplicates (mirrors legacy keep-last semantics).

Context

Discovered while debugging missing benchmark comments on redislabsdev/RediSearchEnterprise#462 — fixing the deployment-name filter there exposed this upsert-collision as the next layer of the same problem.

`check_regression_comment` matched on the literal substrings
"Comparison between" and "Time Period from" -- present in every
regression-table comment regardless of which deployment or triggering
env produced it. So when several matrix entries (e.g. oss-standalone +
oss-cluster-02-primaries, or msmarco + ftsb) run `compare
--pull-request N` against the same PR, the second one finds the first's
comment via that generic predicate and `edit`s it in place, silently
overwriting the previous setup's results. Net effect: only whichever
setup finishes last is visible on the PR.

- Add `build_upsert_marker(baseline_deployment, comparison_deployment,
  triggering_env)` returning a stable hidden HTML comment string. The
  marker excludes architecture so multi-arch sections of one comment
  still converge to a single upsertable comment as each arch finishes.
- Extend `check_regression_comment(comments, marker=None)` to filter on
  the marker when provided. When no comment carries the marker we
  return (False, -1) so the caller posts a fresh comment; any pre-fix
  legacy comment on the PR is left in place as a one-time orphan
  rather than overwritten with a body for a different setup. With
  `marker=None` the legacy generic predicate is preserved for callers
  that don't (yet) compute a marker.
- In `compare_command_logic`, compute the marker once right after the
  deployment names are resolved, thread it into the existing matcher
  call, and append it to `comment_body` before the upsert when
  `is_actionable_pr` is true. The same marker is added on both create
  and edit paths so the equality short-circuit at the diff comparison
  continues to work (the existing comment's stored body already
  contains the marker).
- Tests cover: marker determinism, distinctness by deployment +
  triggering_env, prefix-collision safety (oss-standalone vs
  oss-standalone-threads-8), legacy-predicate fallback when no marker
  is passed, no-match returns (False, -1), legacy comments ignored
  when a marker is provided, last-match wins on duplicates.

Refs: discussion on RediSearchEnterprise#462
@fcostaoliveira fcostaoliveira self-requested a review June 1, 2026 10:56
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 1, 2026

Codecov Report

❌ Patch coverage is 86.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.67%. Comparing base (241dbec) to head (7c15afc).

Files with missing lines Patch % Lines
redisbench_admin/compare/compare.py 86.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #545      +/-   ##
==========================================
+ Coverage   47.50%   47.67%   +0.17%     
==========================================
  Files          74       74              
  Lines        8907     8917      +10     
==========================================
+ Hits         4231     4251      +20     
+ Misses       4676     4666      -10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JoanFM
Copy link
Copy Markdown
Contributor

JoanFM commented Jun 1, 2026

@kei-nan if u bump the version in pyproject, we can merge and inmediately do a release so it would be seen

@kei-nan
Copy link
Copy Markdown
Collaborator Author

kei-nan commented Jun 1, 2026

@kei-nan if u bump the version in pyproject, we can merge and inmediately do a release so it would be seen

I don't have permissions in this project, can't even press the merge button.
It would have to come from @fcostaoliveira

@JoanFM
Copy link
Copy Markdown
Contributor

JoanFM commented Jun 1, 2026

@kei-nan if u bump the version in pyproject, we can merge and inmediately do a release so it would be seen

I don't have permissions in this project, can't even press the merge button. It would have to come from @fcostaoliveira

I mean, in the PR change the version in pyproject. Then I will be able to merge and release a version

@kei-nan kei-nan merged commit 68afaf8 into redis-performance:master Jun 1, 2026
8 checks passed
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.

3 participants