tulip CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
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-distributionstemplate
Build System Architecture
Component Manifest System
The core of Tulip's architecture is the manifest-driven build system:
-
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
-
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
- Reads
-
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:
- Edit
distributions/tulip/manifest.yaml - Add component with gomod path and version under appropriate section (extensions/receivers/exporters/processors/connectors)
- Run
make generate-sourcesto regenerate build files - Run
go mod tidyto update dependencies - Run
make buildto verify - Run
make testto ensure tests pass
To update component versions:
- Edit
distributions/tulip/manifest.yaml- update version numbers - Run
make generateto regenerate build files and goreleaser config - Run
go mod tidy - 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:
- Build the distribution
- Start the collector with test configuration
- Generate test traces
- Verify traces are processed
- Clean up
Test configuration:
- Test scripts in
test/directory test/start-otelcol.sh- Uses${distribution}variable for binary/config namestest/test.sh -d tulip- Test single distributiontest/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
- Make changes to
manifest.yamlor other config files - Run
make generate(regenerates sources + goreleaser config) - Run
go mod tidy(update dependencies) - Run
go fmt ./...(format code) - Run
make test(verify tests pass) - 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 generateafter changingmanifest.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