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
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ jobs:
path: coverage/
retention-days: 7

# ── Memleak (valgrind on Debian Trixie) ──────────────────────────────────
memleak:
runs-on: ubuntu-latest
container:
image: debian:trixie-slim
options: --security-opt seccomp=unconfined
needs: test
steps:
- name: Install valgrind and toolchain deps
run: |
apt-get update
apt-get install -y --no-install-recommends \
valgrind git curl xz-utils ca-certificates make gpg
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Run memleak gate
run: make memleak

# ── Cross-compile: verify pure-Zig on Linux + macOS targets ──────────────
cross-compile:
runs-on: ubuntu-latest
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [0.1.1] - 2026-03-08

### Changed

- CI workflow now runs on pull requests only (`lint`, `test`, `coverage`, `cross-compile`), avoiding duplicate reruns on merge to `main`
- Release workflow now runs on tag pushes only and performs its own sequential gates (`verify-version` -> `lint` -> `test` -> `cross-compile` -> `coverage`) before publishing
- Coverage make target renamed from `test-coverage` to `coverage`; removed `test-depth` gate
- Documentation streamlined: removed hardcoded README version text, simplified usage/architecture sections, and reduced version-specific maintenance text

### Fixed

- `verify-fetchable` now creates a deterministic temp workspace and valid Zig project files before `zig fetch --save`
- `build.zig.zon` package name in smoke test now uses a valid bare Zig identifier (`.fetch_test`)
- Release workflow version parsing accepts both `x.y` and `x.y.z`

## [0.1.0] - 2026-03-08

### Added
Expand Down Expand Up @@ -55,3 +70,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Caller latency test threshold adjusted to avoid flaky failures under machine load while preserving the p99 hot-path guard

[0.1.0]: https://github.com/usezombie/posthog-zig/releases/tag/v0.1.0
[0.1.1]: https://github.com/usezombie/posthog-zig/releases/tag/v0.1.1
14 changes: 9 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
ZIG_GLOBAL_CACHE_DIR ?= $(CURDIR)/.tmp/zig-global-cache
ZIG_LOCAL_CACHE_DIR ?= $(CURDIR)/.tmp/zig-local-cache
COVERAGE_MIN_LINES ?= 60
MEMLEAK_TARGET ?= x86_64-linux

.DEFAULT_GOAL := help

Expand Down Expand Up @@ -60,11 +61,11 @@ test-integration: ## Run integration tests against live PostHog (requires POSTH

# ── Coverage ─────────────────────────────────────────────────────────────────

test-bin: ## Build test binary for kcov
test-bin: ## Build test binary for kcov / memleak
@mkdir -p "$(ZIG_GLOBAL_CACHE_DIR)" "$(ZIG_LOCAL_CACHE_DIR)"
@ZIG_GLOBAL_CACHE_DIR="$(ZIG_GLOBAL_CACHE_DIR)" \
ZIG_LOCAL_CACHE_DIR="$(ZIG_LOCAL_CACHE_DIR)" \
zig build test-bin
zig build test-bin $(if $(TARGET),-Dtarget=$(TARGET),)

coverage: ## Run kcov coverage + enforce minimum threshold
@command -v kcov >/dev/null 2>&1 || { echo "✗ kcov required (brew install kcov / apt-get install kcov)"; exit 1; }
Expand Down Expand Up @@ -95,21 +96,24 @@ bench: ## Benchmark capture() hot-path latency

memleak: ## Run allocator leak gate
@echo "→ Running allocator leak gate..."
@$(MAKE) test-bin
@case "$$(uname -s)" in \
Linux) \
$(MAKE) test-bin TARGET="$(MEMLEAK_TARGET)"; \
command -v valgrind >/dev/null 2>&1 || { echo "✗ valgrind required on Linux"; exit 1; }; \
valgrind --quiet --leak-check=full --show-leak-kinds=all \
POSTHOG_MEMLEAK_MODE=1 valgrind --quiet --leak-check=full --show-leak-kinds=all \
--errors-for-leak-kinds=definite,possible --error-exitcode=1 \
zig-out/bin/posthog-tests;; \
Darwin) \
$(MAKE) test-bin; \
if command -v leaks >/dev/null 2>&1; then \
MallocStackLogging=1 leaks -atExit -- zig-out/bin/posthog-tests >/dev/null || \
echo "→ leaks unavailable in this runtime (allocator gate only)"; \
else \
echo "→ leaks not found; allocator gate only"; \
fi;; \
*) echo "→ platform=$$(uname -s): allocator gate only";; \
*) \
$(MAKE) test-bin; \
echo "→ platform=$$(uname -s): allocator gate only";; \
esac
@echo "✓ memleak gate passed"

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1
0.1.1
2 changes: 1 addition & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.{
.name = .posthog,
.version = "0.1.0",
.version = "0.1.1",
.fingerprint = 0xa5fe060596d90b43,
.minimum_zig_version = "0.15.0",
.dependencies = .{},
Expand Down
5 changes: 4 additions & 1 deletion src/client.zig
Original file line number Diff line number Diff line change
Expand Up @@ -431,5 +431,8 @@ test "integration: capture is non-blocking (avg < 1ms per call for 1000 events)"
const elapsed_ns = std.time.nanoTimestamp() - start;
const avg_ns = @divFloor(elapsed_ns, 1000);

try std.testing.expect(avg_ns < 1_000_000); // < 1ms per call
// Valgrind instrumentation in memleak mode adds heavy runtime overhead.
const in_memleak_mode = std.posix.getenv("POSTHOG_MEMLEAK_MODE") != null;
const max_avg_ns: i128 = if (in_memleak_mode) 50_000_000 else 1_000_000;
try std.testing.expect(avg_ns < max_avg_ns);
}