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
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- run: make lint

# ── Unit tests ────────────────────────────────────────────────────────────
Expand All @@ -22,11 +22,11 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- run: make test-unit

# ── Line coverage (llvm-cov + Codecov) ──────────────────────────────────
# kcov v43 cannot parse Zig 0.15.x DWARF (DWARF v5 incompatibility).
# kcov v43 cannot parse Zig 0.16.x DWARF (DWARF v5 incompatibility).
# llvm-cov is attempted; falls back to a synthetic placeholder report
# (2.20%) if the binary lacks profiling instrumentation.
coverage:
Expand All @@ -40,7 +40,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- name: Run coverage gate
run: make coverage
- name: Upload to Codecov
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- name: Run memleak gate
run: make memleak

Expand All @@ -95,7 +95,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- name: Build ${{ matrix.target }}
run: zig build -Dtarget=${{ matrix.target }} -Doptimize=ReleaseSafe
- name: Verify no external C deps
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- run: make lint

test:
Expand All @@ -51,7 +51,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- run: make test-unit

cross-compile:
Expand All @@ -68,7 +68,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- name: Build ${{ matrix.target }}
run: zig build -Dtarget=${{ matrix.target }} -Doptimize=ReleaseSafe
- name: Verify no external C deps
Expand Down Expand Up @@ -96,7 +96,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- name: Run coverage gate
run: make coverage
- name: Upload to Codecov
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
- uses: actions/checkout@v6
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
version: 0.16.0
- name: Create temp fetch workspace
run: |
FETCH_DIR="$(mktemp -d /tmp/posthog-fetch-XXXXXX)"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ zig-out/
.tmp/
coverage/
*.env
# Worktree-local mise toolchain pins (CI workflow is the source of truth for Zig version)
mise.toml
.mise.toml
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [0.2.0] - 2026-04-20

### Breaking

- `posthog.init(...)` now takes an `io: std.Io` argument between `allocator` and `config`. Pass `posthog.defaultIo()` if you have no opinion, or your own `std.Io.Threaded` for concurrency policy. Zig 0.15.2 users: pin posthog-zig `0.1.x` — see [`docs/v1/ZIG_0_15_COMPAT.md`](docs/v1/ZIG_0_15_COMPAT.md).
- Minimum Zig version is now `0.16.0`. `0.15.x` is no longer supported on the `0.2.x` line.

### Changed

- Internal concurrency primitives migrated to Zig 0.16's `std.Io`: `std.Thread.Mutex/Condition` -> `std.Io.Mutex` + `std.Io.Event` (the flush-thread wake signal is an Event because `Io.Condition` has no `timedWait` in 0.16).
- HTTP transport routes through `std.http.Client{ .allocator, .io }`; `postBatch` / `postDecide` gained an `io` parameter.
- Retry jitter uses a threadlocal `std.Random.DefaultPrng` seeded from `Io.Clock.awake.now`; `std.crypto.random` is gone in 0.16.
- Environment reads and monotonic/real-time clock reads go through `std.Options.debug_threaded_io` (`std.posix.getenv` and `std.time.{milli,nano}Timestamp` were removed in 0.16).
- CI workflows pinned to Zig `0.16.0`.

### Added

- `posthog.defaultIo()` convenience accessor returning the process-wide default `Io`.
- `docs/v1/ZIG_0_15_COMPAT.md` explaining how to pin `0.1.x` for Zig 0.15.2 users.
- `docs/v1/MIGRATION_ZIG_0_16.md` documenting every 0.15 -> 0.16 breakage this library hit.

### Verified

- 73/73 tests pass on Zig 0.16.0 (50 unit + 18 caller simulation + 5 live-PostHog integration).
- Cross-compile clean on `x86_64-linux`, `aarch64-linux`, `x86_64-macos`, `aarch64-macos`.
- `make memleak` green on darwin.

## [0.1.3] - 2026-03-08

### Changed
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
[![ci](https://github.com/usezombie/posthog-zig/actions/workflows/ci.yml/badge.svg)](https://github.com/usezombie/posthog-zig/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/usezombie/posthog-zig/branch/main/graph/badge.svg)](https://codecov.io/gh/usezombie/posthog-zig)
[![version](https://img.shields.io/github/v/tag/usezombie/posthog-zig?label=version&sort=semver)](https://github.com/usezombie/posthog-zig/tags)
[![zig](https://img.shields.io/badge/zig-0.15.x-orange)](https://ziglang.org)
[![zig](https://img.shields.io/badge/zig-0.16.x-orange)](https://ziglang.org)
[![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)

A server-side PostHog analytics client for Zig. Non-blocking event capture with background batch delivery, retry, and graceful shutdown.

**Zig:** 0.15.x
**Zig:** 0.16.x (current). For 0.15.2 users, pin posthog-zig `0.1.x` — see [`docs/v1/ZIG_0_15_COMPAT.md`](docs/v1/ZIG_0_15_COMPAT.md).
**PostHog API:** `/batch/` (capture) + `/decide/` v3 (feature flags)

---
Expand Down Expand Up @@ -70,7 +70,11 @@ const posthog = @import("posthog");

// Init — heap-allocates client, spawns background flush thread.
// Heap allocation ensures &client.queue is a stable address for the flush thread.
const client = try posthog.init(allocator, .{
//
// Zig 0.16 threads `std.Io` through every concurrency primitive. Pass
// `posthog.defaultIo()` to use the process-wide Io, or your own Io.Threaded
// instance if you want control over concurrency policy.
const client = try posthog.init(allocator, posthog.defaultIo(), .{
.api_key = "phc_...",
.host = "https://us.i.posthog.com", // default
.enable_logging = true, // default
Expand Down Expand Up @@ -155,8 +159,10 @@ pub fn main() !void {

// Init — spawns background flush thread.
// Pass null api_key to disable analytics (e.g. when env var is absent).
if (std.posix.getenv("POSTHOG_API_KEY")) |key| {
ph_client = try posthog.init(allocator, .{ .api_key = key });
// 0.16: std.posix.getenv was removed; read via the Threaded Io's Environ.
const env = std.Options.debug_threaded_io.?.environ.process_environ;
if (env.getPosix("POSTHOG_API_KEY")) |key| {
ph_client = try posthog.init(allocator, posthog.defaultIo(), .{ .api_key = key });
}
defer if (ph_client) |c| c.deinit(); // deinit frees the heap-allocated client // drains queue on SIGTERM / clean exit

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.3
0.2.0
2 changes: 1 addition & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub fn build(b: *std.Build) void {
},
}),
});
b.step("test", "Run unit + integration tests").dependOn(&b.addRunArtifact(int_tests).step);
test_step.dependOn(&b.addRunArtifact(int_tests).step);
}

// ── Test binary for kcov coverage ────────────────────────────────────────
Expand Down
12 changes: 10 additions & 2 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
.{
.name = .posthog,
.version = "0.1.3",
.version = "0.2.0",
.fingerprint = 0xa5fe060596d90b43,
.minimum_zig_version = "0.15.0",
.minimum_zig_version = "0.16.0",
.dependencies = .{},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"tests",
// Enumerate user-facing docs individually — shipping all of `docs/`
// would drag in `docs/v1/{pending,active,done}/` project-management
// specs and `docs/nostromo/` agent logs that are of no use to
// downstream consumers.
"docs/ARCHITECTURE.md",
"docs/v1/MIGRATION_ZIG_0_16.md",
"docs/v1/ZIG_0_15_COMPAT.md",
"README.md",
"CHANGELOG.md",
"LICENSE",
},
}
Empty file added docs/nostromo/.gitkeep
Empty file.
Loading
Loading