Deployment

Render your infrastructure. Include operators when you want them.

GitHub Actions

Render TSX to YAML in CI. Use --include-operators to fetch and include operator manifests. Commit the output — your GitOps tool applies everything.

How It Works

1. PushPush r8s.tsx to main
2. RenderCI renders TSX → YAML
3. CommitRendered YAML committed back to repo
4. ApplyGitOps tool applies YAML to cluster

GitHub Actions Workflow

name: Render & Deploy

on:
  push:
    branches: [main]
    paths:
      - 'k8s/**'

jobs:
  render:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci
      - run: npx r8s render --entry k8s/r8s.tsx --out k8s/rendered/ --include-operators

      - name: Commit rendered manifests
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action"
          git add k8s/rendered/
          git diff --quiet && git diff --staged --quiet || \
            (git commit -m "chore: render manifests [skip ci]" && git push)

Including Operators

By default, r8s renders only your resources. Use --include-operators to fetch and include operator manifests in the output. This is useful when each team manages their own operators, or when you want a self-contained deployment.

# Render with operators included
npx r8s render --include-operators

# Render only operators (for platform teams)
npx r8s operators --out operators.yaml

# Render without operators (default)
npx r8s render
# Operator: cnpg v1.22.5
apiVersion: v1
kind: Namespace
metadata:
  name: cnpg-system
---
# Operator: cert-manager v1.14.0
apiVersion: v1
kind: Namespace
metadata:
  name: cert-manager
---
# Your resources
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
# ...

Project Structure

Your repository only needs TSX source files:

my-project/
├── k8s/
│   └── r8s.tsx          # Your entire infrastructure
├── .github/
│   └── workflows/
│       └── deploy.yaml  # Optional: GitHub Actions
└── package.json

Your Infrastructure

Define everything in k8s/r8s.tsx:

// k8s/r8s.tsx
import { App } from '@r8s/recipes';

export default (
  <App
    name="api"
    image="myapp/api:v1.2.3"
    host="api.example.com"
    replicas={3}
    database={{ name: "app-db", storage: "10Gi" }}
    tls={{ issuer: "letsencrypt" }}
  />
);

Multi-Environment

Use overlays for different environments:

// k8s/overlays/staging/r8s.tsx
import { App } from '@r8s/recipes';

export default (
  <App
    name="myapp-staging"
    image="myapp/api:latest"
    host="staging.example.com"
    replicas={1}
    database={{ name: "staging-db", storage: "5Gi" }}
  />
);

// k8s/overlays/production/r8s.tsx
import { App } from '@r8s/recipes';

export default (
  <App
    name="myapp"
    image="myapp/api:v1.2.3"
    host="api.example.com"
    replicas={3}
    database={{ name: "app-db", storage: "20Gi" }}
    tls={{ issuer: "letsencrypt" }}
  />
);

Ready to deploy?

Check out the recipes to find components to deploy, or read about operatorsto understand how dependencies are tracked.