[CI] push-to-main workflow runs fail fast (~50s) while pull_request runs pass #174
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Observed throughout the v3.4.0 merge sequence (2026-07-16): the
pull_request-event CI runs pass reliably (full 5–9 min runs, e.g. run #3518 for #86 = success in 9m22s), but thepush-event runs triggered when a PR merges intomainfail fast, in ~46–50s. This is consistent, not random, and it predates the v3.4.0 work — the post-merge run for #87 (b4e0482) failed the same way at 1m20s. Several Renovate dependency PRs also failed in the same window.Because
pull_requestruns test the branch merged with main and those are green, the integrated code onmainis believed healthy; this appears to be a push-event/runner configuration issue, not a code defect. But it meansmain's status badge/history shows red and any automation keyed off push-run status is unreliable.Why it matters
mainhistory obscures a genuine future breakage.merge-when-checks-succeedauto-merge became unreliable, forcing manual re-triggers and admin force-merges during v3.4.0.Investigate
secrets,forge.token, or apull_request-only context value that is empty/absent onpush? (e.g. a checkout token, a registry login, or a${{ github.event.pull_request.* }}reference evaluated on push.)concurrencyin.forgejo/workflows/ci.yml— confirmcancel-in-progressisn't turning a superseded push run into a "failure" rather than "cancelled".mainand watching the run live.Acceptance
push-to-mainCI runs pass green (or the workflow is corrected/split so push runs are meaningful).mainrun is green end-to-end (frontend, backend+migrations, bot, lint, docker build).Filed as a v3.4.0 follow-up: during that milestone, docs/config-only PRs and one fully-dev-verified code PR (#96) were force-merged past these flaky push checks after independent dev-server verification.
Picking this up. Starting with: (1) the outcome of a
workflow_dispatchrun onmain(different trigger thanpush— tells us if it's push-specific), (2) reading a failed push run's job/step breakdown, and (3) a no-op commit tomainto reproduce live.Investigation findings
Confirmed
mainis green. Aworkflow_dispatchrun ofci.ymlon the currentmainSHA (cd765b6) passed the full pipeline (frontend, backend+migrations, bot, lint, docker) in 3m16s (run #3528). So all of v3.4.0 is validated green — the red push history is not a code defect.pull_requestCI works and remains the real merge gate (every completed PR run in the v3.4.0 sequence passed).Root cause is push-event-specific — NOT resource contention (hypothesis corrected)
I initially suspected the failures were runner starvation during the v3.4.0 merge burst (delegates hammering the dev host). Reproduction disproved that: I pushed a no-op empty commit to
mainunder fully idle load (cae8801, run #454) and it failed in 10 seconds — far too fast for any job to execute. A 10s failure onpushwhileworkflow_dispatchon essentially identical content passes means the failure is at scheduling/startup for thepushevent specifically, independent of load.Data points:
workflow_dispatch(main)cd765b6pull_requestpush→ mainf520ad5,73cc6d2push→ main (no-op, idle)cae8801push→ maincd765b6ci-CI-refs/heads/mainand cancelled it)Separate, unrelated: Renovate dep PRs genuinely fail
pydantic@2.13.4,pydantic-core@2.47.0,react-router-dom@7.18.1PR runs fail (1m30s–3m, i.e. real job execution) even under idle load — those are genuine dependency-incompatibility failures, not this bug. Worth a separate look.Blocked on observability
I could not pin the exact failing step: the Forgejo Actions log API 404s here, the run web page is JS-rendered (WebFetch gets only the shell), and the act_runner container is on neither Docker host I can reach (the Forgejo server is on 10.1.1.7; the runner lives elsewhere). Pinning the root cause needs runner/Forgejo-admin log access.
Recommended next steps (need runner/admin access)
cae8801) — a 10s push failure is almost certainly a workflow-parse/context error or a runner label/registration rule that rejectspush-on-main, evaluated before jobs start.pushvsworkflow_dispatchevent payloads for the same ref; check repo/org Actions settings / branch rulesets for anything restricting the default branch on push.concurrencyblock — on bothpushandworkflow_dispatch,github.ref=refs/heads/main(same group); confirmcancel-in-progressisn't mislabeling cancellations as failures (we saw one genuine "cancelled").Interim mitigation
Until fixed, treat PR-event CI as the gate (it works) and, for a post-merge green signal on
main, trigger aworkflow_dispatchrun (as done here). Leaving this issue open — diagnosis complete, fix needs runner-side access.Note: an empty no-op commit (
cae8801, "ci: no-op commit to reproduce…") was pushed tomainfor the reproduction; it's harmless and can be left or dropped.Resolved ✅
Root cause: the
backendjob'spostgres:16service publishedports: - 5432:5432, binding 5432 on the runner host — which already runs other Postgres containers on 5432. The service container failed to start (Bind for 0.0.0.0:5432 failed: port is already allocated) before any test ran, surfacing as the fast push-run failure. It presented as "push fails / PR passes" flakiness because host-port availability is a race (whichever run happened to hit an already-bound 5432 died).Fix: #177 removed the host-port mapping. It was dead weight — the job reaches the DB by its network alias (
postgres:5432viaDATABASE_URL), never the host.Confirmed: after the fix, the push→
mainrun (#456,51c102d) executed the full pipeline instead of dying at ~10s, and is now green (a single unrelated component failed transiently and passed on retry). The 5432 collision is gone.Takeaway for future: service definitions in
ci.ymlshould not publishports:to the runner host on a shared/multi-tenant runner — reach services by their network alias instead.(Note: the reproduction left one harmless empty commit
cae8801onmain; can be left or dropped.)Closing.