Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,13 @@ web_modules/
out
.nuxt
dist
!internal/ui/dist
!internal/ui/dist/**
# Built UI is NOT committed — it is generated at release time by
# scripts/release.sh and embedded into the tagged commit. Only the .gitkeep
# placeholder is tracked so `//go:embed all:dist` still compiles on a
# source-only checkout.
!internal/ui/dist/
internal/ui/dist/*
!internal/ui/dist/.gitkeep
.cache/
.vuepress/dist
.temp
Expand Down
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
.PHONY: build test vet check setup-hooks ui-install ui-build dev-ui loadtest loadtest-build
.PHONY: build test vet check setup-hooks ui-install ui-build dev-ui loadtest loadtest-build release

ui-install:
cd ui && npm install

ui-build:
cd ui && npm run build
touch internal/ui/dist/.gitkeep # vite emptyOutDir wipes it; keep the source-only placeholder

build: ui-build
CGO_ENABLED=0 go build ./...
Expand All @@ -28,6 +29,12 @@ loadtest: loadtest-build
@echo "Running 200-service load simulator (60s) against localhost:4317..."
./bin/loadsim

## release builds the UI and cuts a tag whose tree embeds it, so
## `go install ...@<tag>` is UI-complete while main stays source-only.
## Usage: make release VERSION=vX.Y.Z [RELEASE=--release]
release:
./scripts/release.sh $(VERSION) $(RELEASE)

## setup-hooks installs the pre-commit hook into .git/hooks
setup-hooks:
cp scripts/pre-commit .git/hooks/pre-commit
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,23 @@ For teams who want traces, logs, and metrics in one place without standing up a
## Quick start

```bash
# 1. Build
go build -o otelcontext .
# 1. Build (Go binary + embedded React UI)
make build # builds the UI, then `go build` with it embedded

# ...or install a released, UI-complete binary directly:
# go install github.com/RandomCodeSpace/otelcontext@latest

# 2. Run with an API key (dev-friendly — SQLite, plaintext HTTP)
export API_KEY="$(openssl rand -hex 32)"
./otelcontext
```

> The built UI is **not** committed — the repo is source-only. A plain
> `go build .` produces a working API/binary but serves no web UI at `/`.
> Use `make build` (or a release tag, which embeds the built UI) for the
> full experience. Maintainers cut releases with `make release VERSION=vX.Y.Z`
> — see [`scripts/release.sh`](scripts/release.sh).

The server listens on:
- OTLP gRPC: `:4317`
- HTTP API + OTLP HTTP + UI + MCP: `:8080`
Expand Down
Empty file added internal/ui/dist/.gitkeep
Empty file.
Binary file not shown.
Binary file not shown.
4 changes: 0 additions & 4 deletions internal/ui/dist/assets/MCPConsoleView-CH5VtsjS.js

This file was deleted.

Binary file not shown.
321 changes: 0 additions & 321 deletions internal/ui/dist/assets/ServicesView-Bb9CYmXY.js

This file was deleted.

1 change: 0 additions & 1 deletion internal/ui/dist/assets/index-DzLWOk_K.css

This file was deleted.

10 changes: 0 additions & 10 deletions internal/ui/dist/assets/index-UdCF7Wgf.js

This file was deleted.

1 change: 0 additions & 1 deletion internal/ui/dist/assets/inputs-DxVBbFvb.js

This file was deleted.

1 change: 0 additions & 1 deletion internal/ui/dist/assets/useMediaQuery-D3Mg-H7H.js

This file was deleted.

14 changes: 0 additions & 14 deletions internal/ui/dist/index.html

This file was deleted.

8 changes: 7 additions & 1 deletion internal/ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ func (s spaFS) Open(name string) (fs.File, error) {
return s.FS.Open("index.html")
}

//go:embed static/* dist
// The built UI is generated at release time (scripts/release.sh) and is not
// committed; only internal/ui/dist/.gitkeep is tracked. The `all:` prefix
// embeds that dotfile so a source-only checkout still compiles. A plain
// `go build` therefore serves no SPA at "/" until the UI is built — release
// tags carry the real dist so `go install <module>@<tag>` is UI-complete.
//
//go:embed static/* all:dist
var content embed.FS

type Server struct {
Expand Down
86 changes: 86 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env bash
#
# scripts/release.sh — cut a release tag whose git tree contains the built UI.
#
# Why this exists
# ---------------
# The binary embeds the React UI via `//go:embed all:dist` in internal/ui, but
# the built dist is intentionally NOT committed to main (main is source-only;
# only internal/ui/dist/.gitkeep is tracked). `go install <module>@<tag>` only
# compiles Go — it never runs vite — so for an installed binary to be
# UI-complete, the *tagged commit* must carry the built dist.
#
# This script builds the UI, creates a DETACHED release commit that includes
# internal/ui/dist, tags it, and pushes ONLY the tag. main is left untouched —
# the release commit is reachable solely through the tag, so no build artifact
# ever lands on the branch.
#
# Usage:
# scripts/release.sh vX.Y.Z[-pre] # build + push tag
# scripts/release.sh vX.Y.Z[-pre] --release # also create a GitHub pre-release
#
set -euo pipefail

VER="${1:-}"
if [[ ! "$VER" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "usage: scripts/release.sh vX.Y.Z[-pre] [--release]" >&2
exit 2
fi
MAKE_RELEASE="${2:-}"

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

# --- Preconditions -----------------------------------------------------------
branch="$(git rev-parse --abbrev-ref HEAD)"
[ "$branch" = "main" ] || { echo "error: must be on main (currently '$branch')" >&2; exit 1; }

Check failure on line 36 in scripts/release.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=RandomCodeSpace_otelcontext&issues=AZ6XdKJ_5wYqrbsp4b77&open=AZ6XdKJ_5wYqrbsp4b77&pullRequest=99
git diff --quiet && git diff --cached --quiet || { echo "error: working tree not clean" >&2; exit 1; }
git fetch origin main --tags --quiet
[ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ] || { echo "error: local main is not in sync with origin/main" >&2; exit 1; }

Check failure on line 39 in scripts/release.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=RandomCodeSpace_otelcontext&issues=AZ6XdKJ_5wYqrbsp4b78&open=AZ6XdKJ_5wYqrbsp4b78&pullRequest=99
if git rev-parse -q --verify "refs/tags/$VER" >/dev/null 2>&1 || git ls-remote --exit-code --tags origin "$VER" >/dev/null 2>&1; then
echo "error: tag $VER already exists (local or remote)" >&2
exit 1
fi

base="$(git rev-parse HEAD)"
# Always restore main to its source-only state, even on failure.
cleanup() { git reset --hard --quiet "$base"; git clean -fdq -- internal/ui/dist >/dev/null 2>&1 || true; }
trap cleanup EXIT

# --- Build the UI ------------------------------------------------------------
echo "▸ building UI (npm ci && npm run build)…"
( cd ui && npm ci && npm run build )
[ -f internal/ui/dist/index.html ] || { echo "error: UI build produced no dist/index.html" >&2; exit 1; }

Check failure on line 53 in scripts/release.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=RandomCodeSpace_otelcontext&issues=AZ6XdKJ_5wYqrbsp4b79&open=AZ6XdKJ_5wYqrbsp4b79&pullRequest=99
touch internal/ui/dist/.gitkeep # vite emptyOutDir wipes it; keep the placeholder

# --- Sanity: the binary compiles with the freshly built dist embedded --------
echo "▸ verifying the binary embeds the UI…"
go build -o /tmp/otelctx-release-check . && rm -f /tmp/otelctx-release-check

# --- Detached release commit carrying the built dist -------------------------
echo "▸ creating release commit + tag $VER…"
git add -f internal/ui/dist
git commit -q -m "release: $VER (built UI embedded; not merged to main)"
git tag -a "$VER" -m "$VER"

# --- Push ONLY the tag (its commit + dist travel with it; main stays clean) ---
git push origin "refs/tags/$VER"
echo "✓ pushed tag $VER -> $(git rev-parse --short "$VER")"

# (the EXIT trap now restores main to the source-only state)

# --- Optional GitHub pre-release --------------------------------------------
if [ "$MAKE_RELEASE" = "--release" ]; then

Check failure on line 73 in scripts/release.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=RandomCodeSpace_otelcontext&issues=AZ6XdKJ_5wYqrbsp4b7-&open=AZ6XdKJ_5wYqrbsp4b7-&pullRequest=99
prev="$(git describe --tags --abbrev=0 "${VER}^" 2>/dev/null || true)"
range="${prev:+${prev}..}${VER}"
notes="$(git log --pretty='- %s' "$range" 2>/dev/null | grep -vE '^- release:' || true)"
gh release create "$VER" --prerelease --title "$VER" --notes \
"Install (UI embedded):
\`\`\`
go install github.com/RandomCodeSpace/otelcontext@$VER
\`\`\`

### Changes
$notes"
echo "✓ created GitHub pre-release $VER"
fi