Adds a shared .gitea/scripts/komodo-deploy.sh that calls the Komodo /execute/DeployStack API after the image is pushed, then polls /read/GetUpdate until the deploy completes. A push webhook cannot do this correctly: it fires before the image exists in the registry, so Komodo would redeploy the previous :latest. - docker.yml deploys stack 'qbit-maid' (required) - docker-dev.yml deploys vars.KOMODO_STACK_DEV, skipped when unset
5.0 KiB
Auto-deploy qbit-maid to Komodo
Status: implemented on branch dev-komodo-deploy.
Komodo instance: https://k.jonb.io · Stack: qbit-maid
What this does
Every successful image build now triggers a Komodo stack deploy:
| Workflow | Trigger | Image tag | Komodo target |
|---|---|---|---|
.gitea/workflows/docker.yml |
push to main |
:latest |
stack qbit-maid |
.gitea/workflows/docker-dev.yml |
push to dev* |
:dev |
vars.KOMODO_STACK_DEV (skipped if unset) |
The deploy step runs after Build and push, so the new image is already in
the registry when Komodo pulls it. If the deploy fails, the workflow goes red.
Why not just use the existing webhook?
You already have webhooks configured, and this is the important part: a push webhook on the stack does not reliably deploy new container builds.
The webhook fires on git push. That happens before Gitea Actions has built
and pushed the image — the build takes minutes. So Komodo receives the deploy
request while the registry still holds the previous :latest. It pulls that,
deploys it, and reports success. The new code never lands until something else
triggers a second deploy.
The ordering is the whole problem, and a webhook cannot fix it because the webhook is tied to the push event, not the build event.
So the workflow calls the Komodo API directly instead:
POST https://k.jonb.io/execute/DeployStack
x-api-key: <key>
x-api-secret: <secret>
{"stack": "qbit-maid"}
This is the same call the Komodo UI makes when you click Deploy, just triggered from CI at the right moment.
What to do with the existing webhook
If you have a stack webhook pointing at
/listener/github/stack/qbit-maid/deploy, it is now redundant and will cause a
second, useless deploy on every push (deploying the stale image). Remove it
in Gitea → repo Settings → Webhooks.
Keep webhooks only if you later point them at a Procedure rather than the stack — see "Using a Procedure" below.
One Komodo setting to verify
DeployStack runs docker compose pull before up only when the stack has
auto_pull enabled. It defaults to true, so this is probably already fine —
but if it has been turned off, deploys will silently reuse the cached image and
you will see no change.
Check in the Komodo UI: stack qbit-maid → Config → Auto Pull should be on.
Setup (one-time)
1. Komodo API key
Komodo → Settings → API Keys → New. The key's user needs Execute
permission on the qbit-maid stack. Copy the key and secret — the secret is
shown once.
2. Gitea secrets
Repo → Settings → Actions → Secrets:
| Name | Value |
|---|---|
KOMODO_URL |
https://k.jonb.io |
KOMODO_API_KEY |
from step 1 |
KOMODO_API_SECRET |
from step 1 |
3. Dev stack (optional)
Repo → Settings → Actions → Variables:
| Name | Value |
|---|---|
KOMODO_STACK_DEV |
your dev stack name, e.g. qbit-maid-dev |
If this variable is unset, the dev workflow logs KOMODO_TARGET is not set - skipping Komodo deploy and still passes. Dev builds never fail because of a
missing dev stack.
The deploy script
.gitea/scripts/komodo-deploy.sh is shared by both workflows. It:
- Skips cleanly if
KOMODO_TARGETis empty (unlessKOMODO_REQUIRED=true). - POSTs to
/execute/DeployStack(or/execute/RunProcedure). - Fails on any non-200, printing Komodo's error body.
- Polls
/read/GetUpdateuntil the update reachesComplete, then checkssuccessand prints the Komodo log on failure.
The execute endpoint returns immediately with an Update object — a 200 means
"queued", not "deployed". That is why step 4 exists.
Tunable via env: KOMODO_TARGET_TYPE (stack/procedure), KOMODO_WAIT
(default true), KOMODO_WAIT_TIMEOUT (default 600s), KOMODO_WAIT_INTERVAL
(default 10s).
Using a Procedure instead of a direct stack deploy
If you later wrap the deploy in a Komodo Procedure (deploy + healthcheck + notification, say), point the workflow at it instead of editing the script:
env:
KOMODO_TARGET_TYPE: 'procedure'
KOMODO_TARGET: 'qbit-maid deploy'
RunProcedure takes {"procedure": "<name>"} and returns the same Update
shape, so the polling logic is unchanged.
Testing
Verified locally against a mock of the Komodo API — 12 checks covering the success path, deploy failure, bad credentials (401), unknown stack (400), empty target skip, required-but-empty target, unreachable host, and the procedure target type. All pass.
Live verification still needed:
- Push
dev-komodo-deploy— it matchesdev*, sodocker-dev.ymlruns. WithKOMODO_STACK_DEVunset it will skip the deploy; set the variable first if you want to exercise it. - Merge to
mainand confirm the Komodo UI shows a newDeployStackupdate forqbit-maid, operator = the API key's user. - Confirm the running container picked up the new image digest.
Rollback
Delete the Deploy to Komodo step from the workflow(s). Nothing on the Komodo
side is modified by CI beyond triggering a deploy.