Immutable
release. Only release title and notes can be modified.
Pipelines as Code version v0.50.0
OpenShift Pipelines as Code v0.50.0 has been released 🥳
✨ Features
- Bitbucket Cloud HMAC webhook secret validation: Bitbucket Cloud webhooks can now be verified using X-Hub-Signature / X-Hub-Signature-256 HMAC validation, matching the existing GitHub and Bitbucket Data
Center pattern. When a webhook_secret is configured on the Repository CR, incoming payloads are verified against the signature header. #2870 - AI-powered code review pipeline (Paco): Added a new Tekton PipelineRun that integrates AI for automated code reviews on pull requests, triggered by PR comments with /paco review or /paco summary. Includes PR
diff analysis, difficulty scoring with labels (Trivial through Very Hard), and security-sensitivity detection. #2840, #2860 - Read-only queue debug endpoint: The watcher now exposes a read-only HTTP endpoint to inspect the concurrency queue state, useful for debugging queue drift issues. #2890
- Container creation error messages in logs: When tasks fail due to secret or configuration issues, the actual error messages from container initialization failures (e.g. "secret not found") are now captured
and displayed, replacing generic failure reason codes. #2853 - GitHub comment strategy webhook validation: Added admission webhook validation for the GitHub comment_strategy repository setting and e2e CRD enum coverage, mirroring the existing checks for GitLab and
Forgejo. #2901
🐛 Bug Fixes
- Queue slot could permanently exceed concurrency limit: When setup failed after a queued PipelineRun was un-paused, PAC handed the slot back even though the run was already going in the cluster. The slot
count drifted on every failure and never recovered — a repository limited to 3 could end up running 4, then 5. PAC now checks whether the run was actually un-paused before releasing the slot. #2890 - Queue lost sync with cluster on watcher restart: A single PipelineRun missing an expected annotation made the watcher abort its entire queue rebuild on startup, leaving every repository it hadn't reached yet
with an empty queue. It now skips the bad run and continues. Changing a concurrency limit also had no effect until an unrelated event woke the queue — PAC now watches Repository changes and re-examines queued
runs immediately. #2890 - Concurrent queue access crashed the watcher: Two concurrency-limited repositories reconciled simultaneously caused a data race that killed the process. The queue bookkeeping is now properly guarded. Three
uncalled methods (~200 lines) including one that would crash on an empty queue are removed. #2890 - Recover fork PR re-runs when GitHub omits PR metadata: Rerequest handling for check runs on fork PRs is now more resilient when GitHub's webhook payload omits pull request metadata or when the
commits/{sha}/pulls API returns no matches. #2655 - GitLab: verify secret write access before token rotation: The token auto-rotation feature now performs a server-side dry-run Secret update before revoking the old token, preventing irrecoverable credential
loss if the Kubernetes Secret update would fail with a permission error. #2837 - GitLab: handle branch creation without commits: GitLab can send a Push Hook with an empty commits array when a new branch is created at an existing commit. These payloads are now accepted and trigger
PipelineRuns using the after SHA. #2875 - GitLab: pin source lookups to event SHA: Use the immutable event SHA for GitLab source provenance instead of a mutable branch reference, pinning both .tekton PipelineRun definitions and repository-local
Task/Pipeline references to the same revision. #2898 - GitHub: query check runs for /retest: Implemented GetCommitStatuses for the GitHub provider so /retest only re-runs failed pipelines when PipelineRuns have been pruned, querying the Check Runs API in App
mode and Commit Statuses API in PAT mode. #2876 - Gitea: check write/admin permission instead of collaborator only: Replaced IsCollaborator (which returns true for read-only collaborators) with CollaboratorPermission to verify the sender has write or admin
access before allowing pipeline runs. #2849 - Gitea: guard nil content in GetFileInsideRepo: Fixed a controller crash (SIGSEGV → CrashLoopBackOff) when the forgejo-sdk returns nil content for a missing file instead of an error. #2894
- CLI: set Bitbucket Cloud email in update-token: When updating a Bitbucket Cloud token via the CLI, the Atlassian account email is now prompted and saved, preventing stale username 401 errors after token
rotation. #2851 - Security: CVE-2026-33211 - upgrade github.com/tektoncd/pipeline to v1.14.1 to fix critical path traversal in the Tekton Pipelines git resolver. #2881
- Security: CVE-2026-42505 - update Go to 1.26.5 to fix crypto/tls ECH privacy leak. #2842
- Graceful shutdown for controller listener: The controller's HTTP listener now monitors context cancellation, allowing clean shutdown on SIGTERM instead of hanging until SIGKILL. #2877
- Log sinker errors and emit event on repository config error: Errors returned from processEvent() now log with full context (repository URL, commit SHA, etc.) and emit a Kubernetes Event when the Repository
CR has a missing or misconfigured GitProvider.Secret. #2848 - Provider logging consistency: All provider code now uses the provider logger (v.Logger) instead of run.Clients.Log, ensuring standard context variables (provider, repository, event-id) are present in logs.
#2827, #2836 - Detect and prevent nil pointer crashes: Integrated NilAway static analysis into the linting pipeline and fixed 11 potential nil pointer issues across core packages. #2868
- Expose metrics port 9090 for webhook: Added the missing containerPort and Service port for Prometheus metrics on the webhook deployment, matching the controller and watcher. #2895
- Populate timestamp fields on emitted k8s events: Events now include FirstTimestamp, LastTimestamp, Count, and ReportingController, fixing in kubectl's LAST SEEN column. #2896
- Bump knative.dev/pkg and semconv to fix otel schema panic. #2845
- Fix e2e flakiness: Wait for push PipelineRun in gitea params test to prevent race condition failures. #2838
🧪 Tests
- Assert concurrency limits are actually respected: Existing e2e tests only checked that all runs eventually succeeded, which passes even without a working queue. New assertions verify true maximum overlap
from PipelineRun start/end timestamps. #2890 - Cover concurrency limit changes: New e2e tests for raising, lowering, and removing a concurrency limit — verifying the queue reacts immediately without needing an unrelated event. #2890
- Assert the queue matches the cluster: New e2e test verifying the watcher survives parallel repository deletion and that queue state stays consistent with cluster state. #2890
📚 Documentation
- Remove deprecated profiling key callout: Removed migration guidance for the old profiling.enable key since it no longer works. #2852
⚙️ Chores
- Remove Tekton Hub support: Tekton Hub has been shut down. All TektonHub-specific code, configuration, tests, and documentation have been removed, leaving only Artifact Hub integration. #2855
- Remove Repository CR pipelinerun_status field: Eliminated the Status field from the Repository CR to stop informer cache churn on every PipelineRun completion. CLI commands now query PipelineRuns directly
via label selectors. #2841 - Replace paco.yaml inline scripts with paco-cli binary: Replaced ~950 lines of bash/jq/awk/Node.js across three Tekton steps with invocations of the compiled paco-cli binary. #2885
- Break Gitea e2e tests into focused files: Split the monolithic 42-test Gitea E2E file into 8 concern-grouped files (remote tasks, concurrency, YAML errors, etc.). #2889
- Split gitea_test.go unit tests: Refactored the 1,511-line file into focused files (status_test.go, repository_test.go). #2826
- Finish Repository.Status removal in e2e waits: Completed the refactoring to remove the deprecated Repository CR Status field from all E2E test wait helpers. #2835, #2789
- Add display names to Tekton pipeline steps: Added displayName fields to all steps for better readability in the Tekton UI. #2867
- Readd Go module updates in Dependabot: Added grouped Go module tracking to prevent excessive dependency PRs. #2844
- Add bitbucket cloud secret in e2e: Added TEST_BITBUCKET_CLOUD_WEBHOOK_SECRET for webhook validation testing. #2869
- Add provider logging guidance to AGENTS.md. #2836
- Delete gemini config from repo: Removed decommissioned Gemini code review configuration. #2862
- Use log lines for TestGithubGHEPullRequestGitCloneTask: Replaced sinceSecond with log lines to reduce test flakiness. #2872
- Fix Python lint errors: Fixed import ordering and timezone-naive datetime calls. #2886
- Dependency bumps: Updated go module dependencies #2900, k8s.io/client-go to 0.36.2 #2846, k8s.io/apiextensions-apiserver to v0.36.2 #2846, grpc to 1.82.1 #2873, go-dependencies group (5 updates) #2888,
go-dependencies group (15 updates) #2845, go-isatty #2864. - CI bumps: actions/checkout to 7.0.1 #2887, actions/setup-go to 7.0.0 #2863, fix team slug format in workflow #2880, skip commit validation on dependabot PRs #2845, ignore go-github and ghinstallation in
dependabot #2845. - Retry Gitea org/repo/hook creation on transient API errors: E2e test setup now retries transient Gitea API failures instead of failing immediately. #2890
Installation
To install this version you can install the release.yaml with kubectl for your platform :
Openshift
kubectl apply -f https://github.com/tektoncd/pipelines-as-code/releases/download/v0.50.0/release.yamlKubernetes
kubectl apply -f https://github.com/tektoncd/pipelines-as-code/releases/download/v0.50.0/release.k8s.yamlDocumentation
The documentation for this release is available here :
https://docs.pipelinesascode.com/v0.50.0
Changelog
- ea8ef1b: chore(deps): update go module dependencies (@theakshaypant)
- f9f1fe5: chore(hub): remove Tekton Hub support (@theakshaypant)
- f9e1a7a: chore: Break Gitea e2e tests down (@KMI1011)
- 717f163: chore: Readd Go module updates in Dependabot (@chmouel)
- 73b19d4: chore: add bitbucket cloud secret in e2e (@zakisk)
- 9a97ed2: chore: add display names to Tekton pipeline steps (@chmouel)
- 73cb521: chore: add provider logginf guidance to AGENTS.md (@theakshaypant)
- 85b606b: chore: bump k8s.io/apiextensions-apiserver to v0.36.2 (@theakshaypant)
- 5585618: chore: delete gemini config from repo (@zakisk)
- a054817: chore: refine paco code review prompt (@chmouel)
- 945c7bd: chore: use log lines for TestGithubGHEPullRequestGitCloneTask (@zakisk)
- fd5d7a0: ci(e2e): fix team slug format in workflow (@theakshaypant)
- f01a7e6: ci: bump actions/checkout in the github-actions group (@dependabot[bot])
- ad947f4: ci: bump actions/setup-go in the github-actions group (@dependabot[bot])
- 5d121ae: ci: bump github.com/mattn/go-isatty in the go-dependencies group (@dependabot[bot])
- 3bbaf67: ci: bump google.golang.org/grpc from 1.81.1 to 1.82.1 (@dependabot[bot])
- 7c6483e: ci: bump k8s.io/client-go in the go-dependencies group (@dependabot[bot])
- 3b3981b: ci: bump the go-dependencies group with 15 updates (@dependabot[bot])
- 7b88d2c: ci: bump the go-dependencies group with 5 updates (@dependabot[bot])
- 2c421e0: ci: ignore go-github and ghinstallation in dependabot (@chmouel)
- 0fe2198: ci: skip commit validation on dependabot PRs (@chmouel)
- 5438a1e: docs(profiling): remove deprecated key callout (@theakshaypant)
- a5b9155: feat(bitbucket-cloud): add HMAC webhook secret validation (@zakisk)
- 619e426: feat(watcher): add read-only queue debug endpoint (@chmouel)
- 19a8c89: feat(webhook): validate GitHub comment strategy setting (@zakisk)
- ad2dcdb: feat: Introduce Paco AI code review (@chmouel)
- 6e3f736: feat: capture container creation error messages in logs (@chmouel)
- 5f31427: feat: score review difficulty and other paco impro (@chmouel)
- f4dfe8e: fix(cli): set BB Cloud email in update-token (@theakshaypant)
- 4b34260: fix(cve): CVE-2026-33211 - upgrade github.com/tektoncd/pipeline to v1.14.1 (Claude Sonnet 4.6 (1M context) noreply@anthropic.com)
- 912f4e6: fix(cve): CVE-2026-42505 - update Go to 1.26.5 (@theakshaypant)
- 2a84139: fix(e2e): wait for push pipelinerun in gitea params test (@chmouel)
- f6a3916: fix(gitea): check write/admin permission instead of collaborator only (@zakisk)
- 5106a0e: fix(gitea): guard nil content in GetFileInsideRepo to avoid panic (@theakshaypant)
- d92a9a6: fix(github): query check runs for /retest (@theakshaypant)
- e264d7a: fix(github): recover fork PR re-runs when GitHub omits PR metadata (@chmouel)
- b328e04: fix(gitlab): handle branch creation without commits (@l-qing)
- 6f0098b: fix(gitlab): pin source lookups to event SHA (@l-qing)
- e270e68: fix(gitlab): verify write access before rotating token (@chmouel)
- c614e91: fix(lint): fix Python lint errors (@zakisk)
- d7afe8b: fix(logging): log sinker errors , emit event on repository config error (@aThorp96)
- 939d30a: fix(provider): always use log using Provider logger (@aThorp96)
- b89b22e: fix(provider): use provider logger in gitlab setClient (@theakshaypant)
- 9b243d4: fix(queue): release the slot only once the run started (@chmouel)
- d1e7b6c: fix(test): retry Gitea org/repo/hook creation on transient API errors (@chmouel)
- 2cc74bd: fix: Enable graceful shutdown for the controller listener (@chmouel)
- 85cad74: fix: bump knative.dev/pkg and semconv to fix otel schema panic (@chmouel)
- e309d1a: fix: detect and prevent nil pointer crashes (@chmouel)
- 9a63051: fix: expose metrics port 9090 for webhook (@khrm)
- 03ef45f: fix: guard queueMap and drop dead semaphore code (@chmouel)
- 612cd11: fix: keep the queue in sync with the cluster (@chmouel)
- c42a902: fix: populate timestamp fields on emitted k8s events (@theakshaypant)
- 3e62d21: refactor(e2e): finish Repository.Status removal in waits (@chmouel)
- 39271f3: refactor(e2e): remove reliance on Repository.Status in wait functions (@zakisk)
- 29c47b6: refactor: remove Repository CR pipelinerun_status field (@zakisk)
- 09fcc35: refactor: replace paco.yaml inline scripts with paco-cli binary (@zakisk)
- 2e845ef: refractor: split gitea_test.go into focused files (@KMI1011)
- 0ed8e25: test(e2e): assert concurrency limits are respected (@chmouel)
- 4ecc61e: test(e2e): assert the queue matches the cluster (@chmouel)
- 5be7d93: test(e2e): cover concurrency limit changes (@chmouel)