Skip to content

fix(github-runner): key per-run job cache by (repo, runID) - #7952

Open
hontarenko wants to merge 2 commits into
kedacore:mainfrom
hontarenko:fix/github-runner-per-run-job-cache
Open

fix(github-runner): key per-run job cache by (repo, runID)#7952
hontarenko wants to merge 2 commits into
kedacore:mainfrom
hontarenko:fix/github-runner-per-run-job-cache

Conversation

@hontarenko

Copy link
Copy Markdown

Summary

previousJobs was keyed by repository name only, but getWorkflowRunJobs is called once per individual workflow run. When a repository has multiple simultaneous queued/in_progress runs (e.g. a matrix-heavy release workflow plus a concurrent scheduled sync run), a 304 for one run's jobs URL could return whichever run's job list was cached last for that repo — silently double-counting one run's jobs in place of another's and inflating the computed GetWorkflowQueueLength() target.

This keys previousJobs by (repoName, workflowRunID) instead, updates pruneCaches/evictExcess accordingly (added an evictExcessJobs helper bounding total (repo, runID) entries), and adds a regression test covering two concurrent runs in the same repo both hitting 304.

Note: previousJobs is intentionally not pruned by the currentRepos list in pruneCaches (unlike previousWfrs) — it's keyed by each run's own Repository.Name, which isn't guaranteed to be an element of currentRepos. It's still bounded by evictExcessJobs.

Fixes #7949

Checklist

previousJobs was keyed by repository name only, but
getWorkflowRunJobs is called once per individual workflow run. When
a repository has multiple simultaneous queued/in_progress runs (e.g.
a matrix-heavy release workflow plus a concurrent scheduled sync
run), a 304 for one run's jobs URL could return whichever run's job
list was cached last for that repo, silently double-counting one
run's jobs in place of another's and inflating the computed
GetWorkflowQueueLength() target.

Key previousJobs by (repoName, workflowRunID) instead, update
pruneCaches/evictExcess accordingly, and add a regression test
covering two concurrent runs in the same repo both hitting 304.

Fixes kedacore#7949

Signed-off-by: Serhii Hontarenko <serhii.hontarenko@amo.tech>
@hontarenko
hontarenko requested a review from a team as a code owner July 31, 2026 21:43
@snyk-io

snyk-io Bot commented Jul 31, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@keda-automation
keda-automation requested a review from a team July 31, 2026 21:43
@github-actions

Copy link
Copy Markdown

Thank you for your contribution! 🙏

Please understand that we will do our best to review your PR and give you feedback as soon as possible, but please bear with us if it takes a little longer as expected.

While you are waiting, make sure to:

  • Add an entry in our changelog in alphabetical order and link related issue
  • Update the documentation, if needed
  • Add unit & e2e tests for your changes
  • GitHub checks are passing
  • Is the DCO check failing? Here is how you can fix DCO issues

Once the initial tests are successful, a KEDA member will ensure that the e2e tests are run. Once the e2e tests have been successfully completed, the PR may be merged at a later date. Please be patient.

Learn more about our contribution guide.

@rickbrouwer

Copy link
Copy Markdown
Member

Great, thanks for the fix.

I've one suggestion on the data structure that I think simplifies things a bit. Instead of nesting map[string]map[int64][]Job, we could use a flat map with a small composite struct key.

The main benefit is that the existing generic evictExcess keeps working as-is, so the separate evictExcessJobs helper can be dropped.

Per review feedback: use a flat map[jobCacheKey][]Job (a small
{repo, runID} struct key) instead of nesting map[string]map[int64][]Job.
This lets the existing generic evictExcess helper bound previousJobs
directly, same as etags and previousWfrs, so the separate
evictExcessJobs helper is no longer needed.

Signed-off-by: Serhii Hontarenko <serhii.hontarenko@amo.tech>
@rickbrouwer

Copy link
Copy Markdown
Member

Great, this is exactly what I was looking for.

I will start the e2e right away.

@rickbrouwer

rickbrouwer commented Aug 1, 2026

Copy link
Copy Markdown
Member

/run-e2e github*
Update: You can check the progress here

passed tests: 1
Execution of tests/scalers/github_runner/github_runner_test.go, has passed after "one" attempts
failed tests: 0

@rickbrouwer rickbrouwer added the Awaiting/2nd-approval This PR needs one more approval review label Aug 1, 2026

@dttung2905 dttung2905 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 @hontarenko for the help! Approved from me. Just two nits from me, both are non-blocking but more like improvement and hygiene

  • the PR body stills mentioned nested maps and eviecExcessJobs can you help to update the PR description to reflect the latest changes?
  • How about completed run IDs lingering after they leave queued/in_progress ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Awaiting/2nd-approval This PR needs one more approval review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

github-runner scaler: per-repo ETag job cache returns the wrong workflow run's jobs when a repository has multiple simultaneous queued/in_progress runs

3 participants