CLAUDE.mdgo

tulip CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

View Source

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Tulip is OllyGarden's commercially supported distribution of the OpenTelemetry Collector. It is built using the OpenTelemetry Collector Builder (ocb) and follows the same architecture as upstream OpenTelemetry Collector distributions.

Key Context:

  • This is a commercial product with enterprise support SLAs (see ../pergola/tulip/00-prd.md)
  • Module name: github.com/ollygarden/tulip
  • Binary output directory: ./bin (as per user instructions)
  • The repository structure mirrors otelcol-distributions template

Build System Architecture

Component Manifest System

The core of Tulip's architecture is the manifest-driven build system:

  1. distributions/tulip/manifest.yaml - The single source of truth for:

    • Component selection (extensions, receivers, processors, exporters, connectors)
    • Component versions (must stay synchronized across all components)
    • Module path and distribution metadata
  2. OpenTelemetry Collector Builder (ocb) - Automatically installed by Makefile:

    • Reads manifest.yaml
    • Generates Go source code in distributions/tulip/_build/
    • Creates components.go, main.go, go.mod, and platform-specific entry points
    • Generated files should NOT be manually edited
  3. Build Process Flow:

    manifest.yaml → ocb → _build/*.go → go build → binary
    

Key Build Commands

Full build (generate + compile):

make build

Generate source code only (no compilation):

make generate-sources
# Or via script:
./scripts/build.sh -d tulip -s true -b ocb

Run tests:

make test

Full CI workflow:

make ci  # Runs: check, build, test, goreleaser validation

Format Go code (required after changes):

go fmt ./...

Adding or Updating Components

To add a new component:

  1. Edit distributions/tulip/manifest.yaml
  2. Add component with gomod path and version under appropriate section (extensions/receivers/exporters/processors/connectors)
  3. Run make generate-sources to regenerate build files
  4. Run go mod tidy to update dependencies
  5. Run make build to verify
  6. Run make test to ensure tests pass

To update component versions:

  1. Edit distributions/tulip/manifest.yaml - update version numbers
  2. Run make generate to regenerate build files and goreleaser config
  3. Run go mod tidy
  4. Run make test

Important: All components must use compatible versions. OpenTelemetry components version together (contrib at v0.X.0, core at v0.X.0).

Distribution Structure

distributions/tulip/
├── manifest.yaml           # Component manifest (source of truth)
├── config.yaml             # Default runtime configuration
├── Dockerfile              # Container image definition
├── tulip.service           # systemd service file
├── tulip.conf              # systemd environment variables
├── tulip-test.yaml         # Test configuration
├── preinstall.sh           # Creates tulip user/group
├── postinstall.sh          # Enables systemd service
├── preremove.sh            # Stops service before removal
├── .goreleaser.yaml        # Generated by make generate-goreleaser
└── _build/                 # Generated by ocb (not committed)
    ├── components.go       # Component registration
    ├── main.go             # Entry point
    ├── main_others.go      # Unix-specific entry
    ├── go.mod              # Generated module file
    └── tulip               # Compiled binary

Testing Architecture

The test system uses shell scripts that:

  1. Build the distribution
  2. Start the collector with test configuration
  3. Generate test traces
  4. Verify traces are processed
  5. Clean up

Test configuration:

  • Test scripts in test/ directory
  • test/start-otelcol.sh - Uses ${distribution} variable for binary/config names
  • test/test.sh -d tulip - Test single distribution
  • test/test-all.sh - Test all distributions

Critical detail: Test scripts are distribution-agnostic and use the distribution name as a variable for paths (e.g., _build/${distribution}, ${distribution}-test.yaml).

Goreleaser Configuration

The .goreleaser.yaml file in each distribution is generated, not manually edited:

make generate-goreleaser
# Or:
./scripts/generate-goreleaser.sh -d tulip

The generator (cmd/goreleaser/) creates platform-specific build configurations for Linux and macOS across multiple architectures. Tulip is optimized for container-based deployments.

Branding and Naming

When working on Tulip-specific changes:

  • Binary name: tulip
  • Service name: tulip.service
  • Config paths: /etc/tulip/
  • User/group: tulip
  • Docker image: cr.olly.garden/ollygarden/tulip/tulip
  • All references should use "Tulip" or "tulip", not "otelcol" or "otelcol-otlp"

Development Workflow

  1. Make changes to manifest.yaml or other config files
  2. Run make generate (regenerates sources + goreleaser config)
  3. Run go mod tidy (update dependencies)
  4. Run go fmt ./... (format code)
  5. Run make test (verify tests pass)
  6. Stage changes for review (do not commit directly per user instructions)

Release and Packaging Tools

The Tulip build and release process requires several external tools. Some are automatically installed by the Makefile, while others need manual installation.

OpenTelemetry Collector Builder (ocb)

Automatically installed by Makefile - no manual installation needed.

The Makefile will download and install ocb to ~/bin/ocb if it's not found in PATH.

GoReleaser

Required for releases - used to build multi-platform binaries, packages, and container images.

Install goreleaser: https://goreleaser.com/install/

# Using Homebrew (macOS/Linux)
brew install goreleaser

# Or download binary from https://github.com/goreleaser/goreleaser/releases

Verifying Installation

ocb version          # or check ~/bin/ocb
goreleaser --version

Important Notes

  • Do not manually edit files in _build/ directory - they are generated
  • Always run make generate after changing manifest.yaml
  • Component versions must be synchronized - use the same version across all contrib components and across all core components
  • The Makefile automatically installs ocb if not found in PATH
  • Test failures are often due to path/naming issues - check that scripts use distribution name variables correctly