Skip to content

Add on-demand parameterized benchmark workflow for PRs#3433

Merged
zuiderkwast merged 4 commits into
valkey-io:unstablefrom
roshkhatri:on-demand-benchmark
May 26, 2026
Merged

Add on-demand parameterized benchmark workflow for PRs#3433
zuiderkwast merged 4 commits into
valkey-io:unstablefrom
roshkhatri:on-demand-benchmark

Conversation

@roshkhatri

@roshkhatri roshkhatri commented Apr 1, 2026

Copy link
Copy Markdown
Member

Description

Add a new workflow_dispatch triggered workflow (benchmark-on-demand.yml) that enables admin-triggered, parameterized benchmarking on any open PR.

Implements: valkey-io/valkey-perf-benchmark#52

Problem

  • Current automated benchmarks (via run-benchmark / run-cluster-benchmark labels) only run a fixed SET/GET workload
  • PRs targeting other command types cannot be benchmarked automatically
  • No way to customize benchmark parameters per PR

Solution

A new workflow with configurable inputs:

Input Description Default
pr_number PR number to benchmark (required)
commands Comma-separated commands (e.g. SET,GET,HSET,LPUSH) SET,GET
data_size Comma-separated data sizes in bytes (e.g. 16,96) 16,96 (from config)
io_threads Comma-separated io-threads values (e.g. 1,9) 1,9 (from config)
pipelines Comma-separated pipeline values (e.g. 1,10) 1,10 (from config)
cluster_mode Enable cluster mode false

Other defaults from config: duration=180, warmup=30, clients=1600, benchmark-threads=90, keyspacelen=3000000, runs=3.

When io_threads is overridden, server_cpu_range is automatically adjusted to match.

Multiple workflow runs can be queued for the same PR with different configs (no concurrency group).

How it works

  1. resolve-pr job fetches the PR merge commit SHA, head SHA, and base ref
  2. benchmark job builds latest valkey-benchmark from unstable, overrides the ARM benchmark config with user-provided parameters, and runs benchmark.py comparing the PR commit against its base branch
  3. Results are posted as a PR comment with commit link, commands tested, and workflow run link

Testing

On-Demand Benchmark ran on commit: 9fa74f0
Commands: SET
Runs: 3 | Workflow Run

RPS Benchmark Comparison: unstable vs d798669

No significant changes

No statistically significant changes detected across 1 test(s).

@roshkhatri roshkhatri force-pushed the on-demand-benchmark branch from 75691eb to 6fe33f5 Compare April 1, 2026 20:38
@roshkhatri roshkhatri marked this pull request as ready for review April 1, 2026 20:39
@roshkhatri roshkhatri requested review from hpatro and zuiderkwast April 1, 2026 20:41
@codecov

codecov Bot commented Apr 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.70%. Comparing base (d9ba5ab) to head (7500b29).
⚠️ Report is 2 commits behind head on unstable.

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #3433      +/-   ##
============================================
- Coverage     76.77%   76.70%   -0.07%     
============================================
  Files           162      162              
  Lines         80706    80706              
============================================
- Hits          61962    61909      -53     
- Misses        18744    18797      +53     

see 20 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rainsupreme

Copy link
Copy Markdown
Contributor

Will this work for set and zset commands like sadd and zadd? Were you able to test this with other data types?

@rainsupreme rainsupreme 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.

tbh I'm not a fan of having so much code embedded in the workflow instead of separate script files, but perhaps this is fine for a MVP.

@Nikhil-Manglore Nikhil-Manglore 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.

LGTM

@roshkhatri

Copy link
Copy Markdown
Member Author

@rainsupreme

Will this work for set and zset commands like sadd and zadd? Were you able to test this with other data types?

Yes it will work, we have tests for this on valkey-perf-benchmark repo

tbh I'm not a fan of having so much code embedded in the workflow instead of separate script files, but perhaps this is fine for a MVP.

These are the scripts to get the merge commit hash from the PR as this WF does not run with the PR context. I dont think we will be re-using these. If we do, we can make them into utils script later

@hpatro hpatro 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.

Few questions:

  1. What's the queue it goes into ? Does it hit any limit (max queue size) ?
  2. Could we also print out the other configs which a user might have overriden?
  3. Is this workflow limited to maintainers? How will other maintainers discover this capability?

Comment on lines +11 to +14
description: "Comma-separated commands to benchmark (e.g. SET,GET,HSET,LPUSH)"
required: false
type: string
default: "SET,GET"

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.

Is this same as -t of valkey-benchmark ? I would prefer flexibility in the parameters to the valkey-benchmark underneath. Could I just feed the parameters of valkey-benchmark as is ? I would be able to control the data size / keyspace length / pipeline / etc ?

@rainsupreme would like to hear your thoughts on this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is kept limited to the -t option of valkey-benchmarks. Righ now I have added only commands, cluster_mode, pipelines, io_threads, and data_size as parameters, but we can add more.

To keep the benchmark running for limited time keyspace length is contant at 3M and we are benchmarking for a constant time.

I will add a parameter to add custom configs to valkey server, if that what we are looking for.

@zuiderkwast zuiderkwast Apr 10, 2026

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.

If it's equivalent to -t then we should perhaps call it "predefined commands" in the description, not just commands.

If we can give custom commands to valkey-benchmark, for example valkey-benchmark SET __rand_1st__ __rand_2nd__ ';' GET __rand_1st__ (set a key and then get the same key afterwards) it would be very powerful.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Hey @zuiderkwast , it would need changes in the valkey-perf-benchmark package. Lets get this merged, I will add that feature and open another PR for that change

@roshkhatri

Copy link
Copy Markdown
Member Author

What's the queue it goes into ? Does it hit any limit (max queue size) ?

This goes into the runner queues, it does not have a specified limit, but one workflow can be queued for mac of 24 hours. Our benchmarks take 5 - 5.5 hrs to run. so approx depending on the current workflow in progress, we can have 5-6 workflows in the queue. If we care going over this queue size, we can add more runners for benchmarking

Could we also print out the other configs which a user might have overriden?

Yes, I can do that

Is this workflow limited to maintainers? How will other maintainers discover this capability?
Yes, this is only limited to people with write access to the repository. We can demo this in one of the monday meetings and also add it to the readme. Can you suggest some more ways to bring visibility to the maintainers?

Screenshot 2026-04-03 at 5 17 57 PM

@sarthakaggarwal97 sarthakaggarwal97 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.

Are there limits to data sizes and other parameters? I want to confirm if excessive load can be generated by increasing the datasize to an extremely high value. Ideally we should upper / lower bound the accepted values

@roshkhatri roshkhatri force-pushed the on-demand-benchmark branch from 52e2f56 to 69b1fe8 Compare April 6, 2026 22:27
@roshkhatri

Copy link
Copy Markdown
Member Author

Addressed the review feedback in 69b1fe8:

Input validation bounds (@sarthakaggarwal97):

  • data_size: 1 – 1,048,576 bytes (1 MB max). valkey-benchmark allows up to 1 GB but 1 MB is a reasonable cap for CI benchmarks.
  • io_threads: 1 – 20. The benchmark instance has cores 0-19 available on the NUMA node for valkey.
  • pipelines: 1 – 1,000.

The workflow now fails early with a clear error if any value is out of bounds.

Display overridden configs in PR comment (@hpatro):
The PR comment now shows which parameters were overridden from defaults. Example:

On-Demand Benchmark ran on commit: abc1234
Commands: SET,GET
Data Size: 16,96 | IO Threads: 1,9 | Pipelines: 1,10
Runs: 3 | Workflow Run

Only non-default overrides are displayed.

server_cpu_range safety cap:
server_cpu_range is now capped to 0-19 even if io_threads is set to 20, matching the available NUMA node CPUs on the benchmark instance.

@sarthakaggarwal97 sarthakaggarwal97 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.

Thanks! LGTM!

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new GitHub Actions workflow for on-demand PR benchmarking that resolves a PR, sets up a build environment on an ARM64 runner, generates parameterized benchmark configurations, executes comparative benchmarks, and reports results via artifact uploads and PR comments.

Changes

On-Demand PR Benchmark Workflow

Layer / File(s) Summary
Workflow dispatch setup and PR resolution
.github/workflows/benchmark-on-demand.yml
Defines manual workflow_dispatch inputs for PR number and benchmark parameters (commands, data sizes, IO threads, pipelines, cluster mode). Establishes minimal workflow-level permissions and implements a gated resolve-pr job that fetches PR metadata from the GitHub REST API, validates PR openness and merge commit availability, and exports merge/head SHA and base reference as outputs.
Benchmark environment and build
.github/workflows/benchmark-on-demand.yml
Checks out the target PR at its merge commit, fetches valkey-perf-benchmark and valkey unstable branch. Installs Python 3.10, build dependencies, and Python requirements. Builds the valkey-benchmark executable from the latest reference and exports its path for downstream use.
Benchmark configuration generation
.github/workflows/benchmark-on-demand.yml
Parses dispatch inputs and validates numeric bounds for data size (1–128), IO threads (1–256), and pipelines (1–16). Transforms the commands string into a JSON array, derives server_cpu_range from maximum IO threads, and uses jq to conditionally apply overrides for cluster_mode, data_sizes, io-threads, and pipelines into the benchmark config.
Benchmark execution and comparison
.github/workflows/benchmark-on-demand.yml
Runs benchmark.py with the generated config, PR-derived commit references, built benchmark path, target IP from secrets, and fixed --runs 3. Compares baseline vs. new metrics.json using compare_benchmark_results.py to produce a comparison.md report.
Results reporting and cleanup
.github/workflows/benchmark-on-demand.yml
Uploads benchmark result directories and comparison.md as artifacts with tolerant failure behavior. Posts a PR comment via actions/github-script containing the commit link, requested commands, overridden parameters, runs count, and workflow run URL. Deletes local outputs and terminates any running valkey processes via pkill with explicit handling for the no-process exit code.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • valkey-io/valkey#3753: Updates ARM and x86 benchmark data_sizes configuration bounds (from 96 to 128), which aligns with the numeric bounds validation logic in this workflow's config generation.

Suggested reviewers

  • sarthakaggarwal97
  • madolson
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.07% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a new on-demand, parameterized benchmark workflow for pull requests.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the problem, solution, implementation details, and testing results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/benchmark-on-demand.yml:
- Around line 40-43: The workflow currently grants pull-requests: write and
issues: write at the top-level permissions; restrict them by leaving only
minimal workflow-level permission (e.g., contents: read) and move job-specific
permissions into the relevant jobs: add issues: write (and pull-requests:
read/write if needed) to the "benchmark" job so it can call
github.rest.issues.createComment, and add pull-requests: read to the
"resolve-pr" job so it can call github.rest.pulls.get; ensure job names
"benchmark" and "resolve-pr" are used to locate where to add these scoped
permissions.
- Around line 145-149: The workflow inlines github.event.inputs directly into
Bash/JS variables (COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES, CLUSTER_MODE and
the JS vars commands/cluster/dataSize/ioThreads/pipelines/issue_number), which
is vulnerable to quote-injection; instead, move all user inputs into the job env
using toJson(...) (e.g. env: COMMANDS: ${{ toJson(github.event.inputs.commands)
}}), then parse them safely inside the Bash step (with jq or shell parsing from
the environment) and in github-script/Node by JSON.parse(process.env.COMMANDS)
or equivalent; update the steps that reference
COMMANDS/DATA_SIZE/IO_THREADS/PIPELINES/CLUSTER_MODE and the github-script
inputs to read from the parsed env variables rather than interpolating
github.event.inputs directly.
- Around line 71-73: The workflow assumes pr.data.merge_commit_sha is always
present but GitHub can return null for open PRs; add a guard after retrieving
pr.data: if merge_commit_sha is null/undefined, call core.setFailed with a clear
message (e.g. "merge_commit_sha unavailable; cannot checkout PR merge commit")
and exit/return to fail early instead of proceeding to setOutput and later using
the merge_commit_sha for the checkout; keep setting head_sha and base_ref as
before only after confirming merge_commit_sha exists so the checkout ref at line
85 won't later fail unexpectedly.
- Line 78: The workflow's timeout-minutes is set to 7200 which is far higher
than the benchmark's expected runtime (duration: 180s, warmup: 30s, and
invocation uses --runs 3); change the timeout-minutes value to a much tighter
bound (e.g., 60) to prevent stuck jobs from locking self-hosted runners—update
the timeout-minutes key in the workflow file accordingly while keeping the
existing benchmark duration/warmup and --runs settings intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 336de460-5fe2-4db1-b2ca-ca445d13e669

📥 Commits

Reviewing files that changed from the base of the PR and between 2585f60 and 5f75834.

📒 Files selected for processing (1)
  • .github/workflows/benchmark-on-demand.yml

Comment thread .github/workflows/benchmark-on-demand.yml Outdated
Comment thread .github/workflows/benchmark-on-demand.yml
Comment thread .github/workflows/benchmark-on-demand.yml Outdated
Comment thread .github/workflows/benchmark-on-demand.yml Outdated

@zuiderkwast zuiderkwast 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.

It's a good start! I suppose we can merge it now and extend it later.

@roshkhatri roshkhatri force-pushed the on-demand-benchmark branch from 5f75834 to a382095 Compare May 26, 2026 17:53

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
deps/linenoise/linenoise.c (1)

970-997: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Ensure CSI buffer is always NUL-terminated and only consume bytes when read() returns 1

In deps/linenoise/linenoise.c (CSI parsing block around lines 970-997):

  • The loop condition read(l.ifd, &additionalChar, 1) != -1 still enters on read()==0 (EOF) and appends an undefined additionalChar.
  • seqBuffer is only NUL-terminated when a final byte is detected; if the loop exits via length limit/EOF/error, the subsequent strcmp(seqBuffer, ...) can read past the valid bytes.
🛠️ Proposed fix
-                    char seqBuffer[SEQ_BUFFER_MAX_LENGTH];
+                    char seqBuffer[SEQ_BUFFER_MAX_LENGTH] = {0};
                     int i = 0;
                     seqBuffer[i++] = seq[1];

                     /* If first param is digit or ';', read more until we see a final in @~ */
                     char additionalChar;
-                    while (i < SEQ_BUFFER_MAX_LENGTH-1 && read(l.ifd, &additionalChar, 1) != -1) {
+                    while (i < SEQ_BUFFER_MAX_LENGTH - 1 &&
+                           read(l.ifd, &additionalChar, 1) == 1) {
                         seqBuffer[i++] = additionalChar;
                         if (additionalChar >= '@' && additionalChar <= '~') {    /* CSI final byte */
-                            seqBuffer[i] = '\0';
                             break;
                         }
                     }
+                    seqBuffer[i] = '\0';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deps/linenoise/linenoise.c` around lines 970 - 997, The CSI parsing loop
appends bytes even when read() returns 0 or -1 and only NUL-terminates seqBuffer
when a CSI final is seen, which can lead to unterminated reads in the subsequent
strcmp; change the loop that reads into seqBuffer to only append additionalChar
when read(l.ifd, &additionalChar, 1) == 1, stop on non-1 return or when buffer
limit is reached, and after the loop always NUL-terminate seqBuffer (ensure i <
SEQ_BUFFER_MAX_LENGTH then set seqBuffer[i] = '\0'); keep the existing
comparisons (strcmp(seqBuffer, "1;5D"), "1;3D", "1;5C", "1;3C", "3~") and call
linenoiseEditMoveWordLeft/Right or linenoiseEditDelete as before.
♻️ Duplicate comments (3)
.github/workflows/benchmark-on-demand.yml (3)

71-73: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail early when merge_commit_sha is missing.

Open PRs can temporarily return no merge commit SHA; without a guard, checkout fails later with a less actionable error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/benchmark-on-demand.yml around lines 71 - 73, Check for
the presence of pr.data.merge_commit_sha before calling
core.setOutput('merge_commit_sha', ...) and fail fast if it's missing: if
pr.data.merge_commit_sha is falsy, log a clear error and exit (or set a workflow
failure) so the later checkout step does not run with a missing merge SHA;
update the block that currently calls core.setOutput('merge_commit_sha',
pr.data.merge_commit_sha), core.setOutput('head_sha', pr.data.head.sha),
core.setOutput('base_ref', pr.data.base.ref) to validate
pr.data.merge_commit_sha first and short-circuit with an explicit error when
absent.

40-43: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Scope write permissions per job instead of workflow-wide.

pull-requests: write and issues: write are broader than needed at top level; keep minimal global permissions and grant write only to the commenting job.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/benchmark-on-demand.yml around lines 40 - 43, The workflow
currently sets broad top-level permissions in the permissions: block
(pull-requests: write and issues: write); instead scope these by leaving only
minimal global permissions (e.g., contents: read) at the top-level and move the
pull-requests: write and issues: write entries into the specific job that needs
them (the commenting job), by adding a permissions: subsection under that job
and granting pull-requests: write and issues: write there so only that job has
write access.

145-149: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid direct template interpolation of dispatch inputs in scripts.

Inlining ${{ github.event.inputs.* }} into Bash/JS is injection-prone on self-hosted runners. Pass inputs through env with toJson(...) and parse from process.env/shell variables.

Also applies to: 266-267, 275-277, 288-288

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/benchmark-on-demand.yml around lines 145 - 149, The
workflow currently inlines github.event.inputs directly into shell variables
(COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES, CLUSTER_MODE), which is
injection-prone on self-hosted runners; instead set these inputs into
environment variables using toJson(...) in the workflow env block and then
read/parse them from process.env or standard shell variables inside the script;
update all occurrences that inline inputs (the shown block and the other places
referenced) to use the env approach and parse JSON/strings at runtime to safely
populate COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES and CLUSTER_MODE before use.
🧹 Nitpick comments (4)
src/latency.c (1)

41-46: ⚡ Quick win

Add a rationale comment for the new destructor helper.

The new function is clear, but it should include a brief why-focused function comment per repository C guidelines.

♻️ Proposed change
+/* Free a latency-events dict entry where key, value, and entry are all heap-owned.
+ * This keeps ownership localized to the dict and avoids leaking on dictRelease/delete. */
 static void dictEntryDestructorHeapKeyValue(void *entry) {
     dictEntry *de = entry;
     zfree(dictGetKey(de));
     zfree(dictGetVal(de));
     zfree(de);
 }

As per coding guidelines "Document why code exists, not just what it does; document all functions in C code".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/latency.c` around lines 41 - 46, Add a why-focused function comment above
dictEntryDestructorHeapKeyValue explaining the purpose and rationale: that this
helper is used to free dictEntry instances where both key and value were
heap-allocated by this module (and the dictEntry itself was malloc'd), so it
safely releases key, value, and the entry in one place and avoids duplication of
free logic; follow the repository C comment convention (brief rationale, usage
context, and any invariants/assumptions about ownership) and place it
immediately before the dictEntryDestructorHeapKeyValue definition.
src/valkey-cli.c (1)

391-408: ⚡ Quick win

Document the new entry-destructor ownership rules.

These helpers encode different key/value ownership contracts, so they need brief /* ... */ comments explaining why each one frees the key, the value, or both. That wiring is subtle enough to be easy to misapply later.

As per coding guidelines "Document why code exists, not just what it does; document all functions in C code".

Also applies to: 9223-9227

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/valkey-cli.c` around lines 391 - 408, Add brief block comments above the
three destructor helpers describing the ownership/ownership-transfer contract
they implement: explain that dictEntryDestructorSdsKeyNoVal
(dictEntryDestructorSdsKeyNoVal) frees only the SDS key because values are
owned/managed elsewhere, dictEntryDestructorSdsVal (dictEntryDestructorSdsVal)
frees only the SDS value because keys are shared or static, and
dictEntryDestructorSdsKeyListVal (dictEntryDestructorSdsKeyListVal) frees the
SDS key and releases the list value via listRelease because ownership of both
was transferred to the dict; include why this choice was made (who owns the
memory before/after insertion) and add the same comment pattern for the
equivalent functions at the other occurrence (lines referenced in review
9223-9227).
src/fuzzer_command_generator.c (1)

280-282: 💤 Low value

Dead code: configDictHashFunction is no longer used.

This function is orphaned after configDictType was updated to use sdsHash instead. Consider removing it.

♻️ Suggested removal
-/* Dictionary type implementation for config entries */
-uint64_t configDictHashFunction(const void *key) {
-    return dictGenHashFunction(key, strlen(key));
-}
-
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fuzzer_command_generator.c` around lines 280 - 282, Remove the unused
helper function configDictHashFunction since configDictType now uses sdsHash;
delete the function definition uint64_t configDictHashFunction(const void *key)
and any forward declaration or prototype for configDictHashFunction to avoid
unused symbol warnings, and run a quick grep for "configDictHashFunction" to
ensure no remaining references.
src/server.c (1)

390-392: ⚡ Quick win

Make these new helpers static.

These compare/hash/destructor helpers appear to be used only inside src/server.c, so exporting them widens the linkage surface for no benefit. Please mark them static (and const-qualify the seed input if you touch the signature).

As per coding guidelines, "Use static keyword for file-local functions in C code".

Also applies to: 424-433, 533-590

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server.c` around lines 390 - 392, Make the file-local helper functions
static and tighten any parameter qualifiers: change dictSdsKeyCaseCompare to
have internal linkage by adding the static keyword (i.e., static int
dictSdsKeyCaseCompare(...)) and, if you modify a hash helper signature to accept
a seed, mark the seed parameter const; apply the same static conversion to the
other compare/hash/destructor helpers in this translation unit (the other helper
functions in the same block referenced in the review) so they are file-local and
use const where appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/benchmark-on-demand.yml:
- Around line 294-307: The cleanup step currently uses a broad pkill -f valkey
which can terminate unrelated Valkey processes on shared runners; modify the
workflow to only kill processes started by this job by capturing and storing the
PID(s) when launching valkey (e.g., echo $! > valkey.pid or append to
valkey.pids in the step that starts valkey) and then in the cleanup step read
and kill those PIDs (kill <pid> for each, checking existence) and remove the pid
file(s); alternatively, if you must match by name, scope the pattern to the
workspace path or the exact command line used (e.g., match the working directory
or unique args) instead of using pkill -f valkey, and retain the existing safe
exit-code handling and rm -rf cleanup for files like comparison.md and valkey*.

In `@src/dict.h`:
- Around line 183-187: dictFreeUnlinkedEntry currently calls
type->entryDestructor(de) unconditionally which can dereference a NULL function
pointer; modify dictFreeUnlinkedEntry to retrieve hashtableType *type =
hashtableGetType(d) and only invoke type->entryDestructor(de) if type and
type->entryDestructor are non-NULL (i.e., guard the call with if (type &&
type->entryDestructor) ) so types that do not provide an entryDestructor are
handled safely.

In `@src/server.h`:
- Around line 947-949: Update the comment for the server.dbnum field to reflect
that it represents the configured/maximum number of selectable databases (the
configured DB count), not a count of currently initialized DBs; mention that
code such as watchForKey(), selectDb(), and
initServer()/server.config_databases(_cluster) rely on dbnum as the
configured/max DB index bound and that clients index watched_keys_by_db by
c->db->id which is validated against server.dbnum. Ensure the comment near the
hashtable **watched_keys_by_db** declaration and the server.dbnum declaration
clarifies this semantics to avoid confusion about bounds safety.

In `@src/valkey-cli.c`:
- Around line 379-380: dictSdsHash currently calls sdslen(key) with a void
pointer; cast key to const_sds like dictSdsKeyCompare does (e.g., uint64_t
dictSdsHash(const void *key) { return dictGenHashFunction((const_sds)key,
sdslen((const_sds)key)); }) to satisfy sdslen's expected type and avoid implicit
UB. Also add short doc comments above the destructor functions
dictEntryDestructorSdsKeyNoVal, dictEntryDestructorSdsVal,
dictEntryDestructorSdsKeyListVal, and dictEntryDestructorTypeinfoVal that state
the ownership semantics and exactly which parts they free (e.g., whether they
free the key, the value, both, or a list of sds values, and whether callers must
free before removal) so callers know the freeing contract.

In `@tests/unit/multi.tcl`:
- Around line 391-418: The test changes the shared client r's selected DB (uses
"r select 0" and "r select 1") without restoring it, which can leak DB selection
into other tests; update the test to save and restore r's DB (or simply ensure
you call "r select 0" at the end) so the shared client is returned to its
original DB selection after the test finishes, and ensure any temporary
selection on rd0/rd1 is also cleaned up (references: the r client and rd0/rd1
watch/multi/exec sequence).

---

Outside diff comments:
In `@deps/linenoise/linenoise.c`:
- Around line 970-997: The CSI parsing loop appends bytes even when read()
returns 0 or -1 and only NUL-terminates seqBuffer when a CSI final is seen,
which can lead to unterminated reads in the subsequent strcmp; change the loop
that reads into seqBuffer to only append additionalChar when read(l.ifd,
&additionalChar, 1) == 1, stop on non-1 return or when buffer limit is reached,
and after the loop always NUL-terminate seqBuffer (ensure i <
SEQ_BUFFER_MAX_LENGTH then set seqBuffer[i] = '\0'); keep the existing
comparisons (strcmp(seqBuffer, "1;5D"), "1;3D", "1;5C", "1;3C", "3~") and call
linenoiseEditMoveWordLeft/Right or linenoiseEditDelete as before.

---

Duplicate comments:
In @.github/workflows/benchmark-on-demand.yml:
- Around line 71-73: Check for the presence of pr.data.merge_commit_sha before
calling core.setOutput('merge_commit_sha', ...) and fail fast if it's missing:
if pr.data.merge_commit_sha is falsy, log a clear error and exit (or set a
workflow failure) so the later checkout step does not run with a missing merge
SHA; update the block that currently calls core.setOutput('merge_commit_sha',
pr.data.merge_commit_sha), core.setOutput('head_sha', pr.data.head.sha),
core.setOutput('base_ref', pr.data.base.ref) to validate
pr.data.merge_commit_sha first and short-circuit with an explicit error when
absent.
- Around line 40-43: The workflow currently sets broad top-level permissions in
the permissions: block (pull-requests: write and issues: write); instead scope
these by leaving only minimal global permissions (e.g., contents: read) at the
top-level and move the pull-requests: write and issues: write entries into the
specific job that needs them (the commenting job), by adding a permissions:
subsection under that job and granting pull-requests: write and issues: write
there so only that job has write access.
- Around line 145-149: The workflow currently inlines github.event.inputs
directly into shell variables (COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES,
CLUSTER_MODE), which is injection-prone on self-hosted runners; instead set
these inputs into environment variables using toJson(...) in the workflow env
block and then read/parse them from process.env or standard shell variables
inside the script; update all occurrences that inline inputs (the shown block
and the other places referenced) to use the env approach and parse JSON/strings
at runtime to safely populate COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES and
CLUSTER_MODE before use.

---

Nitpick comments:
In `@src/fuzzer_command_generator.c`:
- Around line 280-282: Remove the unused helper function configDictHashFunction
since configDictType now uses sdsHash; delete the function definition uint64_t
configDictHashFunction(const void *key) and any forward declaration or prototype
for configDictHashFunction to avoid unused symbol warnings, and run a quick grep
for "configDictHashFunction" to ensure no remaining references.

In `@src/latency.c`:
- Around line 41-46: Add a why-focused function comment above
dictEntryDestructorHeapKeyValue explaining the purpose and rationale: that this
helper is used to free dictEntry instances where both key and value were
heap-allocated by this module (and the dictEntry itself was malloc'd), so it
safely releases key, value, and the entry in one place and avoids duplication of
free logic; follow the repository C comment convention (brief rationale, usage
context, and any invariants/assumptions about ownership) and place it
immediately before the dictEntryDestructorHeapKeyValue definition.

In `@src/server.c`:
- Around line 390-392: Make the file-local helper functions static and tighten
any parameter qualifiers: change dictSdsKeyCaseCompare to have internal linkage
by adding the static keyword (i.e., static int dictSdsKeyCaseCompare(...)) and,
if you modify a hash helper signature to accept a seed, mark the seed parameter
const; apply the same static conversion to the other compare/hash/destructor
helpers in this translation unit (the other helper functions in the same block
referenced in the review) so they are file-local and use const where
appropriate.

In `@src/valkey-cli.c`:
- Around line 391-408: Add brief block comments above the three destructor
helpers describing the ownership/ownership-transfer contract they implement:
explain that dictEntryDestructorSdsKeyNoVal (dictEntryDestructorSdsKeyNoVal)
frees only the SDS key because values are owned/managed elsewhere,
dictEntryDestructorSdsVal (dictEntryDestructorSdsVal) frees only the SDS value
because keys are shared or static, and dictEntryDestructorSdsKeyListVal
(dictEntryDestructorSdsKeyListVal) frees the SDS key and releases the list value
via listRelease because ownership of both was transferred to the dict; include
why this choice was made (who owns the memory before/after insertion) and add
the same comment pattern for the equivalent functions at the other occurrence
(lines referenced in review 9223-9227).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e5a6058-f40f-4083-8f81-f9ae13ddc6d5

📥 Commits

Reviewing files that changed from the base of the PR and between 5f75834 and a382095.

📒 Files selected for processing (79)
  • .github/workflows/benchmark-on-demand.yml
  • MAINTAINERS.md
  • cmake/Modules/SourceFiles.cmake
  • deps/CMakeLists.txt
  • deps/Makefile
  • deps/libvalkey/CMakeLists.txt
  • deps/libvalkey/Makefile
  • deps/libvalkey/src/async.c
  • deps/libvalkey/src/cluster.c
  • deps/linenoise/Makefile
  • deps/linenoise/linenoise.c
  • src/Makefile
  • src/cluster_legacy.c
  • src/commands.def
  • src/commands.h
  • src/commands/brpoplpush.json
  • src/commands/bzpopmax.json
  • src/commands/client-import-source.json
  • src/commands/cluster-flushslot.json
  • src/commands/cluster-getslotmigrations.json
  • src/commands/cluster-replicate.json
  • src/commands/commandlog-help.json
  • src/commands/decrby.json
  • src/commands/flushdb.json
  • src/commands/hexpire.json
  • src/commands/hexpireat.json
  • src/commands/hexpiretime.json
  • src/commands/hgetex.json
  • src/commands/hpexpire.json
  • src/commands/hpexpireat.json
  • src/commands/hpexpiretime.json
  • src/commands/hsetex.json
  • src/commands/incrbyfloat.json
  • src/commands/lolwut.json
  • src/commands/ltrim.json
  • src/commands/setnx.json
  • src/commands/slowlog-help.json
  • src/commands/spublish.json
  • src/commands/srandmember.json
  • src/commands/xautoclaim.json
  • src/commands/xclaim.json
  • src/commands/xlen.json
  • src/config.c
  • src/crc16.c
  • src/defrag.c
  • src/dict.c
  • src/dict.h
  • src/eval.c
  • src/expire.c
  • src/expire.h
  • src/functions.c
  • src/fuzzer_command_generator.c
  • src/hashtable.c
  • src/hashtable.h
  • src/latency.c
  • src/module.c
  • src/multi.c
  • src/object.c
  • src/rdb.c
  • src/scripting_engine.c
  • src/sentinel.c
  • src/server.c
  • src/server.h
  • src/t_zset.c
  • src/unit/test_dict.cpp
  • src/unit/test_hashtable.cpp
  • src/unit/test_kvstore.cpp
  • src/unit/test_object.cpp
  • src/valkey-benchmark.c
  • src/valkey-cli.c
  • tests/integration/corrupt-dump-fuzzer.tcl
  • tests/integration/dual-channel-replication.tcl
  • tests/unit/cluster/failover.tcl
  • tests/unit/cluster/failover2.tcl
  • tests/unit/cluster/faster-failover.tcl
  • tests/unit/cluster/replica-migration.tcl
  • tests/unit/maxmemory.tcl
  • tests/unit/memefficiency.tcl
  • tests/unit/multi.tcl
💤 Files with no reviewable changes (3)
  • src/unit/test_dict.cpp
  • src/dict.c
  • src/expire.h
✅ Files skipped from review due to trivial changes (35)
  • src/commands/commandlog-help.json
  • src/commands/hgetex.json
  • src/commands/cluster-flushslot.json
  • src/commands/lolwut.json
  • src/commands/hpexpiretime.json
  • src/commands/client-import-source.json
  • src/commands/slowlog-help.json
  • src/commands/hpexpireat.json
  • src/commands/flushdb.json
  • src/commands/brpoplpush.json
  • src/commands/decrby.json
  • src/commands/hexpireat.json
  • src/commands/cluster-getslotmigrations.json
  • MAINTAINERS.md
  • src/commands/bzpopmax.json
  • src/commands/hexpire.json
  • src/commands/xautoclaim.json
  • src/t_zset.c
  • src/commands/xlen.json
  • deps/libvalkey/src/cluster.c
  • deps/linenoise/Makefile
  • src/hashtable.h
  • src/commands/spublish.json
  • src/commands/hsetex.json
  • deps/libvalkey/src/async.c
  • src/commands/hexpiretime.json
  • deps/Makefile
  • src/commands/setnx.json
  • src/commands/hpexpire.json
  • src/commands/srandmember.json
  • src/commands/xclaim.json
  • src/commands/ltrim.json
  • src/commands/cluster-replicate.json
  • src/commands/incrbyfloat.json
  • src/commands.def

Comment thread .github/workflows/benchmark-on-demand.yml
Comment thread src/dict.h
Comment thread src/server.h
Comment thread src/valkey-cli.c
Comment thread tests/unit/multi.tcl

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (3)
.github/workflows/benchmark-on-demand.yml (3)

163-167: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid direct ${{ github.event.inputs.* }} interpolation inside Bash/JS scripts.

Lines 163-167 and Lines 284-306 inline workflow inputs directly into executable script text. Even with maintainer-triggered dispatch, this is still a template-injection risk on self-hosted runners. Use env + toJson(...) and parse from environment in Bash/Node.

Safer pattern (condensed)
       - name: Generate benchmark config
+        env:
+          INPUT_COMMANDS: ${{ toJson(github.event.inputs.commands) }}
+          INPUT_DATA_SIZE: ${{ toJson(github.event.inputs.data_size) }}
+          INPUT_IO_THREADS: ${{ toJson(github.event.inputs.io_threads) }}
+          INPUT_PIPELINES: ${{ toJson(github.event.inputs.pipelines) }}
+          INPUT_CLUSTER_MODE: ${{ toJson(github.event.inputs.cluster_mode) }}
         run: |
-          COMMANDS='${{ github.event.inputs.commands }}'
+          COMMANDS="$(jq -r . <<<"$INPUT_COMMANDS")"
           ...

       - name: Comment PR with results
+        env:
+          INPUT_PR_NUMBER: ${{ toJson(github.event.inputs.pr_number) }}
+          INPUT_COMMANDS: ${{ toJson(github.event.inputs.commands) }}
+          INPUT_CLUSTER_MODE: ${{ toJson(github.event.inputs.cluster_mode) }}
+          INPUT_DATA_SIZE: ${{ toJson(github.event.inputs.data_size) }}
+          INPUT_IO_THREADS: ${{ toJson(github.event.inputs.io_threads) }}
+          INPUT_PIPELINES: ${{ toJson(github.event.inputs.pipelines) }}
         with:
           script: |
-            const commands = '${{ github.event.inputs.commands }}';
+            const commands = JSON.parse(process.env.INPUT_COMMANDS);
             ...
-              issue_number: ${{ github.event.inputs.pr_number }},
+              issue_number: Number(JSON.parse(process.env.INPUT_PR_NUMBER)),

Also applies to: 284-306

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/benchmark-on-demand.yml around lines 163 - 167, Replace
direct interpolation of workflow inputs into script text (the variables
COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES, CLUSTER_MODE) with a safe
environment-based pattern: set an env output using toJson(...) in the workflow
YAML and then read/parse that JSON from the script (Bash or Node) instead of
embedding ${ { github.event.inputs.* } } inline; update both the block that
defines COMMANDS/DATA_SIZE/IO_THREADS/PIPELINES/CLUSTER_MODE and the later
script region (lines around 284-306) to parse the same env JSON and assign local
variables, ensuring no direct template injection into executable script content.

319-326: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not use broad pkill -f valkey on a shared self-hosted runner.

Line 319 can terminate unrelated Valkey processes from other workflows on the same host. Prefer killing only PIDs started by this run (or, at minimum, scope matching to this workspace path).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/benchmark-on-demand.yml around lines 319 - 326, The pkill
-f valkey call is too broad and may kill unrelated Valkey processes; instead
modify the workflow script to track and kill only the PID(s) started by this run
(or scope the match to the current workspace). When launching valkey, capture
its PID (e.g., store $! into a file or variable) and later kill those PIDs
(verify they belong to this workspace before killing), replacing the pkill -f
valkey line and using the existing exit_code handling; alternatively, constrain
any pattern used with pgrep/pkill to include the workspace path (e.g., match
"valkey.*$GITHUB_WORKSPACE") so only processes from this run are targeted.

93-96: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove unnecessary pull-requests: write from the benchmark job permissions.

The benchmark job only posts the results to the PR via github.rest.issues.createComment, so it doesn’t need pull-requests write scope (that’s used elsewhere for github.rest.pulls.get with read access).

Suggested minimal change
     permissions:
       contents: read
-      pull-requests: write
       issues: write
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/benchmark-on-demand.yml around lines 93 - 96, The
benchmark job's permissions block grants unnecessary pull-requests: write;
remove the "pull-requests: write" entry from the permissions section (leaving
contents: read and issues: write) so that the job only has the minimal scopes
needed for github.rest.issues.createComment; update the permissions object in
the workflow where the keys permissions, contents, pull-requests, and issues are
declared to delete the pull-requests line.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @.github/workflows/benchmark-on-demand.yml:
- Around line 163-167: Replace direct interpolation of workflow inputs into
script text (the variables COMMANDS, DATA_SIZE, IO_THREADS, PIPELINES,
CLUSTER_MODE) with a safe environment-based pattern: set an env output using
toJson(...) in the workflow YAML and then read/parse that JSON from the script
(Bash or Node) instead of embedding ${ { github.event.inputs.* } } inline;
update both the block that defines
COMMANDS/DATA_SIZE/IO_THREADS/PIPELINES/CLUSTER_MODE and the later script region
(lines around 284-306) to parse the same env JSON and assign local variables,
ensuring no direct template injection into executable script content.
- Around line 319-326: The pkill -f valkey call is too broad and may kill
unrelated Valkey processes; instead modify the workflow script to track and kill
only the PID(s) started by this run (or scope the match to the current
workspace). When launching valkey, capture its PID (e.g., store $! into a file
or variable) and later kill those PIDs (verify they belong to this workspace
before killing), replacing the pkill -f valkey line and using the existing
exit_code handling; alternatively, constrain any pattern used with pgrep/pkill
to include the workspace path (e.g., match "valkey.*$GITHUB_WORKSPACE") so only
processes from this run are targeted.
- Around line 93-96: The benchmark job's permissions block grants unnecessary
pull-requests: write; remove the "pull-requests: write" entry from the
permissions section (leaving contents: read and issues: write) so that the job
only has the minimal scopes needed for github.rest.issues.createComment; update
the permissions object in the workflow where the keys permissions, contents,
pull-requests, and issues are declared to delete the pull-requests line.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 71b31b4f-47da-4b3e-89f8-fcb9d646ecc7

📥 Commits

Reviewing files that changed from the base of the PR and between a382095 and 3e926b4.

📒 Files selected for processing (1)
  • .github/workflows/benchmark-on-demand.yml

Adds a workflow_dispatch-triggered workflow that runs comparative
benchmarks on any open PR with configurable inputs (commands, data
sizes, io-threads, pipelines, cluster mode). Posts results back to
the PR as a comment.

Implements: valkey-io/valkey-perf-benchmark#52

Notes:
- Permissions are scoped per-job (defense-in-depth): only the job
  that posts the comment has pull-requests:write + issues:write.
- Input validation enforces sane bounds for data_size (1-1MB),
  io_threads (1-20), pipelines (1-1000).
- timeout-minutes set to 420 (7h, ~1.3x expected runtime).
- Fails fast with a clear message if the PR has no mergeable commit
  (conflict with base, or merge not yet computed).

Signed-off-by: Roshan Khatri <rvkhatri@amazon.com>
@roshkhatri roshkhatri force-pushed the on-demand-benchmark branch from 3e926b4 to f4e1240 Compare May 26, 2026 18:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/benchmark-on-demand.yml:
- Around line 129-138: The workflow's "Install dependencies" step is missing the
jq package used later by the "Generate benchmark config" step; update the
install command in the Install dependencies step to include jq (add jq to the
sudo dnf install list) so the subsequent uses of jq in the Generate benchmark
config step (lines referenced in the review) will run without error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d43e2b2b-5ad2-4593-8238-a99ed62e61ec

📥 Commits

Reviewing files that changed from the base of the PR and between 3e926b4 and f4e1240.

📒 Files selected for processing (1)
  • .github/workflows/benchmark-on-demand.yml

Comment thread .github/workflows/benchmark-on-demand.yml
Signed-off-by: Roshan Khatri <rvkhatri@amazon.com>
@roshkhatri roshkhatri requested a review from zuiderkwast May 26, 2026 18:44
Direct interpolation of ${{ github.event.inputs.* }} into bash and
JavaScript bodies meant a quote/escape character in an input could
break script quoting on the self-hosted runner. The risk is small
(workflow_dispatch is admin-only) but the pattern is fragile.

Move the inputs through job-level `env:` mappings instead, so the
runner passes them via environment variables rather than shell
substitution. The Bash step reads via "$INPUT_*", and the
github-script step reads via process.env.INPUT_*.

Addresses CodeRabbit review on PR valkey-io#3433.

Signed-off-by: Roshan Khatri <rvkhatri@amazon.com>
PR valkey-io#3753 moved benchmark configs out of valkey/.github/benchmark_configs/
into valkey-perf-benchmark/configs/. Update the config path references
in the Generate benchmark config and Run benchmarks steps to match.

This aligns with how benchmark-on-label.yml references the config today.

Signed-off-by: Roshan Khatri <rvkhatri@amazon.com>
@zuiderkwast zuiderkwast merged commit 12e12c6 into valkey-io:unstable May 26, 2026
63 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.

6 participants