Deploy from CI
The CLI is a thin HTTP client: it talks to a Kaio server and nothing else. A pipeline therefore needs no checkout of Kaio and no toolchain, just the published image with its entrypoint overridden.
docker run --rm --network host -e KAIO_ADDR \ --entrypoint kaio-cli ghcr.io/rgaidot/kaio:latest healthGitHub Actions
Section titled “GitHub Actions”name: Deployon: push: branches: [main]
jobs: deploy: runs-on: self-hosted env: KAIO_ADDR: ${{ secrets.KAIO_ADDR }} KAIO: >- docker run --rm --network host -e KAIO_ADDR -v ${{ github.workspace }}:/w -w /w --entrypoint kaio-cli ghcr.io/rgaidot/kaio:latest steps: - uses: actions/checkout@v4
- name: Refuse to deploy to a server that is not answering run: $KAIO health
- name: Deploy run: $KAIO stack deploy blog compose.yml --env-file .env.ci
- name: Fail if the stack did not come up run: | $KAIO --json status | jq -e --arg s blog ' [.[] | select(.stack == $s and .state == "running")] | length > 0 'GitLab CI
Section titled “GitLab CI”deploy: stage: deploy image: ghcr.io/rgaidot/kaio:latest variables: KAIO_ADDR: $KAIO_ADDR script: - kaio-cli health - kaio-cli stack deploy blog compose.yml --env-file .env.ci only: - mainThe image ships both binaries, so a job that runs in it calls kaio-cli
directly. The entrypoint only needs overriding when the image is invoked with
docker run.
What the steps buy you
Section titled “What the steps buy you”health first. A server that is down fails the job before anything is
written, instead of halfway through a deploy.
stack deploy is idempotent. It rewrites the compose file, recreates the
containers and records a new version, so re-running the pipeline on an unchanged
file is safe. A failed compose up restores the previous version on its own and
the step fails, so a bad commit leaves the last working stack running.
Verify what you deployed. stack deploy returning 0 means the deploy was
accepted, not that the containers stayed up. The --json status check above
reads the containers back and fails the job if none of the stack’s are running.
Rolling it across a cluster
Section titled “Rolling it across a cluster”The control plane forwards to any node in its registry, so the pipeline keeps talking to one address and names the node it wants:
kaio-cli --json node ls | jq -r '.[] | select(.status == "online") | .name' - name: Deploy on every node that answers run: | for node in $($KAIO --json node ls | jq -r '.[] | select(.status=="online") | .name'); do echo "deploying on $node" $KAIO node "$node" run stack deploy blog compose.yml doneA node removed from the registry drops out of the list and loses its route, so a decommissioned server cannot be deployed to by a pipeline that has not been updated.
Nothing schedules this for you. The loop is the whole of it, a node that was offline when the pipeline ran is skipped, and there is no rollback across hosts: each server deploys or restores its own previous version independently. If you need all-or-nothing across a cluster, that belongs in your pipeline, not in Kaio.
See Multiple servers for how servers join in the first place.
Other things worth a job
Section titled “Other things worth a job”# Fail the build when a stack has a pending image updatekaio-cli --json stack ls | jq -e 'map(select(.update_available)) | length == 0'
# Fail on any critical CVE in a scanned imagekaio-cli --json image ls | jq -e '[.[].scan.summary.critical // 0] | add == 0'
# Report nodes that stopped answeringkaio-cli --json node ls | jq -r '.[] | select(.status != "online") | "\(.name) \(.last_error)"'Related
Section titled “Related”Kaio, built by Régis Gaidot