2
0
Code
logikonline ee5fd838b8
Some checks failed
CI / build-and-test (push) Has been cancelled
Release / build (amd64, darwin) (push) Successful in 53s
Release / build (amd64, linux) (push) Successful in 1m4s
Release / build (amd64, windows) (push) Successful in 50s
Release / build (arm64, darwin) (push) Successful in 48s
Release / build (arm64, linux) (push) Successful in 51s
Release / release (push) Successful in 21s
feat(labels): support schema validation in runs-on matching
Enhances PickPlatform to validate schema when runs-on includes explicit mode (e.g., "linux:host" or "ubuntu:docker"). Parses schema suffix from runs-on values and ensures it matches the runner's configured schema for that label. Returns empty string on schema mismatch to prevent jobs from running in wrong environment (e.g., workflow requesting :host but runner only has :docker). Adds test coverage for schema matching, mismatches, and backward compatibility with schema-less runs-on values.
2026-02-09 02:30:24 -05:00
2023-02-28 23:39:30 +08:00
2022-11-24 15:36:16 +08:00
2026-01-23 00:53:55 +00:00
2023-11-23 20:41:10 +00:00

GitCaddy Runner

A Gitea Actions runner with enhanced capability detection and reporting for AI-friendly workflow generation.

GitCaddy Runner is a hard fork of Gitea's act_runner, rebranded and enhanced with automated capability detection to enable AI tools to generate compatible workflows based on available resources.

Features

  • Automated Capability Detection: Automatically identifies OS, architecture, installed tools, and available resources
  • Concurrent Job Execution: Configure runner capacity to handle multiple jobs simultaneously
  • Docker Support: Full support for Docker and Docker Compose workflows
  • Xcode Integration: Detects Xcode installations, SDKs, and simulators on macOS
  • Tool Detection: Identifies installed tools (Node.js, Python, .NET, Go, Ruby, Swift, etc.)
  • AI-Friendly API: Exposes capabilities through Gitea's API for automated workflow generation
  • Cache Support: Built-in workflow cache support for faster builds

Installation

Pre-built Binaries

Download the latest release for your platform from the releases page:

macOS:

# Apple Silicon (M1/M2/M3/M4)
curl -L -o gitcaddy-runner https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-darwin-arm64
chmod +x gitcaddy-runner

# Intel
curl -L -o gitcaddy-runner https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-darwin-amd64
chmod +x gitcaddy-runner

Linux:

# x86_64
curl -L -o gitcaddy-runner https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-linux-amd64
chmod +x gitcaddy-runner

# ARM64
curl -L -o gitcaddy-runner https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-linux-arm64
chmod +x gitcaddy-runner

Windows:

# Download the Windows executable
# https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-windows-amd64.exe

Build from Source

git clone https://git.marketally.com/gitcaddy/gitcaddy-runner.git
cd gitcaddy-runner
make build

Quick Start

1. Enable Gitea Actions

In your Gitea app.ini:

[actions]
ENABLED = true

2. Generate Configuration

./gitcaddy-runner generate-config > config.yaml

3. Configure the Runner

Edit config.yaml to customize settings. Important configuration options:

log:
  level: info

runner:
  file: .runner
  capacity: 2  # Number of concurrent jobs (default: 1)
  timeout: 3h
  shutdown_timeout: 3m  # Grace period for running jobs on shutdown
  insecure: false
  fetch_timeout: 5s
  fetch_interval: 2s
  labels:
    - "ubuntu-latest:docker://node:16-bullseye"
    - "ubuntu-22.04:docker://node:16-bullseye"

cache:
  enabled: true
  dir: ""

container:
  network: ""
  privileged: false
  options: ""
  valid_volumes: []
  docker_host: ""
  force_pull: false

host:
  workdir_parent: ""

Capacity Configuration

The capacity setting controls how many jobs the runner can execute simultaneously:

  • Default: 1 (one job at a time)
  • Recommended: 2-4 for multi-core systems
  • Considerations:
    • Each job consumes CPU, memory, and disk I/O
    • iOS/macOS builds are resource-intensive (start with 2)
    • Lighter builds (Node.js, Go) can handle higher capacity (4-6)
    • Monitor system load and adjust accordingly

Example for different workloads:

# Light builds (web apps, APIs)
runner:
  capacity: 4

# Mixed builds
runner:
  capacity: 2

# Heavy builds (iOS/macOS, large containers)
runner:
  capacity: 1

4. Register the Runner

./gitcaddy-runner register \
  --instance https://your-gitea-instance.com \
  --token YOUR_REGISTRATION_TOKEN \
  --name my-runner \
  --labels ubuntu-latest:docker://node:16-bullseye

The registration token can be obtained from:

  • Gitea Admin Panel > Actions > Runners
  • Or repository Settings > Actions > Runners

5. Start the Runner

Important: Always specify the config file path with -c flag:

./gitcaddy-runner daemon -c config.yaml

Without the -c flag, the runner will use default settings and ignore your config.yaml!

Running as a Service

macOS (launchd)

Create ~/Library/LaunchAgents/com.gitcaddy.runner.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.gitcaddy.runner</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/gitcaddy-runner</string>
        <string>daemon</string>
        <string>-c</string>
        <string>/path/to/config.yaml</string>
    </array>
    <key>WorkingDirectory</key>
    <string>/path/to/runner/directory</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/path/to/runner.log</string>
    <key>StandardErrorPath</key>
    <string>/path/to/runner.err</string>
</dict>
</plist>

Load the service:

launchctl load ~/Library/LaunchAgents/com.gitcaddy.runner.plist

Linux (systemd)

Create /etc/systemd/system/gitcaddy-runner.service:

[Unit]
Description=GitCaddy Actions Runner
After=network.target

[Service]
Type=simple
User=runner
WorkingDirectory=/home/runner/gitcaddy-runner
ExecStart=/home/runner/gitcaddy-runner/gitcaddy-runner daemon -c /home/runner/gitcaddy-runner/config.yaml
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable gitcaddy-runner
sudo systemctl start gitcaddy-runner

Windows (NSSM or Native Service)

GitCaddy Runner has native Windows service support. When running as a service, it automatically detects the Windows Service Control Manager (SCM) and handles stop/shutdown signals properly.

Option 1: Using NSSM (Recommended)

Install NSSM via Chocolatey:

choco install nssm -y

Create the service:

# Install the service
nssm install GiteaRunnerSvc C:\gitea-runner\gitcaddy-runner.exe daemon --config C:\gitea-runner\config.yaml

# Set working directory
nssm set GiteaRunnerSvc AppDirectory C:\gitea-runner

# Set environment variables
nssm set GiteaRunnerSvc AppEnvironmentExtra HOME=C:\gitea-runner USERPROFILE=C:\gitea-runner

# Configure auto-restart on failure
sc failure GiteaRunnerSvc reset=86400 actions=restart/60000/restart/60000/restart/60000

# Start the service
sc start GiteaRunnerSvc

Option 2: Native sc.exe (requires wrapper)

Create a wrapper batch file C:\gitea-runner\start-runner.bat:

@echo off
set HOME=C:\gitea-runner
set USERPROFILE=C:\gitea-runner
cd /d C:\gitea-runner
C:\gitea-runner\gitcaddy-runner.exe daemon --config C:\gitea-runner\config.yaml

Service Management:

# Check service status
sc query GiteaRunnerSvc

# Start service
sc start GiteaRunnerSvc

# Stop service
sc stop GiteaRunnerSvc

# View service logs (if using NSSM with log rotation)
Get-Content C:\gitea-runner\logs\runner.log -Tail 50

Environment Variables for Windows Services:

Variable Description Example
GITEA_RUNNER_SERVICE_NAME Override service name detection GiteaRunnerSvc

Capability Detection

GitCaddy Runner automatically detects and reports system capabilities:

Platform Information

  • Operating system (darwin, linux, windows)
  • Architecture (amd64, arm64)

Container Runtime

  • Docker availability and version
  • Docker Compose support
  • Container runtime type

Development Tools

  • Node.js, npm, yarn
  • Python, pip
  • Go
  • .NET
  • Ruby
  • Rust
  • Java
  • Swift (macOS)
  • Git, Make

macOS-Specific

  • Xcode version and build
  • Available SDKs (iOS, macOS, tvOS, watchOS, visionOS)
  • Simulators
  • Code signing tools (codesign, pkgbuild)
  • Package managers (Homebrew, CocoaPods, Fastlane)

System Resources

  • CPU cores
  • Load average
  • Disk space and usage
  • Network bandwidth

Example Capabilities Output

{
  "os": "darwin",
  "arch": "arm64",
  "capacity": 2,
  "docker": true,
  "docker_compose": true,
  "container_runtime": "docker",
  "xcode": {
    "version": "15.2",
    "build": "15C500b",
    "sdks": ["iOS 17.2", "macOS 14.2"]
  },
  "tools": {
    "node": ["20.11"],
    "python": ["3.11"],
    "swift": ["5.9"]
  },
  "build_tools": ["fastlane", "cocoapods", "codesign"],
  "cpu": {
    "num_cpu": 10,
    "load_percent": 25.5
  },
  "disk": {
    "free_bytes": 54199226368,
    "used_percent": 77.89
  }
}

Configuration Reference

Runner Section

Option Type Default Description
capacity int 1 Maximum concurrent jobs
timeout duration 3h Maximum job execution time
shutdown_timeout duration 3m Grace period for jobs to complete on shutdown
insecure bool false Allow insecure HTTPS
fetch_timeout duration 5s Timeout for fetching tasks
fetch_interval duration 2s Interval between task fetches
labels []string [] Runner labels for job matching
env_file string .env Environment variables file

Cache Section

Option Type Default Description
enabled bool true Enable cache support
dir string "" Cache directory path
host string "" External cache server host
port int 0 External cache server port

Container Section

Option Type Default Description
network string "" Docker network for containers
privileged bool false Run containers in privileged mode
docker_host string "" Custom Docker host
force_pull bool false Always pull latest images

Troubleshooting

Capacity Not Being Applied

Problem: Runner shows "capacity":1 even though config.yaml has capacity: 2

Solution: Ensure you're using the -c flag when starting the daemon:

# ✅ Correct
./gitcaddy-runner daemon -c /path/to/config.yaml

# ❌ Wrong - uses defaults
./gitcaddy-runner daemon

Verify the config is being loaded:

# Check runner process
ps aux | grep gitcaddy-runner

# Should show: gitcaddy-runner daemon -c /path/to/config.yaml

Docker Not Detected

Problem: Capabilities show "docker":false but Docker is installed

Solution:

  1. Ensure Docker Desktop/daemon is running:

    docker ps
    
  2. Restart the runner after starting Docker:

    ./gitcaddy-runner daemon -c config.yaml
    
  3. Check Docker socket permissions:

    ls -l /var/run/docker.sock
    

Jobs Not Running Concurrently

Problem: Jobs queue instead of running in parallel

Checklist:

  1. Verify capacity in capabilities output (check runner logs)
  2. Confirm config.yaml has capacity > 1
  3. Ensure runner was started with -c config.yaml flag
  4. Check system resources aren't maxed out
  5. Restart runner after config changes

Runner Not Starting

Problem: Runner exits immediately or fails to start

Common causes:

  1. Invalid config.yaml syntax
  2. .runner file missing (run register first)
  3. Permission issues on working directory
  4. Invalid Gitea instance URL or token

Debug steps:

# Check config syntax
./gitcaddy-runner generate-config > test-config.yaml
diff config.yaml test-config.yaml

# Test with verbose logging
./gitcaddy-runner daemon -c config.yaml --log-level debug

# Verify registration
cat .runner

Environment Variables

GitCaddy Runner supports environment variable configuration:

Variable Description Example
GITEA_RUNNER_CAPACITY Override capacity setting GITEA_RUNNER_CAPACITY=2
GITEA_RUNNER_ENV_FILE Custom env file path GITEA_RUNNER_ENV_FILE=.env.prod

API Integration

Query runner capabilities via Gitea API:

curl -H "Authorization: token YOUR_TOKEN" \
  https://your-gitea.com/api/v1/runners

Use capabilities to generate compatible workflows:

# Example: Use capabilities to select appropriate runner
name: Build
on: [push]
jobs:
  build:
    runs-on: ${{ capabilities.os == 'darwin' && 'macos-latest' || 'ubuntu-latest' }}
    steps:
      - uses: actions/checkout@v3

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

License

MIT License - see LICENSE for details.

Support

Acknowledgments

GitCaddy Runner is a hard fork of Gitea's act_runner, rebranded and enhanced with automated capability detection and reporting features for AI-friendly workflow generation.

GitCaddy Runner - User Guide

A CI/CD runner for Gitea Actions that executes workflows defined in .gitea/workflows/ directories. This runner connects to your Gitea instance and picks up jobs to execute them in Docker containers or directly on the host machine.

Table of Contents

Installation

From Binary

Download the latest release for your platform:

# Linux AMD64
wget https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-linux-amd64

# macOS ARM64
wget https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-darwin-12-arm64

# Windows AMD64
wget https://git.marketally.com/gitcaddy/gitcaddy-runner/releases/download/v1.0.0/gitcaddy-runner-1.0.0-windows-amd64.exe

Make the binary executable:

chmod +x gitcaddy-runner-1.0.0-linux-amd64
sudo mv gitcaddy-runner-1.0.0-linux-amd64 /usr/local/bin/gitcaddy-runner

From Source

Requirements:

  • Go 1.23 or later
  • Docker (if using Docker-based workflows)
git clone https://git.marketally.com/gitcaddy/gitcaddy-runner.git
cd gitcaddy-runner
make build
sudo mv gitcaddy-runner /usr/local/bin/

Verify Installation

gitcaddy-runner --version

Getting Started

Prerequisites

  1. Gitea Instance: You need a running Gitea instance (v1.21 or later recommended)
  2. Docker (optional but recommended): For running workflows in containers
  3. Registration Token: Obtain from your Gitea instance:
    • Go to your repository → Settings → Actions → Runners
    • Click "Create new runner" and copy the registration token

Quick Start

  1. Generate a configuration file:
gitcaddy-runner generate-config > config.yaml
  1. Register the runner:
gitcaddy-runner register \
  --instance https://gitea.example.com \
  --token YOUR_REGISTRATION_TOKEN \
  --name my-runner \
  --labels "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
  1. Start the runner daemon:
gitcaddy-runner daemon

Registration

The runner must be registered with your Gitea instance before it can execute jobs.

Interactive Registration

Run the registration command without flags for an interactive setup:

gitcaddy-runner register

You'll be prompted for:

  • Gitea instance URL: https://gitea.example.com/
  • Registration token: Obtained from Gitea UI
  • Runner name: Defaults to hostname if left empty
  • Labels: Comma-separated list of labels (or press Enter for defaults)

Non-Interactive Registration

For automation or scripts:

gitcaddy-runner register \
  --no-interactive \
  --instance https://gitea.example.com \
  --token YOUR_TOKEN \
  --name production-runner \
  --labels "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest,ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"

Ephemeral Runners

For single-use runners (useful for auto-scaling):

gitcaddy-runner register \
  --ephemeral \
  --instance https://gitea.example.com \
  --token YOUR_TOKEN \
  --name ephemeral-runner

Ephemeral runners automatically unregister after completing one job.

Registration File

Registration information is stored in .runner (by default). This file contains:

  • Runner UUID and token
  • Runner name
  • Configured labels
  • Gitea instance address

Important: Keep this file secure as it contains authentication credentials.

Running the Daemon

Basic Usage

Start the runner daemon to begin accepting jobs:

gitcaddy-runner daemon

With a custom configuration file:

gitcaddy-runner daemon --config /path/to/config.yaml

Run Once Mode

Execute a single job and then exit:

gitcaddy-runner daemon --once

This is useful for:

  • Testing runner setup
  • Ephemeral runners in auto-scaling environments
  • Scheduled job execution

Background Execution

Run as a background service using systemd:

Create /etc/systemd/system/gitcaddy-runner.service:

[Unit]
Description=GitCaddy Runner
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
User=gitea-runner
WorkingDirectory=/home/gitea-runner
ExecStart=/usr/local/bin/gitcaddy-runner daemon --config /home/gitea-runner/config.yaml
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable gitcaddy-runner
sudo systemctl start gitcaddy-runner
sudo systemctl status gitcaddy-runner

Configuration

Generate Default Configuration

gitcaddy-runner generate-config > config.yaml

Configuration File Structure

log:
  level: info  # trace, debug, info, warn, error, fatal

runner:
  file: .runner                # Registration file path
  capacity: 1                  # Number of concurrent jobs
  timeout: 3h                  # Job timeout
  shutdown_timeout: 0s         # Graceful shutdown timeout
  insecure: false              # Skip TLS verification
  fetch_timeout: 5s            # Job fetch timeout
  fetch_interval: 2s           # Job fetch interval
  github_mirror: ''            # Mirror for GitHub actions
  envs:                        # Extra environment variables
    NODE_ENV: production
  env_file: .env               # Load environment from file
  labels:                      # Runner labels
    - "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"

cache:
  enabled: true
  dir: ""                      # Cache directory (default: $HOME/.cache/actcache)
  host: ""                     # Cache server host (auto-detected)
  port: 0                      # Cache server port (0 = random)
  external_server: ""          # External cache server URL

container:
  network: ""                  # Docker network (empty = auto-create)
  privileged: false            # Run containers in privileged mode
  options: ""                  # Additional docker run options
  workdir_parent: workspace    # Parent directory for job workspaces
  valid_volumes:               # Allowed volume mounts (glob patterns)
    - '**'
  docker_host: ""              # Docker daemon socket (auto-detected)
  force_pull: true             # Always pull images
  force_rebuild: false         # Rebuild images even if present
  require_docker: false        # Require Docker daemon
  docker_timeout: 0s           # Docker daemon startup timeout

host:
  workdir_parent: ""           # Host workspace directory (default: $HOME/.cache/act)

Environment Variables

Legacy environment variables (deprecated but still supported):

  • GITEA_DEBUG: Enable debug logging
  • GITEA_TRACE: Enable trace logging
  • GITEA_RUNNER_CAPACITY: Set runner capacity
  • GITEA_RUNNER_FILE: Set registration file path
  • GITEA_RUNNER_ENVIRON: Set environment variables (comma-separated key:value)
  • GITEA_RUNNER_ENV_FILE: Load environment from file

Note: Configuration file settings take precedence over environment variables.

Labels and Execution Environments

Labels determine which jobs a runner can execute and how they run.

Label Format

label-name:schema:argument
  • label-name: Identifier used in workflow runs-on
  • schema: Execution environment (docker or host)
  • argument: Additional configuration (e.g., Docker image)

Docker Labels

Run jobs in Docker containers:

labels:
  - "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
  - "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
  - "node:docker://node:18"
  - "python:docker://python:3.11"

Workflow usage:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: echo "Running in Ubuntu container"

Host Labels

Run jobs directly on the host machine:

labels:
  - "self-hosted:host"
  - "linux:host"
  - "macos:host"

Workflow usage:

jobs:
  build:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v3
      - run: echo "Running on host"

Custom Images

Use custom Docker images:

labels:
  - "custom-env:docker://registry.example.com/my-build-env:latest"

Multiple Labels

A runner can have multiple labels to support different job types:

labels:
  - "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
  - "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
  - "self-hosted:host"
  - "gpu:host"

Docker Deployment

Basic Docker Run

docker run -d \
  --name gitcaddy-runner \
  -e GITEA_INSTANCE_URL=https://gitea.example.com \
  -e GITEA_RUNNER_REGISTRATION_TOKEN=YOUR_TOKEN \
  -e GITEA_RUNNER_NAME=docker-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /data/runner:/data \
  marketally/gitcaddy-runner:latest

Docker Compose

Create docker-compose.yml:

version: '3'

services:
  runner:
    image: marketally/gitcaddy-runner:latest
    environment:
      - GITEA_INSTANCE_URL=https://gitea.example.com
      - GITEA_RUNNER_REGISTRATION_TOKEN=YOUR_TOKEN
      - GITEA_RUNNER_NAME=compose-runner
      - GITEA_RUNNER_LABELS=ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./runner-data:/data
    restart: unless-stopped

Start:

docker-compose up -d

Docker-in-Docker (DinD)

For isolated Docker environments:

version: '3'

services:
  runner:
    image: marketally/gitcaddy-runner:latest-dind
    privileged: true
    environment:
      - GITEA_INSTANCE_URL=https://gitea.example.com
      - GITEA_RUNNER_REGISTRATION_TOKEN=YOUR_TOKEN
      - DOCKER_TLS_CERTDIR=/certs
    volumes:
      - runner-data:/data
      - docker-certs:/certs
    restart: unless-stopped

volumes:
  runner-data:
  docker-certs:

Rootless Docker

For enhanced security:

version: '3'

services:
  runner:
    image: marketally/gitcaddy-runner:latest-dind-rootless
    environment:
      - GITEA_INSTANCE_URL=https://gitea.example.com
      - GITEA_RUNNER_REGISTRATION_TOKEN=YOUR_TOKEN
      - DOCKER_HOST=unix:///run/user/1000/docker.sock
    volumes:
      - runner-data:/data
    restart: unless-stopped
    security_opt:
      - seccomp:unconfined

volumes:
  runner-data:

Kubernetes Deployment

Using Docker-in-Docker

See examples/kubernetes/dind-docker.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitcaddy-runner-vol
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Secret
metadata:
  name: runner-secret
type: Opaque
data:
  token: <base64-encoded-registration-token>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitcaddy-runner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gitcaddy-runner
  template:
    metadata:
      labels:
        app: gitcaddy-runner
    spec:
      volumes:
      - name: docker-certs
        emptyDir: {}
      - name: runner-data
        persistentVolumeClaim:
          claimName: gitcaddy-runner-vol
      containers:
      - name: runner
        image: git.marketally.com/gitcaddy/gitcaddy-runner:latest
        command: ["sh", "-c", "while ! nc -z localhost 2376 </dev/null; do echo 'waiting for docker daemon...'; sleep 5; done; /sbin/tini -- run.sh"]
        env:
        - name: DOCKER_HOST
          value: tcp://localhost:2376
        - name: DOCKER_CERT_PATH
          value: /certs/client
        - name: DOCKER_TLS_VERIFY
          value: "1"
        - name: GITEA_INSTANCE_URL
          value: http://gitcaddy-http.gitcaddy.svc.cluster.local:3000
        - name: GITEA_RUNNER_REGISTRATION_TOKEN
          valueFrom:
            secretKeyRef:
              name: runner-secret
              key: token
        volumeMounts:
        - name: docker-certs
          mountPath: /certs
        - name: runner-data
          mountPath: /data
      - name: daemon
        image: docker:23.0.6-dind
        env:
        - name: DOCKER_TLS_CERTDIR
          value: /certs
        securityContext:
          privileged: true
        volumeMounts:
        - name: docker-certs
          mountPath: /certs

Apply:

kubectl apply -f dind-docker.yaml

Using Rootless Docker

See examples/kubernetes/rootless-docker.yaml for a more secure rootless setup.

Common Workflows

Basic CI Workflow

Create .gitea/workflows/ci.yaml:

name: CI

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.21'
      
      - name: Run tests
        run: go test ./...
      
      - name: Build
        run: go build -v ./...

Multi-Platform Build

name: Build

on: [push]

jobs:
  build-linux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: make build-linux
  
  build-macos:
    runs-on: macos
    steps:
      - uses: actions/checkout@v3
      - run: make build-macos
  
  build-windows:
    runs-on: windows
    steps:
      - uses: actions/checkout@v3
      - run: make build-windows

Using Caching

name: Build with Cache

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-
      
      - name: Build
        run: go build ./...

Using Artifacts

Important: GitCaddy Runner does not support actions/upload-artifact@v4 or actions/download-artifact@v4. Use v3 instead:

name: Build and Upload

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build
        run: make build
      
      - name: Upload artifact
        uses: actions/upload-artifact@v3  # Note: v3, not v4
        with:
          name: my-artifact
          path: dist/
  
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v3  # Note: v3, not v4
        with:
          name: my-artifact
          path: dist/
      
      - name: Deploy
        run: ./deploy.sh

Using Services

name: Integration Tests

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v3
      
      - name: Run integration tests
        env:
          DATABASE_URL: postgres://postgres:postgres@postgres:5432/test
        run: go test -tags=integration ./...

Artifact Upload Helper

For large files or unreliable networks, use the built-in upload helper with retry logic:

gitcaddy-upload \
  -url https://gitea.example.com/api/v1/repos/owner/repo/releases/1/assets \
  -token YOUR_TOKEN \
  -file ./large-artifact.zip \
  -retries 10

Options:

  • -url: Upload endpoint URL
  • -token: Authentication token
  • -file: File to upload
  • -retries: Maximum retry attempts (default: 5)

The upload helper automatically:

  • Retries on network failures
  • Pre-warms connections
  • Uses chunked uploads for large files
  • Provides detailed progress logging

Disk Space Management

The runner includes automatic disk space monitoring and cleanup capabilities.

Automatic Cleanup

The runner automatically monitors disk usage and triggers cleanup when:

  • Disk usage exceeds 85% (warning threshold)
  • Disk usage exceeds 95% (critical threshold)

Cleanup targets:

  • Old cache directories (>24 hours)
  • Old work directories (>48 hours)
  • Old artifact staging files (>72 hours)
  • System temp files (>24 hours)
  • Build tool caches (>7 days): Go, npm, pip, Maven, Gradle, NuGet, Cargo, etc.

Manual Cleanup

Trigger cleanup manually:

gitcaddy-runner cleanup --config config.yaml

Output example:

Cleanup completed: freed 15728640000 bytes, deleted 1234 files in 5.2s

Monitoring Disk Space

The runner reports disk space in its capabilities:

{
  "disk": {
    "path": "/workspace",
    "total_bytes": 107374182400,
    "free_bytes": 32212254720,
    "used_bytes": 75161927680,
    "used_percent": 70.0
  }
}

Best Practices

  1. Monitor disk usage: Check runner logs for disk space warnings
  2. Configure cleanup: Adjust cache retention in config.yaml
  3. Use ephemeral runners: For auto-scaling environments
  4. Separate volumes: Use dedicated volumes for runner data

Cache Server

The runner includes a built-in cache server for actions/cache.

Automatic Cache Server

Enabled by default in the configuration:

cache:
  enabled: true
  dir: ""      # Default: $HOME/.cache/actcache
  host: ""     # Auto-detected
  port: 0      # Random available port

The cache server URL is automatically provided to jobs via ACTIONS_CACHE_URL.

External Cache Server

Use an external cache server:

cache:
  enabled: true
  external_server: "http://cache.example.com:8080/"

Standalone Cache Server

Run the cache server independently:

gitcaddy-runner cache-server \
  --dir /path/to/cache \
  --host 0.0.0.0 \
  --port 8080

Options:

  • --dir: Cache storage directory
  • --host: Listen address
  • --port: Listen port

Troubleshooting

Runner Not Picking Up Jobs

Check registration:

cat .runner

Verify the runner appears in Gitea UI (Settings → Actions → Runners).

Check labels: Ensure workflow runs-on matches a runner label.

Check logs:

gitcaddy-runner daemon --config config.yaml

Look for connection errors or authentication issues.

Docker Connection Issues

Error: Cannot ping the docker daemon

Solutions:

  1. Verify Docker is running:
docker ps
  1. Check Docker socket path:
ls -la /var/run/docker.sock
  1. Add user to docker group:
sudo usermod -aG docker $USER
newgrp docker
  1. Specify Docker host in config:
container:
  docker_host: "unix:///var/run/docker.sock"

Timeout Issues

Error: Job timeout after 3 hours

Solution: Increase timeout in config:

runner:
  timeout: 6h

Disk Space Issues

Error: No space left on device

Solutions:

  1. Run manual cleanup:
gitcaddy-runner cleanup
  1. Increase disk space or use dedicated volume

  2. Configure more aggressive cleanup:

cache:
  dir: /path/to/larger/disk

SSL/TLS Certificate Issues

Error: x509: certificate signed by unknown authority

Solution (not recommended for production):

runner:
  insecure: true

Better solution: Install proper CA certificates:

sudo cp your-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

Actions Not Found

Error: unable to resolve action

Solution: Configure GitHub mirror if needed:

runner:
  github_mirror: 'https://github.mirror.example.com'

Artifact Upload Failures

Error: actions/upload-artifact@v4 not supported

Solution: Use v3 instead:

- uses: actions/upload-artifact@v3  # Not v4
  with:
    name: my-artifact
    path: dist/

For large files with unreliable networks, use the upload helper:

gitcaddy-upload -url $URL -token $TOKEN -file artifact.zip

Best Practices

Security

  1. Keep registration file secure: The .runner file contains authentication credentials
  2. Use secrets: Never hardcode sensitive data in workflows
  3. Limit volume mounts: Restrict valid_volumes in configuration
  4. Use rootless Docker: When possible, use rootless containers
  5. Regular updates: Keep runner and Docker images up to date

Performance

  1. Use caching: Cache dependencies to speed up builds
  2. Parallel jobs: Increase capacity for concurrent job execution
  3. Local images: Use force_pull: false for frequently used images
  4. Dedicated volumes: Use fast storage for workspaces and cache

Reliability

  1. Monitor disk space: Watch for low disk space warnings
  2. Set appropriate timeouts: Balance between job completion and resource usage
  3. Use health checks: Monitor runner process and Docker daemon
  4. Graceful shutdown: Configure shutdown_timeout for clean termination
  5. Log rotation: Implement log rotation to prevent disk fill

Scalability

  1. Ephemeral runners: Use --ephemeral for auto-scaling
  2. Multiple runners: Deploy multiple runners for load distribution
  3. Label-based routing: Use labels to route jobs to appropriate runners
  4. Resource limits: Set Docker resource limits in container.options

Maintenance

  1. Regular cleanup: Run periodic manual cleanup or rely on automatic cleanup
  2. Update images: Keep runner images and workflow images current
  3. Monitor logs: Check logs for warnings and errors
  4. Test configuration: Validate config changes in staging first
  5. Backup registration: Keep backup of .runner file

Workflow Best Practices

  1. Use specific versions: Pin action versions (e.g., @v3, not @latest)
  2. Minimize steps: Combine related commands
  3. Use artifacts wisely: Only upload necessary files
  4. Clean up: Remove temporary files in workflows
  5. Test locally: Use gitcaddy-runner exec to test workflows locally

Example Production Setup

# config.yaml
log:
  level: info

runner:
  capacity: 4
  timeout: 2h
  shutdown_timeout: 5m
  fetch_interval: 2s
  labels:
    - "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
    - "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"

cache:
  enabled: true
  dir: /mnt/fast-storage/cache

container:
  network: gitea-actions
  force_pull: false
  workdir_parent: /mnt/fast-storage/workspace
  valid_volumes:
    - /mnt/artifacts/**
  docker_host: unix:///var/run/docker.sock

host:
  workdir_parent: /mnt/fast-storage/host-workspace

This configuration provides:

  • 4 concurrent jobs
  • 2-hour job timeout with 5-minute graceful shutdown
  • Fast storage for cache and workspaces
  • Restricted volume mounts for security
  • Optimized image pulling
MIT License Copyright (c) 2026 gitcaddy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Description
GitCaddy fork of act_runner with capability reporting for AI-friendly workflow generation
http://www.gitcaddy.com
Readme MIT 79 MiB
2026-02-09 07:30:38 +00:00
Languages
Go 94.4%
Makefile 3.4%
Shell 1.4%
Dockerfile 0.8%