Patch-based overlay for integrating Xatu Sidecar observability into Teku.
Temu uses a patch + overlay approach instead of maintaining a full fork. The repo stores only custom code and small patches; upstream Teku is cloned fresh each build.
temu/
├── plugins/ # Custom code (copied into upstream clone)
│ └── xatu/ # Xatu Sidecar plugin for Teku integration
├── patches/
│ └── consensys/teku/
│ └── master.patch # Base patch: gossip hooks, xatu init, CLI flag
├── ci/
│ └── disable-upstream-workflows.sh
├── .github/workflows/
│ ├── check-patches.yml # Daily: verify patches apply + build
│ ├── docker.yml # On push/release: build + push Docker image
│ └── validate-patches.yml # On PR: validate patch file structure
├── scripts/
│ ├── temu-build.sh # Full orchestrator: clone -> patch -> build
│ ├── apply-temu-patch.sh # Apply patches + plugin overlay + deps
│ ├── save-patch.sh # Regenerate patches from modified clone
│ └── validate-patch.sh # Patch file structural validation
├── example-xatu-config.yaml # Xatu configuration template
└── .gitignore # Ignore teku/ working directory
# Full build: clone upstream -> apply patches -> build binary
./scripts/temu-build.sh -r consensys/teku -b master
# The binary will be at teku/build/install/teku/bin/teku# Prepare patched source (skip Gradle build)
./scripts/temu-build.sh -r consensys/teku -b master --skip-build
# Build Docker image using Teku's Gradle distDocker
cd teku && ./gradlew distDocker
# Tag and push (image is produced as consensys/teku:develop)
docker tag consensys/teku:develop ethpandaops/temu:latestcd teku
# Option 1: CLI flag
./build/install/teku/bin/teku --xatu-config /path/to/xatu-config.yaml
# Option 2: Environment variable
XATU_CONFIG=/path/to/xatu-config.yaml ./build/install/teku/bin/teku
# Option 3: System property
java -Dxatu.config=/path/to/xatu-config.yaml -jar build/libs/teku.jarThe configuration file should be based on example-xatu-config.yaml.
| Script | Purpose |
|---|---|
temu-build.sh |
Full orchestrator: clone upstream, apply patches + plugin overlay, build |
apply-temu-patch.sh |
Apply patches to an existing teku clone + copy plugin + deps |
save-patch.sh |
Regenerate patches from a modified teku clone |
validate-patch.sh |
Validate patch file structure (hunk counts, etc.) |
disable-upstream-workflows.sh |
Rename upstream CI workflows to .disabled |
./scripts/temu-build.sh -r <org/repo> -b <branch> [-c <commit>] [--ci] [--skip-build]Options:
-r, --repo: Repository in formatorg/repo-b, --branch: Branch name, tag, or commit hash-c, --commit: Pin to specific upstream commit SHA--ci: CI mode (non-interactive, auto-clean, auto-update patches)--skip-build: Skip./gradlew installDist, exit after applying patches (for Docker CI)
plugins/xatu/ is the Xatu Sidecar plugin module, copied into the upstream clone at build time. It is never part of the patch.
Instead of patching workflow renames, a simple script renames all non-temu workflows to .disabled.
Docker images are built using Teku's built-in ./gradlew distDocker, which produces a consensys/teku:develop image. CI then tags and pushes it as ethpandaops/temu:<tag>. The patch includes modifications to build.gradle (Docker tasks, xatu dependencies) and docker/jdk*/Dockerfile (libxatu.so integration).
The patch includes Java source changes and build configuration:
master.patch: Adds EventChannels for gossip message notifications, xatu plugin initialization hooks,--xatu-configCLI flag, transport peer ID support, build dependencies, Gradle Docker tasks, and Dockerfile libxatu.so integration
Self-contained new code goes in plugins/xatu/. These files are copied verbatim into the upstream clone at build time.
vim plugins/xatu/src/main/java/tech/pegasys/teku/plugin/xatu/NewFeature.java
git add plugins/
git commit -m "feat: add new feature"If your feature requires changing existing upstream Java source:
# 1. Build to get the working upstream clone
./scripts/temu-build.sh -r consensys/teku -b master
# 2. Edit upstream files in the clone
vim teku/networking/eth2/src/main/java/.../Eth2TopicHandler.java
# 3. Regenerate the patch
./scripts/save-patch.sh -r consensys/teku -b master teku
# 4. Commit the updated patch
git add patches/
git commit -m "feat: add new-feature wiring to base patch"When upstream changes the same lines our patches touch, apply-temu-patch.sh will fail. To fix:
# 1. Run the build -- it will show exactly which hunks failed
./scripts/temu-build.sh -r consensys/teku -b master
# 2. Fix the conflicts in the upstream clone
vim teku/networking/eth2/src/main/java/.../Eth2TopicHandler.java
# 3. Regenerate the patch
./scripts/save-patch.sh -r consensys/teku -b master teku
# 4. Commit the updated patch
git add patches/
git commit -m "fix: update patches for upstream changes"Temu uses a plugin-based architecture to integrate Xatu with Teku:
-
Core Changes: Minimal modifications to Teku core:
- Event system extensions for gossip message notifications
- Plugin initialization hooks
-
Xatu Plugin: Complete observability implementation:
- Subscribes to gossip message events via EventChannels
- Uses JNA to call into libxatu.so native library
- Handles event batching and delivery
-
Native Library: libxatu.so (from xatu-sidecar):
- Provides efficient event processing
- Handles network delivery to Xatu server
| Workflow | Trigger | What it does |
|---|---|---|
check-patches.yml |
Daily (cron) | Clones upstream, applies patches, builds. Auto-commits if patches needed updating |
docker.yml |
Push to master / release | Builds via ./gradlew distDocker, tags + pushes multi-arch image to ethpandaops/temu:<tag> |
validate-patches.yml |
PR | Validates patch file structure (hunk counts, etc.) |
- Java 21+ (Eclipse Temurin recommended)
- Gradle (wrapper included in Teku)
- Git
- Bash
- GitHub CLI (
gh) for release creation in CI