Actions: a concurrency: block prevents run CREATION — push/dispatch return 204 but no run is created
#799
Reference in New Issue
Block a user
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?
Summary
MokoGIT's Actions engine fails to create a run for any workflow that declares a top-level
concurrency:block. On push (and onworkflow_dispatch), the request returns 204/success but no run is ever created — the workflow is silently skipped. Removing theconcurrency:block makes the exact same workflow run normally.This is distinct from #798 (which was about the
.mokogit/workflows/path not being indexed at all). Here the path is indexed and other workflows in the same repo run fine on the same push; only the one(s) declaringconcurrency:are dropped.Impact
deploy-dev.yml/deploy-rc.yml/deploy-prod.yml) all ship with aconcurrency:block inTemplate-Go(the canonical sync source), so every Go repo's deploys silently stopped firing.Template-Goon every workflow sync, so a downstream repo that removes it locally gets it re-added and breaks again.Evidence (repo: MokoConsulting/mokoai)
Holding everything else constant and toggling only the
concurrency:block ondeploy-dev.yml:concurrency:blockdeploy-dev-mokoai-v2)Same pattern reproduced on
deploy-prod.yml: the01.01.00merge tomainwith the block present created 0 deploy-prod runs; after removing the block (PR mokoai#87) the nextmainpush created and completed a deploy-prod run.Reproduction
.mokogit/workflows/.concurrency:creates none.POST .../actions/workflows/<file>/dispatchesreturns 204 but also creates nothing.Diagnostic note
The REST tasks endpoint (
GET /api/v1/repos/{o}/{r}/actions/tasks) only lists started/completed runs — queued (0s) runs do not appear there, which makes this bug look like "nothing was created" even in cases where a run is merely queued. Confirm via the web Actions page (which shows 0s/queued entries) before concluding no run exists.Likely area
Gitea Actions run-creation path — evaluation of the
concurrencyexpression / group when scheduling a new run (the fork may be erroring or short-circuiting run creation when a concurrency group is declared, rather than queuing/cancelling as upstream does). Worth diffing the fork'sservices/actionsnotifier /jobparserconcurrency handling against upstream Gitea.Workaround applied (not a fix)
Removed the
concurrency:block fromdeploy-dev/rc/prod.ymlinTemplate-Go(PR MokoConsulting/Template-Go#18, merged) and in the affected downstream repo (mokoai). Each keeps a NOTE comment. Once this MokoGIT bug is fixed, theconcurrency:blocks should be restored template-wide (serialized deploys are desirable).Related: #798 (path indexing — separate root cause, same "no runs created" symptom).
Branch created:
feature/799-actions-a-concurrency-block-prevents-runRoot-cause analysis (source-level)
Traced this in the MokoGIT source. The bug is an incomplete migration of Actions concurrency from run-level to attempt-level — concurrency workflows enter a half-wired code path, so the run is created but never dispatched (it shows in the Actions UI at
0sand never executes; the REST.../actions/tasksendpoint only lists started/completed runs, which is why it looks like "no run created"). Workflows without aconcurrency:block skip this path entirely and run normally.The inconsistency (file : line)
models/migrations/v1_27/v331.go—AddActionRunAttemptModel: adds theaction_run_attempttable +action_run.latest_attempt_id, and intentionally DROPSaction_run.concurrency_group/action_run.concurrency_cancel(see its own comment: "intentionally removes the legacy run-level concurrency columns"). Concurrency is meant to live onaction_run_attemptnow.models/actions/run.go(ActionRun struct, ~L52-54) still declaresRawConcurrency/ConcurrencyGroup/ConcurrencyCancel. Because the model keeps those fields, xorm's startupSyncre-adds the columns the migration just dropped — a schema flip-flop, and a sign the model side wasn't updated with the migration.services/actions/run.go—InsertRun: builds anattempt := &ActionRunAttempt{...}(~L95), fills it viaEvaluateRunConcurrencyFillModel, callsPrepareToStartRunWithConcurrency(attempt)— but neverdb.Inserts the attempt. (The onlydb.Insert(..., attempt)in the tree is inrerun.go.) Soaction_run_attemptgets no row andrun.LatestAttemptIDstays0.services/actions/clear_tasks.go—shouldBlockRunByConcurrency/CancelPreviousJobsByRunConcurrencyoperate on attempt-level data (GetConcurrentRunAttemptsAndJobs→FindConcurrentRunAttemptsoveraction_run_attempt), which is empty because of #3.services/actions/job_emitter.go—checkRunConcurrency(~L172) still keys off run-levelrun.ConcurrencyGroup.So the implementation is split across both models (run-level and attempt-level) with the attempt row never persisted — mutually inconsistent, and only exercised when a
concurrency:block is present.Fix direction (pick one, applied consistently)
InsertRunmustdb.InserttheActionRunAttemptand setrun.LatestAttemptID; move the remaining run-level reads (job_emitter.checkRunConcurrency) onto the attempt; and drop the now-deadConcurrencyGroup/ConcurrencyCancelfields from theActionRunmodel so the schema stops flip-flopping. ORaction_runcolumns in v331, and remove the attempt-basedshouldBlock/Cancelpaths.Confirming the exact failing op
Code analysis points to the created-but-not-dispatched path above. Pinning whether it fails at insert-time (SQL) vs emit-time (no dispatch) needs one of: the
mokogitcontainer error log around a concurrency-triggered push, or a build+test repro — both require host/build access I don't have in this context.Interim mitigation (already shipped)
concurrency:blocks removed fromdeploy-dev/rc/prodin Template-Go (MokoConsulting/Template-Go#18, merged) and downstream (mokoai), so deploys fire again. These should be restored once this is fixed.Update — appears RESOLVED in
stable-439, and my earlier root-cause was wrongRe-tested against the currently deployed prod
mokogit(stable-439-g81d065b9bb, restarted ~06:26 UTC 2026-07-17) using a throwaway repo, and the bug no longer reproduces:concurrency:block on both.gitea/workflows/and.mokogit/workflows/paths..gitea-path concurrency runs executed tostatus=success(verified inaction_runfor the test repo). The.mokogit-path concurrency run was likewise created and queued.So run-creation with a
concurrency:block works onstable-439. Whatever shipped in that build fixed it.Correction to my earlier comment: the "incomplete attempt-level refactor / attempt never inserted" hypothesis was not the cause.
action_run_attemptstays empty (ATTEMPTS=0) even for runs that complete successfully, so an empty attempt table is normal, not the bug. Please disregard that root-cause analysis.Suggested follow-ups
stable-439changed and close this if satisfied.deploy-dev/rc/prodin Template-Go#18 and downstream) can now be reverted to restore serialized deploys, since concurrency works again.