Skip to content

8bitdogs/goci

Repository files navigation

GOCI

Docker Image Version Docker Hub Pulls Docker Stars Docker Cloud Automated build GitHub Go Report Card

Description

goci is a lightweight CI/CD runner that deploys your services without SSH keys. It listens for GitHub webhook events, runs a configurable pipeline (pull image, redeploy container, run commands), and reports the result back to GitHub as a commit status. Your GitHub Actions workflow waits for the status and finishes accordingly — giving you a clean, auditable deployment gate directly inside your PR/push workflow.

Key features:

  • No SSH keys or VPN required on the target host
  • Driven by GitHub webhooks (workflow_job or push events)
  • Commit status integration — GitHub Actions waits for goci to finish
  • Per-service pipeline configuration (JSON or YAML)
  • Docker Compose-aware: pulls new images and redeploys services

How it works

           GITHUB                                       GOCI
──────────────────────────────────────────────────────────────────────
  git push
       │
       ▼
  Actions: build/push job
  ├─ build container image
  └─ push image to registry
       │
       │  workflow_job.completed
       │ ──────────────────────────────────────────▶ receive webhook
       │                                                   │
       │                                            [1] set commit status: pending
       │                                                   │
  Actions: deploy job                               [2] run pipeline
  (waiting for commit status)                              ├─ pull new image
       │                                                   ├─ redeploy service
       │                                                   └─ run steps
       │                                                    │
       │                                            [3] set commit status
       │                                             ┌──────┴────────┐
       │                                          success         failure
       │                                             │               │
       │◀───────────────── commit status: success ──┘               │
       │◀───────────────────────────── commit status: failure ──────┘
       │
       ▼
  deploy job: ✓ success / ✗ failure

Configuration

Environment variables (.env / top-level)

These are global defaults. Any value can be overridden per-service in the config file.

Variable Default Description
GOCI_HOST (empty) Optional. Public URL of this goci instance. Used in status update descriptions.
GOCI_SERVER_ADDR :7878 Address and port for the goci HTTP server.
GOCI_LOG_LEVEL info Log verbosity: debug, info, warn, error.
GOCI_GITHUB_TOKEN (required) GitHub personal access token (or GITHUB_TOKEN from Actions). Used to set commit statuses.
GOCI_GITHUB_WEBHOOK_PATH_PREFIX (empty) Optional. Path prefix applied to all service webhook URLs. When set, the effective webhook path for each service becomes <prefix>/<service-name>, overriding the path field in the service config. Trailing slashes are stripped automatically.
GOCI_GITHUB_WEBHOOK_SECRET (empty) Secret used to validate incoming GitHub webhooks.
GOCI_GITHUB_METHOD POST HTTP method expected for the webhook endpoint.
GOCI_GITHUB_RESPONSE_TIMEOUT 10s Timeout for outbound GitHub API calls.
GOCI_GITHUB_TARGET_BRANCH main Only process events targeting this branch.
GOCI_GITHUB_EVENT_TYPE push GitHub event type to listen for. Use workflow_job for workflow-driven deployments.
GOCI_GITHUB_COMMIT_STATUS_CONTEXT goci/pipeline Context string for GitHub commit status updates. Must match the context field in your GitHub Actions wait-commit-status step.
GOCI_GITHUB_WORKFLOW_NAME (empty) Optional. Filter by workflow name (the name: field at the root of the workflow YAML).
GOCI_GITHUB_WORKFLOW_JOB_NAME (required for workflow_job) Name of the GitHub Actions job whose completion triggers goci.
GOCI_GITHUB_WORKFLOW_ACTION completed Workflow job action to react to: queued, in_progress, or completed.

See .env.example for a ready-to-copy template.


Service config file (config.yaml / config.json)

Pass the path with -config /path/to/config.yaml (default: config.json).

Defines one or more services, each with its own pipeline and GitHub webhook settings. Service-level GitHub fields override the global environment variables.

YAML example:

- name: "my-service"
  pipeline:
    jobs:
      - name: "deploy"
        steps:
          - name: "pull image"
            cmd: "docker"
            args: ["compose", "pull", "my-service"]
            dir: "/app"
            timeout: 60s
          - name: "restart service"
            cmd: "docker"
            args: ["compose", "up", "-d", "my-service"]
            dir: "/app"
            timeout: 30s
  github:
    token: "<github-token>"              # overrides GOCI_GITHUB_TOKEN
    webhook:
      path: "/webhook/my-service"          # GitHub webhook URL path
      method: "POST"                        # optional, default POST
      secret: "<webhook-secret>"            # overrides GOCI_GITHUB_WEBHOOK_SECRET
      branch: "main"                        # target branch filter
      event: "workflow_job"                 # event type
      commit_status_context: "goci/deploy" # overrides GOCI_GITHUB_COMMIT_STATUS_CONTEXT
      workflow:
        action: "completed"
        job_name: "build-and-push"         # GitHub Actions job name that triggers goci

JSON example: see config.json.example.


Pull the image

# Docker Hub
docker pull 8bitdogs/goci:latest

# GitHub Container Registry
docker pull ghcr.io/8bitdogs/goci:latest

Docker Compose setup

Add goci as a service in your docker-compose.yaml:

name: "<compose-name>"  # required

services:

  # your application services...

  goci:
    image: 8bitdogs/goci:latest
    container_name: goci
    depends_on:
      - your-service
    env_file:
      - .env                                          # top-level configuration
    volumes:
      - ~/.docker/config.json:/root/.docker/config.json:ro  # registry auth
      - /var/run/docker.sock:/var/run/docker.sock           # Docker control
      - ./docker-compose.yaml:/docker-compose.yaml          # Compose file for redeployment
      - ./config.yaml:/config.yaml                          # goci service config
    command: goci -config /config.yaml

Note: Mounting docker.sock gives goci the ability to pull images and restart containers on the host. Ensure the goci container is trusted.


GitHub Actions integration

Add a deploy job to your workflow that waits for goci to report the deployment result via commit status:

jobs:
  docker:
    name: build and push docker image
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build and push
        # ... your build/push steps

  deploy:
    name: deploy
    needs: docker
    runs-on: ubuntu-latest
    permissions:
      statuses: read         # wait-commit-status polls the commit status
    steps:
      - uses: 8bitdogs/wait-commit-status@main
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          context: goci/deploy   # must match GOCI_GITHUB_COMMIT_STATUS_CONTEXT or service config
          interval: 5            # poll every 5 seconds
          timeout: 300           # fail after 5 minutes

The deploy job will block until goci sets the commit status to success or failure, ensuring your workflow reflects the actual deployment result.

Required permissions

The only permission required for goci integration is:

Permission Job Why
statuses: read deploy wait-commit-status polls commit statuses until goci responds

goci writes commit statuses using its own GOCI_GITHUB_TOKEN (a PAT configured on the server), not the workflow's GITHUB_TOKEN. The workflow only needs statuses: read so wait-commit-status can poll for the result.

The context value must exactly match GOCI_GITHUB_COMMIT_STATUS_CONTEXT (env) or commit_status_context in your service config.


GitHub Webhook setup

Go to your repository (or organization) → Settings → Webhooks → Add webhook.

1. Payload URL

Combine your goci host with the webhook path defined in your service config:

<CI_HOST> + <github.path from service config>

# example
https://goci.example.com/webhook/my-service

2. Content type

Select application/json.

3. Secret

Generate a high-entropy secret and paste it into the Secret field. Use the same value for GOCI_GITHUB_WEBHOOK_SECRET (env) or secret in your service config.

openssl rand -hex 32

4. Events

Choose "Let me select individual events" and enable:

Event Purpose
Ping Verifies the webhook is reachable (always enable)
Push Triggers goci on push events (GOCI_GITHUB_EVENT_TYPE=push)
Workflow jobs Triggers goci when a workflow job completes (GOCI_GITHUB_EVENT_TYPE=workflow_job)

Disable all other events to reduce noise.

5. Verify

After saving, GitHub immediately sends a ping event. Open the Recent Deliveries tab and check the response code:

Status Meaning
200 Webhook validated and pipeline executed
202 Webhook validated but nothing matched (no pipeline executed)
4xx / 5xx Error — see the response payload message for details

Any other status or a failed delivery means goci is unreachable or the payload was rejected — check that goci is running, the Payload URL is correct, and the secret matches.


Quick start

# 1. Copy and fill in environment config
cp .env.example .env

# 2. Create your service config
cp config.yaml.example config.yaml

# 3. Run with Docker Compose
docker compose up -d goci

Or build from source:

make up

About

Lightweight CI/CD runner that deploys your services via GitHub webhooks — no SSH keys required.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages