Skip to content

fix(queue): concurrency follow-ups from #2890 post-merge review - #2965

Open
chmouel wants to merge 3 commits into
tektoncd:mainfrom
chmouel:chmouel/fix-concurrency-queue-followups
Open

chmouel wants to merge 3 commits into
tektoncd:mainfrom
chmouel:chmouel/fix-concurrency-queue-followups

Conversation

@chmouel

@chmouel chmouel commented Sep 4, 2026

Copy link
Copy Markdown
Member

📝 Description of the Change

Fixes concurrency queue recovery and malformed execution-order handling
following #2890, and makes the queue debug endpoint opt-in.

Malformed execution-order entries (#2945)

Execution-order entries now use a shared parser that rejects empty or
malformed namespace/name pairs. Bad entries no longer panic the watcher
during startup or queue promotion. Finalization uses the same guarded
promotion path.

Queue recovery after API failures

A failed start response does not prove that Kubernetes left a run pending.
The watcher reads the run's current state and keeps its concurrency
reservation while the outcome is uncertain. Retries resume that reservation
instead of admitting another run or waiting for a watcher restart.

Temporary read failures keep candidates in their original waiting order.
Retries respect the current concurrency limit, including inherited settings.
Conditional start requests prevent delayed writes from overwriting a newer
run state or affecting a replacement run with the same name.

Completion and finalization return queue-promotion errors for retry.
Completion records its terminal state only after promotion succeeds, since
terminal states stop further reconciliation. Successful handoffs are
remembered while the final state is being saved.

Provider detection failures (#2946)

Temporary provider detection failures now return an error so the workqueue
retries. Previously, a finished run could keep its concurrency slot because
the failure was silently treated as success.

Missing or unknown providers take a separate path: release the finished run's
slot, promote the queue, then mark the run failed. If promotion fails, the
run stays retryable until its queue work finishes.

Queue debug endpoint (#2947)

/debug/queue was registered unconditionally on the probe port and exposed
Repository and PipelineRun names across namespaces without authentication.
It is now gated behind PAC_ENABLE_QUEUE_DEBUG, disabled by default, and
stays disabled for an invalid value.

The E2E helper opts in by updating the watcher Deployment and waiting for
rollout. The concurrency documentation describes the toggle.

🔗 Linked GitHub Issue

Fixes #2945
Fixes #2946
Fixes #2947

Jira epic: SRVKP-14316 — Concurrency queue robustness:
no lost or leaked slots under failure

Ticket Covered by
SRVKP-14113 — watcher crash-loops on a malformed execution-order annotation fix: Keep queue recovery within concurrency limits
SRVKP-7608 — PaC concurrency getting stuck with no running PipelineRuns queue recovery + provider lookup commits
SRVKP-11296 — PipelineRuns stuck in Pending state (limit > 1) queue recovery + provider lookup commits
SRVKP-14317/debug/queue unauthenticated and enabled by default fix(watcher): gate /debug/queue behind an env var

🧪 Testing Strategy

  • Unit tests
  • Integration tests
  • End-to-end tests
  • Manual testing
  • Not Applicable

Unit coverage includes lost start responses, transient read failures,
retry ownership, concurrency-limit changes, final-state write failures,
malformed queue keys, provider detection, and the debug toggle.
The existing Gitea concurrency E2E case covers debug-endpoint opt-in;
live E2E execution is outside this update's scope.

🤖 AI Assistance

  • I have not used any AI assistance for this PR.
  • I have used AI assistance for this PR.

✅ Submitter Checklist

  • 📝 My commit messages are clear, informative, and follow the project's How to write a git commit message guide. The Gitlint linter ensures in CI it's properly validated
  • ✨ I have ensured my commit message prefix (e.g., fix:, feat:) matches the "Type of Change" I selected above.
  • ♽ I have run make test and make lint locally to check for and fix any
    issues. For an efficient workflow, I have considered installing
    pre-commit and running pre-commit install to
    automate these checks.
  • 📖 I have added or updated documentation for any user-facing changes.
  • 🧪 I have added sufficient unit tests for my code changes.
  • 🎁 I have added end-to-end tests where feasible. See README for more details.
  • 🔎 I have addressed any CI test flakiness or provided a clear reason to bypass it.
  • If adding a provider feature, I have filled in the following and updated the provider documentation:
    • GitHub App
    • GitHub Webhook
    • Gitea/Forgejo
    • GitLab
    • Bitbucket Cloud
    • Bitbucket Data Center

Copilot AI lite review requested due to automatic review settings September 4, 2026 08:30
@chmouel chmouel added bug Something isn't working security labels Sep 4, 2026
@codecov

codecov Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.46926% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.68%. Comparing base (8ed3d29) to head (268c7a2).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pkg/queue/admission.go 92.03% 9 Missing ⚠️
pkg/queue/queue_manager.go 93.93% 2 Missing ⚠️
pkg/reconciler/reconciler.go 97.05% 2 Missing ⚠️
pkg/queue/semaphore.go 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2965      +/-   ##
==========================================
+ Coverage   91.57%   91.68%   +0.10%     
==========================================
  Files         164      165       +1     
  Lines       12532    12718     +186     
==========================================
+ Hits        11476    11660     +184     
- Misses       1055     1057       +2     
  Partials        1        1              
Flag Coverage Δ
unit-tests 91.68% <95.46%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 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.

Copilot AI 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.

🟡 Changes recommended

The new E2E helper can silently “succeed” even if it never finds the target watcher container to patch, and an error message inaccurately refers to an annotation as a label.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Follow-up fixes to Pipelines-as-Code’s concurrency queue and watcher, addressing a crash-loop on malformed execution-order annotations, preventing leaked concurrency slots when provider detection fails on completed PipelineRuns, and gating the /debug/queue endpoint behind an explicit opt-in.

Changes:

  • Add a shared, defensive namespace/name key parser and apply it to execution-order/queue parsing paths to prevent panics and slot leaks.
  • Ensure transient provider-detection failures return errors (to trigger retries), while permanent “provider not configured” cases fail the run and release the queue slot.
  • Disable /debug/queue by default and require PAC_ENABLE_QUEUE_DEBUG=true to enable it; update E2E helpers, docs, and tests accordingly.
File summaries
File Description
test/pkg/kubestuff/watcher.go Adds E2E opt-in helper to enable /debug/queue by patching the watcher Deployment and waiting for rollout.
test/gitea_concurrency_test.go Enables queue debug endpoint before scenarios that assert drained queue state.
pkg/reconciler/reconciler.go Differentiates transient vs permanent provider-detection failures; introduces abandonment path to release slots for done runs with no resolvable provider.
pkg/reconciler/reconciler_test.go Adds regression tests for transient detectProvider errors vs permanent “not configured” behavior and queue-slot release ordering.
pkg/reconciler/queue_pipelineruns.go Uses shared queue key parsing helper when fetching acquired PipelineRuns.
pkg/reconciler/finalizer.go Routes finalizer promotion through the shared “start next from queue” path to avoid key-splitting panics.
pkg/reconciler/finalizer_test.go Adds regression tests ensuring malformed queue keys don’t panic and don’t strand phantom running slots.
pkg/reconciler/event.go Introduces ErrProviderNotConfigured and wraps “missing/unknown provider” errors to classify as permanent.
pkg/reconciler/event_test.go Updates detectProvider tests to assert permanent classification via errors.Is.
pkg/queue/queue_manager.go Skips malformed execution-order entries instead of panicking; logs a warning and normalizes returned keys.
pkg/queue/queue_manager_test.go Adds coverage for malformed execution-order entries mixed with valid ones.
pkg/queue/queue_manager_interface.go Adds SplitPrKey helper to defensively parse namespace/name keys with trimming/validation.
pkg/queue/queue_manager_interface_test.go New unit tests for SplitPrKey validation behavior.
docs/content/docs/advanced/concurrency.md Documents /debug/queue risk, default-off behavior, and explicit enable/disable steps.
cmd/pipelines-as-code-watcher/main.go Gates /debug/queue handler registration behind PAC_ENABLE_QUEUE_DEBUG (fail-closed on invalid values).
cmd/pipelines-as-code-watcher/main_test.go New tests covering PAC_ENABLE_QUEUE_DEBUG parsing and default-off behavior.
Review details
  • Files reviewed: 16/16 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/pkg/kubestuff/watcher.go Outdated
Comment thread pkg/reconciler/event.go
@pipelines-as-code

pipelines-as-code Bot commented Sep 4, 2026

Copy link
Copy Markdown

Paco Review 🔍

This PR introduces an admission-based concurrency queue manager for Pipelines-as-Code. It adds a new Admission abstraction that owns retries, tracks uncertain starts, and prevents slot leaks when PipelineRun starts fail transiently or idempotently. It also gates the /debug/queue endpoint behind an env-var flag for security, propagates errors from FilterPipelineRunByState, adds optimistic concurrency via resourceVersion/uid in the start patch, and wires everything through the reconciler's multiple code paths (initial queue, finalizer, abandonment, promotion).

Review difficulty: 5/5 (Very Hard) — The change touches the core concurrency slot management across five code paths (initial, resume, promotion, finalization, abandonment), introduces a new multi-phase admission state machine with lock-guarded invariants, changes error semantics for ErrPipelineRunNotStarted and slot release, and adds ~1400 lines of new code including complex recovery tests.

6 new inline comment(s) found.

Reviewed commit: cd89bc1

@pipelines-as-code pipelines-as-code Bot added paco/review-hard Paco review difficulty security-review Flagged as security-sensitive by Paco labels Sep 4, 2026

@pipelines-as-code pipelines-as-code 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.

Paco inline comments -- see the Paco Review summary comment for the overview.

Comment thread pkg/reconciler/reconciler.go
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from a754bb2 to 7e67624 Compare September 4, 2026 08:45
@chmouel
chmouel requested a balanced review from Copilot September 4, 2026 09:00

Copilot AI 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.

🟡 Changes recommended

The provider-error behavior conflicts with the documented retry requirement, and the debug-toggle test is environment-dependent.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 16/16 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread pkg/reconciler/reconciler.go
Comment thread cmd/pipelines-as-code-watcher/main_test.go Outdated
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from 7e67624 to d39ff62 Compare September 7, 2026 12:17
Comment thread pkg/reconciler/reconciler.go
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from d39ff62 to 9554126 Compare September 9, 2026 12:52
@chmouel

chmouel commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

The follow-up review I did with while sterring the harness agent found two more queue
failure paths. Kubernetes could start a run but fail to return the response,
causing the watcher to release its slot and start another run beyond the concurrency limit.
A temporary API read failure could also remove the next run from the queue and leave it
waiting indefinitely.

Both are fixed. Uncertain starts keep their reservations while the watcher
checks their state and retries. Temporary read failures preserve waiting
order. Completion, deletion, and provider-abandonment paths now return
promotion errors for retry before treating their queue work as finished.
Retrying a completed handoff does not start another successor.

These changes are folded into the queue and provider-recovery commits. The
debug-endpoint change is unchanged.

@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from 9554126 to 1c58ea1 Compare September 9, 2026 14:39
@chmouel
chmouel requested a balanced review from Copilot September 9, 2026 14:44
@chmouel

chmouel commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

More than i think about it and if we want to properly test this is to do some chaos monkey on the cluster (there is some k8s project doing this) and see how well we recover from the chaos. but that's a long and winded road to be able to get there.

Copilot AI 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.

🟡 Changes recommended

Graceful cancellation states remain startable during queue recovery and can be incorrectly reported as running.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread pkg/reconciler/reconciler.go Outdated
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch 2 times, most recently from 11b9ab4 to 13fea28 Compare September 10, 2026 06:24
@chmouel
chmouel requested a balanced review from Copilot September 10, 2026 06:46

Copilot AI 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.

🟡 Changes recommended

Failed start readbacks can suppress required metadata retries, and terminal runs can retry forever after their Repository is deleted.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread pkg/reconciler/reconciler.go
Comment thread pkg/reconciler/reconciler.go
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from f40059b to 2ad680e Compare September 11, 2026 08:11
@chmouel
chmouel requested a balanced review from Copilot September 11, 2026 08:13

Copilot AI 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.

🟡 Changes recommended

Queue-promotion retries can repeat final provider reporting and costly LLM analysis side effects.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread pkg/reconciler/reconciler.go

Copilot AI 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.

🟡 Changes recommended

Malformed Kubernetes path segments can still indefinitely block watcher startup or queue recovery.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread pkg/queue/queue_manager_interface.go
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from 2ad680e to 69c6f3b Compare September 11, 2026 11:11
@chmouel
chmouel requested a balanced review from Copilot September 11, 2026 11:11

Copilot AI 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.

🔵 Needs a closer look

The stateful concurrency recovery and cross-reconciliation retry behavior warrant final human review despite comprehensive tests.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@chmouel

chmouel commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

I’m experimenting with queue recovery through a chaos-testing branch, and it found a retry loop in this path.

A PipelineRun can still report Running while cancellation or graceful shutdown is in progress, before PaC reports its start. updatePipelineRunToInProgress returns errPipelineRunGone, but ReconcileKind sent that error back to the workqueue. The watcher retried until Tekton finished draining the run.

Queue promotion already treats errPipelineRunGone as terminal. I folded the fix into 8e4c853 (fix: Keep queue recovery within concurrency limits) so both paths handle it the same way. It covers Cancelled, CancelledRunFinally, and StoppedRunFinally.

@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from 69c6f3b to 8e4c853 Compare September 11, 2026 14:19
@chmouel
chmouel requested a balanced review from Copilot September 11, 2026 14:21

Copilot AI 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.

🟡 Changes recommended

The security-sensitive route gating lacks a route-level regression test for its default-off guarantee.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread cmd/pipelines-as-code-watcher/main.go
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from 5c922bb to 17e643f Compare September 11, 2026 14:37
@chmouel
chmouel requested a balanced review from Copilot September 16, 2026 08:08

Copilot AI 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.

🔵 Needs a closer look

The extensive concurrency state-machine and failure-recovery changes warrant final human validation despite strong test coverage.

Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@chmouel

chmouel commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

/paco review

@pipelines-as-code pipelines-as-code Bot added paco/review-very-hard Paco review difficulty and removed paco/review-hard Paco review difficulty labels Sep 21, 2026

@pipelines-as-code pipelines-as-code 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.

Paco inline comments -- see the Paco Review summary comment for the overview.

Comment thread pkg/queue/admission.go
Comment thread pkg/queue/admission.go
Comment thread pkg/queue/admission.go
Comment thread pkg/queue/admission.go
Comment thread pkg/reconciler/reconciler.go
Comment thread pkg/queue/queue_manager_test.go Outdated
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from cd89bc1 to 67093a2 Compare September 21, 2026 10:18
Malformed execution-order entries were skipped instead of crashing
the watcher during startup or queue promotion.

Queue recovery was changed to handle temporary API failures without
losing waiting runs or starting too many at once. Kubernetes could
start a run even when the watcher received an error. Reservations
were kept until the run's state could be established. Retries were
tracked so recovery no longer depended on a watcher restart.

Temporary read failures preserved waiting order. Retried starts used
updated concurrency limits, and stale start requests could not overwrite
a newer run state. Completion and deletion returned promotion failures
for retry before treating their queue work as finished.

Fixes tektoncd#2945

Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>
Temporary provider lookup failures on finished runs were returned for
retry instead of silently leaving their concurrency slots occupied.

Runs with missing or unknown providers released their slots before being
marked failed. If starting the next waiting run failed, the error was
returned before recording that final state, so the next attempt could
resume the queue work. A successful handoff was remembered when saving
the final state failed, preventing retries from starting another run
for the same handoff.

Fixes tektoncd#2946

Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>
The queue debug endpoint was registered unconditionally and is
unauthenticated, disclosing namespace, Repository, and PipelineRun
names to anything that can reach the pod. Gate it behind
PAC_ENABLE_QUEUE_DEBUG (default disabled, fails closed on an
unparseable value). Update the E2E helper to opt in and document
the new toggle.

Fixes tektoncd#2947

Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>
Assisted-by: Claude
@chmouel
chmouel force-pushed the chmouel/fix-concurrency-queue-followups branch from 67093a2 to 268c7a2 Compare September 21, 2026 11:45

This branch has not been deployed

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

Labels

bug Something isn't working ok-to-test paco/review-very-hard Paco review difficulty security security-review Flagged as security-sensitive by Paco

Projects

None yet

3 participants