Skip to main content

GitHub Actions Reference

kindling ships two reusable composite actions that replace 15+ lines of signal-file boilerplate with a single uses: step. These actions live in the kindling repo under .github/actions/ and are referenced as:

kindling-sh/kindling/.github/actions/kindling-build@main
kindling-sh/kindling/.github/actions/kindling-deploy@main

kindling-build

Build and push a container image via the Kaniko build-agent sidecar.

Dockerfile required

This action runs the Dockerfile found in the build context directory as-is using Kaniko. It does not generate or modify Dockerfiles. Each service must have a working Dockerfile that builds successfully on its own (e.g. docker build .). If it doesn't build locally, it won't build in kindling.

Inputs

InputRequiredDefaultDescription
nameUnique build name (used for signal files: /builds/<name>.*)
contextPath to the build context directory
imageFull image reference (registry/name:tag)
exclude""tar --exclude patterns (space-separated, e.g. "./ui ./.git")
dockerfile""Path to Dockerfile relative to build context (e.g. api/Dockerfile). If omitted, Kaniko uses the default Dockerfile in the context root.
timeout300Max seconds to wait for the build to complete

What it does

  1. Creates a tarball of the build context at /builds/<name>.tar.gz (with optional --exclude patterns)
  2. Writes the target image to /builds/<name>.dest
  3. If dockerfile is specified, writes the path to /builds/<name>.dockerfile
  4. Touches /builds/<name>.request to trigger the Kaniko sidecar
  5. Polls for /builds/<name>.done (up to timeout seconds)
  6. Checks /builds/<name>.exitcode — exits non-zero on failure

Usage

- name: Build my-app
uses: kindling-sh/kindling/.github/actions/kindling-build@main
with:
name: my-app
context: ${{ github.workspace }}
image: "registry:5000/my-app:${{ github.sha }}"

With exclusions

- name: Build API (exclude UI directory)
uses: kindling-sh/kindling/.github/actions/kindling-build@main
with:
name: my-api
context: ${{ github.workspace }}
image: "registry:5000/my-api:${{ github.sha }}"
exclude: "./ui ./.git ./node_modules"

With custom Dockerfile path

When the Dockerfile is not at the context root (common in monorepos or projects using docker-compose with context: . and dockerfile: api/Dockerfile):

- name: Build API (Dockerfile in subdirectory)
uses: kindling-sh/kindling/.github/actions/kindling-build@main
with:
name: my-api
context: ${{ github.workspace }}
image: "registry:5000/my-api:${{ github.sha }}"
dockerfile: "api/Dockerfile"

kindling-deploy

Deploy a DevStagingEnvironment CR via the build-agent sidecar.

Inputs

InputRequiredDefaultDescription
nameDSE metadata.name (typically <actor>-<service>)
imageContainer image reference
portContainer port (string)
labels""Extra labels as YAML block
env""Extra env vars as YAML block
dependencies""Dependencies as YAML block
ingress-host""Ingress hostname (omit to skip ingress)
ingress-classnginxIngress class name
health-check-path/healthzHTTP health check path
replicas1Number of replicas
service-typeClusterIPService type
waittrueWait for deployment rollout
wait-timeout180sRollout wait timeout

What it does

  1. Generates a complete DevStagingEnvironment YAML manifest from the inputs
  2. Writes it to /builds/<name>-dse.yaml
  3. Touches /builds/<name>-dse.apply to trigger sidecar kubectl apply
  4. Waits for the sidecar to confirm the apply succeeded
  5. Optionally waits for the Deployment rollout to complete

Basic usage

- name: Deploy my-app
uses: kindling-sh/kindling/.github/actions/kindling-deploy@main
with:
name: "${{ github.actor }}-my-app"
image: "registry:5000/my-app:${{ github.sha }}"
port: "8080"
ingress-host: "${{ github.actor }}-my-app.localhost"

With dependencies

- name: Deploy with Postgres + Redis
uses: kindling-sh/kindling/.github/actions/kindling-deploy@main
with:
name: "${{ github.actor }}-my-app"
image: "registry:5000/my-app:${{ github.sha }}"
port: "8080"
ingress-host: "${{ github.actor }}-my-app.localhost"
dependencies: |
- type: postgres
version: "16"
- type: redis

With env vars

- name: Deploy with environment variables
uses: kindling-sh/kindling/.github/actions/kindling-deploy@main
with:
name: "${{ github.actor }}-my-ui"
image: "registry:5000/my-ui:${{ github.sha }}"
port: "80"
health-check-path: "/"
ingress-host: "${{ github.actor }}-my-ui.localhost"
env: |
- name: API_URL
value: "http://${{ github.actor }}-my-api:8080"
- name: NODE_ENV
value: "development"

Complete workflow example

A full workflow using both actions:

name: Dev Deploy
on:
push:
branches: [main]

jobs:
build-and-deploy:
runs-on: [self-hosted, "${{ github.actor }}"]
env:
TAG: ${{ github.sha }}
steps:
- uses: actions/checkout@v4

- name: Clean builds directory
run: rm -f /builds/*

# ── Build ──────────────────────────────────────────────
- name: Build API image
uses: kindling-sh/kindling/.github/actions/kindling-build@main
with:
name: my-api
context: ${{ github.workspace }}
image: "registry:5000/my-api:${{ env.TAG }}"
exclude: "./ui"

- name: Build UI image
uses: kindling-sh/kindling/.github/actions/kindling-build@main
with:
name: my-ui
context: "${{ github.workspace }}/ui"
image: "registry:5000/my-ui:${{ env.TAG }}"

# ── Deploy ─────────────────────────────────────────────
- name: Deploy API
uses: kindling-sh/kindling/.github/actions/kindling-deploy@main
with:
name: "${{ github.actor }}-my-api"
image: "registry:5000/my-api:${{ env.TAG }}"
port: "8080"
ingress-host: "${{ github.actor }}-my-api.localhost"
dependencies: |
- type: postgres
version: "16"
- type: redis

- name: Deploy UI
uses: kindling-sh/kindling/.github/actions/kindling-deploy@main
with:
name: "${{ github.actor }}-my-ui"
image: "registry:5000/my-ui:${{ env.TAG }}"
port: "80"
health-check-path: "/"
ingress-host: "${{ github.actor }}-my-ui.localhost"
env: |
- name: API_URL
value: "http://${{ github.actor }}-my-api:8080"

Troubleshooting

Build times out

Increase the timeout:

with:
timeout: "600" # 10 minutes

Deploy apply fails

Check the output for:

  • Invalid YAML indentation
  • Missing required fields
  • Image not found in registry

Rollout doesn't complete

Check pod events:

kubectl describe pod -l app.kubernetes.io/name=<name>
kubectl logs -l app.kubernetes.io/name=<name>

Common causes:

  • Image pull errors (image not pushed to registry:5000)
  • Health check failing (wrong path or port)
  • Dependency not ready (database still starting)