Skip to main content
wit includes a built-in CI/CD engine that can parse and validate GitHub Actions-compatible workflow files. Define your workflows in .wit/workflows/ and wit understands them natively.
The CI/CD engine supports local workflow execution. Jobs run on your machine with shell command execution, environment variable expansion, and step output handling.

Quick Start

# Initialize workflows directory with sample
wit init  # Creates .wit/workflows/ with sample

# Validate a workflow
wit ci validate .wit/workflows/ci.yml

Workflow Location

Workflows are stored in .wit/workflows/*.yml:
.wit/
└── workflows/
    ├── ci.yml
    ├── deploy.yml
    └── test.yml

Workflow Syntax

wit supports GitHub Actions workflow syntax:
name: CI

on:
  push:
    branches:
      - main
      - develop
  pull_request:
    branches:
      - main

env:
  NODE_VERSION: '20'

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

  test:
    name: Test
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run tests
        run: npm test

  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run linter
        run: npm run lint

Triggers

Push Trigger

on:
  push:
    branches:
      - main
      - 'release/**'
    branches-ignore:
      - 'wip/**'
    tags:
      - 'v*'
    paths:
      - 'src/**'
      - 'package.json'
    paths-ignore:
      - 'docs/**'
      - '*.md'

Pull Request Trigger

on:
  pull_request:
    branches:
      - main
    types:
      - opened
      - synchronize
      - reopened
    paths:
      - 'src/**'

Schedule Trigger

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

Manual Trigger

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deployment environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

Multiple Triggers

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

Jobs

Basic Job

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello, World!"

Job Dependencies

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build

  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: npm test

  deploy:
    needs: [build, test]
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh
wit automatically determines the correct job order based on dependencies.

Matrix Strategy

jobs:
  test:
    strategy:
      matrix:
        node: [18, 20, 22]
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm test

Conditional Jobs

jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

Steps

Run Commands

steps:
  - name: Run tests
    run: npm test

  - name: Multi-line script
    run: |
      echo "Building..."
      npm run build
      echo "Done!"

  - name: With working directory
    run: npm test
    working-directory: ./packages/core

Use Actions

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Setup Node
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  - name: Use local action
    uses: ./.github/actions/my-action

Environment Variables

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      CI: true
    steps:
      - name: With step env
        env:
          NODE_ENV: production
        run: npm run build

Services

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

Concurrency

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

Permissions

permissions:
  contents: read
  pull-requests: write
  issues: write

Programmatic API

wit exposes the CI engine programmatically:
import { CIEngine, createCIEngine } from 'wit/ci';

// Create engine for a repository
const engine = createCIEngine('/path/to/repo');

// Load all workflows
const workflows = engine.load();

// Find workflows that match a trigger
const matching = engine.findMatchingWorkflows({
  event: 'push',
  branch: 'main',
  paths: ['src/index.ts'],
});

// Get job execution order
for (const workflow of matching) {
  const jobOrder = engine.getJobOrder(workflow.workflow);
  console.log('Jobs:', jobOrder);
  
  // Get parallel jobs
  const completed = new Set<string>();
  const parallel = engine.getParallelJobs(workflow.workflow, completed);
  console.log('Can run in parallel:', parallel);
}

// Validate a workflow
const result = engine.validate(yamlContent);
if (!result.valid) {
  console.error('Errors:', result.errors);
}

Validation

wit validates workflows for common errors:
import { validateWorkflowFile } from 'wit/ci';

const result = validateWorkflowFile(yamlContent);

if (!result.valid) {
  for (const error of result.errors) {
    console.error(`${error.path}: ${error.message}`);
  }
}

Validated Elements

  • Required fields (name, on, jobs)
  • Valid trigger events
  • Job dependency cycles
  • Step structure
  • Expression syntax (${{ ... }})
  • Cron expressions

Example Workflows

Node.js CI

name: Node.js CI

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

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [18, 20]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
          cache: npm
      - run: npm ci
      - run: npm test

Deploy on Tag

name: Deploy

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build
      - run: npm run deploy
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

Scheduled Maintenance

name: Maintenance

on:
  schedule:
    - cron: '0 3 * * 0'  # Weekly on Sunday at 3 AM

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run cleanup
      - run: npm run report

Comparison with GitHub Actions

FeatureGitHub Actionswit CI
Workflow syntaxYAMLYAML (compatible)
TriggersFull supportParsing + matching
Job dependenciesFull supportFull support
Matrix buildsFull supportParsing support
ExecutionCloud runnersLocal execution
Local validationLimitedBuilt-in

Future Plans

  • Container step support
  • Action marketplace integration
  • Parallel job execution
  • Artifact handling
  • Remote runners