Skip to content

T-21168 Add an E2E test of the example project on the oldest, newest and pre-release Go - #6

Merged
PetrHeinz merged 1 commit into
mainfrom
claude/t-21168-slog-betterstack-e2e
Nov 5, 2026
Merged

PetrHeinz merged 1 commit into
mainfrom
claude/t-21168-slog-betterstack-e2e

Conversation

@PetrHeinz

Copy link
Copy Markdown
Member

Adds an end-to-end test (.github/workflows/e2e.yml) that proves the client still delivers logs to Better Stack, daily at 08:00 UTC and on every push to main and pull request. Same shape as the E2E workflows of the other Better Stack clients.

What a run does. A plan job (e2e/plan.sh) resolves three legs:

  • floor: the Go of go.mod's go directive (1.21, setup-go installs its newest patch release) with the slog-common version go.mod requires (v0.22.0).
  • latest: the newest stable Go on go.dev (the job name carries the exact release) with the newest slog-common release on the Go module proxy.
  • canary: the newest Go release candidate or beta when one is newer than the stable release, and slog-common's newest pre-release when there is one. While no Go pre-release is newer, the canary runs the stable release again and its job name says so.

Every leg builds the example with e2e/example.sh build and then proves that the binary is the planned one: go version -m on the binary names the Go it was built with and every module compiled in, and go list -m -json names where the client came from. The Go must match the plan, slog-common must be exactly the planned version, and the client must be the checkout (the main module, Dir is the workspace) or, on the schedule, exactly the planned release from the module cache, not replaced. The versions go into the job summary. Then the job creates its own source through the Telemetry API (e2e-slog-gh<run>a<attempt>-<leg>, platform go), warms it up until ingest accepts the token, runs the example with that source, reads the stored rows back through the testing team's SQL API connection and checks them exactly against e2e/expected.json (the three records the example sends: level, message, logger.name and the attributes under extra), then deletes the source and any e2e-slog- source older than three hours. A failure on main or on the schedule files a Linear issue to Petr through notify_linear_failure.yml, at low priority when only the canary failed, and comments on the open issue instead of filing a second one while the same failure persists. Pull requests from forks and from Dependabot run only the plan, they get no secrets. The existing dependabot.yml stays as it is.

How the client gets into the example. example-project/ is a package of this module (it has no go.mod of its own), so on pushes and pull requests it builds the way its doc comment tells customers to run it, go run ./example-project from the repository root, and compiles the checkout's code. The latest and canary legs move slog-common with go get at job time. On the daily schedule the job builds the example the way a customer's own program builds: it copies the example into a module of its own outside the checkout and runs go get for the newest slog-betterstack release on the module proxy and the leg's slog-common, so it tests what a customer gets today, and the floor comes from that release's go.mod. Nothing about the example's layout changes.

Dispatch lets you run one leg, build against the newest release instead of the checkout, or pin an exact Go (e.g. 1.24.5 or 1.28rc1) or slog-common version, to bisect a failure to one release.

Plumbing. The Better Stack steps are composite actions under .github/actions/ (create-source, verify-logs, cleanup-sources, bash with curl and jq, the logic in run.sh files that run the same way outside Actions) and the reusable Linear notifier, the same files as in the other client repositories.

Example project.

  • It reads BETTER_STACK_SOURCE_TOKEN and BETTER_STACK_INGESTING_HOST, the names every other Better Stack client example uses, instead of BETTERSTACK_SOURCE_TOKEN and BETTERSTACK_INGESTING_HOST. The old names are not read any more: it is a program run by hand once, and the Go docs do not mention them. Both are required now, and the example exits 1 with a usage line when either is missing.
  • It sends one record per level it logs at, all with the logger's release attribute: an info record, a warning with a user group and a list, and an error with a wrapped error value under error (slog-common records its kind and message, it has no stack trace to offer). A debug record stays below the handler's Level: slog.LevelInfo, so the read-back also proves that it is not sent.
  • It already closed the handler before exiting. It now also exits 1 when the handler's Stats show that Better Stack did not accept every record, so a rejected batch fails the run.

The README shows no run command, so it is unchanged; the run command in the example's doc comment follows the new names.

Verified locally against Petr's testing team by running the composite actions' run.sh files and e2e/example.sh the way the workflow does (Go 1.26.10, the checkout): source created and warmed up, the example's three rows read back and matched exactly once each, source deleted. The schedule's build against slog-betterstack v1.5.1 and the failure paths of the version checks were run locally too.

🤖 Generated with Claude Code

…and pre-release Go

e2e.yml plans three legs with e2e/plan.sh (floor: go.mod's go directive and
slog-common requirement, latest: newest stable Go and slog-common, canary:
the newest Go pre-release when one is newer), builds the example with
e2e/example.sh and checks the binary's Go and modules against the plan,
then sends the example's records to a fresh source and reads them back
exactly against e2e/expected.json. The plumbing under .github/actions and
the Linear notifier are the shared files of the other client repositories.

The example reads BETTER_STACK_SOURCE_TOKEN and BETTER_STACK_INGESTING_HOST,
exits 1 with a usage line when either is missing, logs one record per level
with grouped attributes and a wrapped error, and exits 1 when Better Stack
did not accept every record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PetrHeinz
PetrHeinz marked this pull request as ready for review November 5, 2026 17:26
@PetrHeinz
PetrHeinz merged commit 18b8184 into main Nov 5, 2026
14 checks passed
@PetrHeinz
PetrHeinz deleted the claude/t-21168-slog-betterstack-e2e branch November 5, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant