Skip to content

Development Setup

This guide covers setting up a development environment for contributing to Shed.

Prerequisites

  • Go 1.24 or later
  • Docker (for building the base image and testing)
  • Make
  • Git

Getting Started

Clone the Repository

git clone https://github.com/charliek/shed.git
cd shed

Build

# Build both binaries
make build

# Binaries are placed in bin/
ls bin/
# shed  shed-server

Run Tests

# Run all tests
make test

# Run tests with coverage
make coverage

# Run tests with race detection
go test -race ./...

Code Quality

# Run linter (requires golangci-lint)
make lint

# Format code
make fmt

# Run all checks
make check

Project Structure

shed/
├── cmd/
│   ├── shed/               # CLI binary
│   │   ├── main.go         # Entry point
│   │   ├── client.go       # HTTP client for API
│   │   ├── create.go       # create command
│   │   ├── console.go      # console command
│   │   └── ...
│   └── shed-server/        # Server binary
│       ├── main.go         # Entry point
│       ├── serve.go        # serve command
│       └── install.go      # systemd install
├── internal/
│   ├── api/                # HTTP API handlers
│   ├── config/             # Configuration types
│   ├── docker/             # Docker client wrapper
│   ├── sshd/               # SSH server
│   ├── sshconfig/          # SSH config management
│   ├── provision/          # Provisioning hooks
│   ├── sync/               # File synchronization
│   ├── tunnels/            # SSH tunnel management
│   └── version/            # Version information
├── scripts/
│   └── build-image.sh      # Build shed-base image
├── configs/
│   ├── server.example.yaml
│   └── server.dev.yaml
├── docs/
├── Makefile
└── go.mod

Running Locally

Single Machine Development

Run both CLI and server on the same machine:

# Terminal 1: Start the server
./bin/shed-server serve -c configs/server.dev.yaml

# Terminal 2: Use the CLI
./bin/shed server add localhost
./bin/shed create test-shed
./bin/shed console test-shed

Making Changes

Adding a New CLI Command

  1. Create a new file in cmd/shed/ (e.g., newcmd.go)
  2. Define a cobra.Command variable
  3. Register it in cmd/shed/main.go
  4. Implement the command logic
// cmd/shed/newcmd.go
package main

import "github.com/spf13/cobra"

var newCmd = &cobra.Command{
    Use:   "newcmd",
    Short: "Description of the new command",
    RunE:  runNewCmd,
}

func runNewCmd(cmd *cobra.Command, args []string) error {
    // Implementation
    return nil
}

Adding a New API Endpoint

  1. Add the route in internal/api/server.go
  2. Add the handler in internal/api/handlers.go
  3. Add any new types to internal/config/types.go

Testing

Unit Tests

Place unit tests alongside the code:

// internal/config/types_test.go
package config

import "testing"

func TestValidateShedName(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        wantErr bool
    }{
        {"valid", "my-shed", false},
        {"empty", "", true},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            err := ValidateShedName(tt.input)
            if (err != nil) != tt.wantErr {
                t.Errorf("ValidateShedName(%q) error = %v", tt.input, err)
            }
        })
    }
}

Integration Tests

Use build tags for Docker-dependent tests:

//go:build integration

package docker

func TestCreateShed_Integration(t *testing.T) {
    // Test with real Docker
}

Run integration tests:

go test -tags=integration ./...

Continuous Integration

GitHub Actions runs on push to main or feature/* branches:

  1. Test: Runs all unit tests
  2. Lint: Runs golangci-lint
  3. Dockerfile Lint: Runs hadolint

Run checks locally before pushing:

make check

Installing Tools

# golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5

# hadolint (for Dockerfile linting)
# macOS: brew install hadolint

Building Documentation

# Build documentation
make docs

# Serve locally
make docs-serve
# Visit http://127.0.0.1:7070

Debugging

Server Logs

LOG_LEVEL=debug ./bin/shed-server serve

Docker Inspection

docker ps --filter "label=shed=true"
docker inspect shed-myproject
docker logs shed-myproject

API Testing

curl http://localhost:8080/api/info
curl http://localhost:8080/api/sheds