Skip to content

v0.4.0

Choose a tag to compare

@Uaghazade1 Uaghazade1 released this 14 Aug 20:11
· 29 commits to main since this release

If you installed on Coolify, your tracker script was never being served. Upgrade,
and check it:

curl -o /dev/null -w '%{http_code}\n' https://c.<your-domain>/oa.js   # 200, not 404

An ordinary docker-compose.yml install was never affected and needs nothing beyond
the usual:

git fetch --tags && git checkout v0.4.0
cd infra/selfhost && ./upgrade.sh

The bug, and why nothing caught it

tracker-build is the shared Dockerfile's build stage. That stage copied apps,
packages and the manifests, and not scripts/ — while pnpm run tracker:build
is node scripts/build-tracker.mjs. The stock compose never noticed, because it
bind-mounts that directory from your checkout and passes an explicit command.

A one-click platform install has neither. So the container inherited the build
stage's default command, which is a bare node: it read EOF from a closed stdin and
exited 0. A one-shot reporting success, with the shared volume left empty and
nothing written anywhere to say so.

Nothing would have served the file even if it had been built. The collector mounts
/v1/tracker, /v1/events and /v1/realtime and no static route; on the stock
compose Caddy serves /oa.js from the volume, and the platform variants have no
Caddy. Meanwhile the dashboard hands every new site
<script src="${COLLECTOR_BASE_URL}/oa.js">.

The result: a Coolify install from v0.3.0 through v0.3.2 had a working dashboard, a
working api and working ingest, and a snippet that could not load. The end-to-end
proof that shipped with those releases passed because it posted events directly to
/v1/events and never fetched the script.

Both halves are fixed

The build. The build stage copies scripts/, builds the bundle, and asserts it is
non-empty. A missing bundle now fails where the image is built rather than where it
is served, which is the same rule the APP guard beside it has always followed.

The serving. apps/collector/src/tracker-script.ts reads the bundle once at boot
and answers GET /oa.js with the headers Caddyfile:93-114 already set, for the same
reasons: one hour of freshness, an ETag that revalidates to a bodyless 304, and
the copy precompressed once at startup so the bytes on the wire are the bytes the
size budget measured. The two encodings get different tags, so a shared cache cannot
hand gzip to a client that asked for none.

With no bundle the route is not mounted at all. An empty 200 is the worst answer
available here: every visitor's browser would cache "the tracker is nothing" for an
hour. A 404 is a miss an operator can see.

What changed for whom

  • Stock compose: nothing. Caddy still serves /oa.js from the volume and never
    forwards it, so the new route is unreachable there. tracker-build and the
    tracker volume stay exactly as they were.
  • Coolify and the other one-click platforms: docker-compose.coolify.yml drops
    tracker-build and the tracker volume, which now do nothing. That install pulls
    nine images instead of ten and ends with twelve containers, two of them
    exited
    rather than thirteen and three.

Images

Ten, published to ghcr.io/openlabs-so/openanalytics and tagged v0.4.0: migrate,
tracker-build, api, collector, worker, query-gateway, realtime, web,
clickhouse, valkey. amd64. On arm64, build them instead: same compose file, one
flag.

Every one of them now carries the tracker bundle, because the runtime stage copies
the build stage wholesale and ten kilobytes is not worth a second stage to keep out
of the five that do not serve it.

A minor rather than a patch, by RELEASING.md:
the shape of a compose file an operator may have overridden changed.

Full changelog: v0.3.2...v0.4.0