Renovate/Gitea merges PR while required-less commit status is PENDING (main has no branch protection) #188

Closed
opened 2026-06-02 05:40:52 +00:00 by goern · 1 comment
goern commented 2026-06-02 05:40:52 +00:00 (Migrated from codeberg.org)

Summary

PR #187 (Renovate docker-digest bump) merged at 02:18:05 while the Tekton build-and-test task was still running. The merge cancelled the PipelineRun, so build-and-test reported TaskRunCancelled — it did not fail on merits, it was killed by the merge. Merge came first (02:18:05), cancellation 5s later (02:18:10).

Timeline (2026-06-02)

Time Event
02:16:29 Renovate opens PR #187
02:16:49 PaC posts pending commit status for both contexts (code-scans, on-pull-request)
02:17:31 code-scanssuccess
02:18:05 PR merged (combined status still pendingon-pull-request not done)
02:18:10 on-pull-requestcancelled (build-and-test TaskRunCancelled)

Full commit-status history on head 7279457:

02:16:49  pending    | op1st Pipelines as Code / forgejo-mcp-code-scans
02:16:49  pending    | op1st Pipelines as Code / forgejo-mcp-on-pull-request
02:17:31  success    | op1st Pipelines as Code / forgejo-mcp-code-scans
02:18:10  cancelled  | op1st Pipelines as Code / forgejo-mcp-on-pull-request

Root cause — main has zero branch protection

GET /repos/goern/forgejo-mcp/branch_protections → []

No required status checks. At merge time the combined commit status was pending (on-pull-request pending since 02:16:49), yet the merge went through. Because no check is required, the pending status is non-blocking to the merge path.

Correction: an earlier draft of this issue claimed "PaC posts no pending status at pipeline start." That is false — the status history above shows PaC did post a pending status at 02:16:49, and PaC source (openshift-pipelines/pipelines-as-code pkg/provider/gitea/gitea.go) sets forgejo.StatusPending on in_progress. The single real hole is the missing branch protection.

Open question (does not change the fix): which path ignored the pending status —
(a) Renovate client-side merge not treating the ambient pending status as blocking when no check is required, or
(b) Gitea/Forgejo native scheduled auto-merge, which has no definition of "green" without branch protection so merges immediately.
Both are downstream of the missing required checks; pinning it needs Renovate run logs.

Fix

Add branch protection on main requiring both PaC contexts:

curl -X POST -H "Authorization: token $CODEBERG_TOKEN" \
  -H "Content-Type: application/json" \
  https://codeberg.org/api/v1/repos/goern/forgejo-mcp/branch_protections \
  -d '{
    "rule_name": "main",
    "enable_status_check": true,
    "status_check_contexts": [
      "op1st Pipelines as Code / forgejo-mcp-code-scans",
      "op1st Pipelines as Code / forgejo-mcp-on-pull-request"
    ]
  }'

A required check that is pending or absent makes the branch non-mergeable, so the merge waits until both contexts are present and success — for both Renovate and Gitea native auto-merge.

Acceptance

  • main branch protection requires both PaC status check contexts with enable_status_check=true.
  • A PR with a pending or absent required check is not mergeable, including by Renovate automerge.
  • Verified by re-running a Renovate digest PR and confirming it waits for build-and-test before merge.

Tracked in beads as forgejo-mcp-f6h (P0 bug). Follow-up feature: forgejo-mcp-uc6 (branch-protection management tools + resource-templates).

## Summary PR #187 (Renovate docker-digest bump) merged at `02:18:05` while the Tekton `build-and-test` task was still running. The merge cancelled the PipelineRun, so `build-and-test` reported `TaskRunCancelled` — it did **not** fail on merits, it was killed by the merge. Merge came first (02:18:05), cancellation 5s later (02:18:10). ## Timeline (2026-06-02) | Time | Event | |------|-------| | 02:16:29 | Renovate opens PR #187 | | 02:16:49 | PaC posts **pending** commit status for both contexts (`code-scans`, `on-pull-request`) | | 02:17:31 | `code-scans` → **success** | | **02:18:05** | **PR merged** (combined status still **pending** — `on-pull-request` not done) | | 02:18:10 | `on-pull-request` → **cancelled** (`build-and-test` TaskRunCancelled) | Full commit-status history on head `7279457`: ``` 02:16:49 pending | op1st Pipelines as Code / forgejo-mcp-code-scans 02:16:49 pending | op1st Pipelines as Code / forgejo-mcp-on-pull-request 02:17:31 success | op1st Pipelines as Code / forgejo-mcp-code-scans 02:18:10 cancelled | op1st Pipelines as Code / forgejo-mcp-on-pull-request ``` ## Root cause — `main` has zero branch protection ``` GET /repos/goern/forgejo-mcp/branch_protections → [] ``` No required status checks. At merge time the combined commit status was **pending** (`on-pull-request` pending since 02:16:49), yet the merge went through. Because no check is *required*, the pending status is non-blocking to the merge path. > **Correction:** an earlier draft of this issue claimed "PaC posts no pending status at pipeline start." That is false — the status history above shows PaC *did* post a pending status at 02:16:49, and PaC source (`openshift-pipelines/pipelines-as-code` `pkg/provider/gitea/gitea.go`) sets `forgejo.StatusPending` on `in_progress`. The single real hole is the missing branch protection. **Open question (does not change the fix):** which path ignored the pending status — (a) Renovate client-side merge not treating the ambient pending status as blocking when no check is required, or (b) Gitea/Forgejo native scheduled auto-merge, which has no definition of "green" without branch protection so merges immediately. Both are downstream of the missing required checks; pinning it needs Renovate run logs. ## Fix Add branch protection on `main` requiring both PaC contexts: ```bash curl -X POST -H "Authorization: token $CODEBERG_TOKEN" \ -H "Content-Type: application/json" \ https://codeberg.org/api/v1/repos/goern/forgejo-mcp/branch_protections \ -d '{ "rule_name": "main", "enable_status_check": true, "status_check_contexts": [ "op1st Pipelines as Code / forgejo-mcp-code-scans", "op1st Pipelines as Code / forgejo-mcp-on-pull-request" ] }' ``` A required check that is pending or absent makes the branch non-mergeable, so the merge waits until both contexts are present and `success` — for both Renovate and Gitea native auto-merge. ## Acceptance - `main` branch protection requires both PaC status check contexts with `enable_status_check=true`. - A PR with a pending or absent required check is not mergeable, including by Renovate automerge. - Verified by re-running a Renovate digest PR and confirming it waits for `build-and-test` before merge. --- Tracked in beads as `forgejo-mcp-f6h` (P0 bug). Follow-up feature: `forgejo-mcp-uc6` (branch-protection management tools + resource-templates).
goern commented 2026-06-02 05:52:29 +00:00 (Migrated from codeberg.org)

Fixed — branch protection applied

Created branch protection rule on main (HTTP 201, verified):

rule_name:             main
enable_status_check:   true
status_check_contexts:
  - op1st Pipelines as Code / forgejo-mcp-code-scans
  - op1st Pipelines as Code / forgejo-mcp-on-pull-request

A pending or absent required check now makes the branch non-mergeable, so neither Renovate nor Gitea native auto-merge can merge before both PaC pipelines report success. This closes the merge-while-pending gap that sank PR #187.

Verify on next Renovate digest PR: the PR should sit unmergeable until build-and-test (the on-pull-request context) goes green, instead of merging at the first cron tick.

Follow-up: forgejo-mcp-uc6 — add MCP tools + forgejo:// resource-templates to manage branch protection, so this config is visible/enforceable through the server itself.

Closing as fixed.

## Fixed — branch protection applied Created branch protection rule on `main` (HTTP 201, verified): ``` rule_name: main enable_status_check: true status_check_contexts: - op1st Pipelines as Code / forgejo-mcp-code-scans - op1st Pipelines as Code / forgejo-mcp-on-pull-request ``` A pending or absent required check now makes the branch non-mergeable, so neither Renovate nor Gitea native auto-merge can merge before both PaC pipelines report `success`. This closes the merge-while-pending gap that sank PR #187. **Verify on next Renovate digest PR:** the PR should sit unmergeable until `build-and-test` (the `on-pull-request` context) goes green, instead of merging at the first cron tick. Follow-up: `forgejo-mcp-uc6` — add MCP tools + `forgejo://` resource-templates to manage branch protection, so this config is visible/enforceable through the server itself. Closing as fixed.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
agentic-forges/forgejo-mcp#188
No description provided.