Skip to content

This tutorial walks you through setting up CI/CD with Kizuna Actions. The workflow syntax is GitHub Actions-compatible, so existing workflows can migrate with minimal changes.

Prerequisites

  • A Kizuna repository with code to build/test
  • Basic familiarity with YAML
  • A project with a test suite (we'll use Node.js as an example)

Step 1: Create Your First Workflow

Create the Workflow File

Kizuna Actions reads workflow files from .kizuna/workflows/:

bash
mkdir -p .kizuna/workflows

Create .kizuna/workflows/ci.yml:

yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Check coverage
        run: npm run test:coverage

Commit and Push

bash
# With Jujutsu
jj describe -m "Add CI workflow"
jj git push

# With Git
git add .kizuna/workflows/ci.yml
git commit -m "Add CI workflow"
git push

The pipeline triggers automatically on push.

Step 2: View Pipeline Results

In the Web UI

  1. Go to your repository > Pipelines tab
  2. You'll see the running (or completed) pipeline
  3. Click on it to see:
    • Job list — each job and its status
    • Step logs — click a step to see its output
    • Timing — how long each step took

On Pull Requests

When a PR triggers CI:

  • Status checks appear at the bottom of the PR
  • Green checkmark = passed, Red X = failed
  • Click "Details" to see the full log

Via CLI

bash
# Coming soon
kz pipeline list --repo my-team/my-project
kz pipeline logs --repo my-team/my-project --run 42

Step 3: Add a Build Matrix

Test across multiple versions or platforms:

yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

      - run: npm ci
      - run: npm test

This creates three parallel jobs, one for each Node.js version.

Step 4: Add Secrets

Store sensitive values like API keys securely.

Add a Secret

  1. Go to Repository Settings > Secrets
  2. Click New Secret
  3. Enter:
    • Name: DEPLOY_TOKEN
    • Value: Your secret value
  4. Click Save

Use Secrets in Workflows

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: |
          curl -X POST https://api.example.com/deploy \
            -H "Authorization: Bearer $DEPLOY_TOKEN"

Security: Secrets are masked in logs and never exposed in PR builds from forks.

Step 5: Multi-Stage Pipeline

Create a pipeline with build, test, and deploy stages:

yaml
name: Build, Test & Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm test

  build:
    needs: [lint, test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run build

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/

  deploy-staging:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/

      - name: Deploy to staging
        env:
          DEPLOY_TOKEN: ${{ secrets.STAGING_DEPLOY_TOKEN }}
        run: |
          echo "Deploying to staging..."
          # Your deployment script here

  deploy-production:
    needs: deploy-staging
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/

      - name: Deploy to production
        env:
          DEPLOY_TOKEN: ${{ secrets.PROD_DEPLOY_TOKEN }}
        run: |
          echo "Deploying to production..."
          # Your deployment script here

Pipeline Flow

lint ──┐
       ├──> build ──> deploy-staging ──> deploy-production
test ──┘
  • lint and test run in parallel
  • build waits for both to pass
  • deploy-staging runs only on main branch
  • deploy-production runs after staging succeeds

Step 6: Add Policy Gates (Optional)

Use Kizuna's policy engine to gate deployments:

yaml
  deploy-production:
    needs: deploy-staging
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - name: Check deployment policy
        run: |
          kz policy check \
            --action "deploy.production" \
            --resource "${{ github.repository }}" \
            --context '{"branch": "${{ github.ref_name }}", "actor": "${{ github.actor }}"}'

      - name: Deploy
        run: echo "Deploying..."

If the policy check fails (exit code 1), the deployment is blocked.

Step 7: Set Up Self-Hosted Runners (Optional)

For faster builds or specialized hardware:

Register a Runner

  1. Go to Organization Settings > Runners
  2. Click New Runner
  3. Follow the setup instructions for your platform:
bash
# Download runner
curl -O https://kizuna.yourcompany.com/runner/download/linux-amd64
chmod +x kizuna-runner

# Configure
./kizuna-runner configure \
  --url https://kizuna.yourcompany.com \
  --token RUNNER_REGISTRATION_TOKEN \
  --name my-runner \
  --labels gpu,linux

# Start
./kizuna-runner start

Use in Workflows

yaml
jobs:
  ml-training:
    runs-on: [self-hosted, gpu]
    steps:
      - uses: actions/checkout@v4
      - run: python train.py

Step 8: Require CI in Branch Protection

Make CI mandatory for merges:

  1. Go to Repository Settings > Branch Protection
  2. Edit the main branch rule
  3. Under Required Status Checks, add:
    • CI / lint
    • CI / test
    • CI / build
  4. Save

Now PRs cannot merge unless all CI checks pass.

Common Workflow Patterns

Docker Build and Push

yaml
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build and push
        run: |
          docker build -t kizuna.yourcompany.com/my-team/my-app:${{ github.sha }} .
          docker push kizuna.yourcompany.com/my-team/my-app:${{ github.sha }}

Scheduled Builds

yaml
on:
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM UTC

jobs:
  nightly:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test:e2e

Conditional Steps

yaml
steps:
  - name: Deploy docs
    if: contains(github.event.head_commit.message, '[docs]')
    run: npm run deploy:docs

Troubleshooting

Pipeline Not Triggering

  • Verify the workflow file is in .kizuna/workflows/ (not .github/workflows/)
  • Check the on: trigger matches your event (push, pull_request, etc.)
  • Ensure the YAML syntax is valid

Job Fails with "Runner Not Found"

  • For ubuntu-latest: ensure the Kizuna instance has cloud runners configured
  • For self-hosted: verify the runner is online in Settings > Runners

Secrets Not Available in PR Builds

For security, secrets are not available in PRs from forks. Use environment-level secrets with protection rules for sensitive deployments.

Next Steps