Run it
How it works
Fifty-six lines. Open.aspect/observe.axl and read it top to bottom.
bazel rather than ctx.bazel: the iterator exists before any build does, which is the point — subscribe first, then start the build. Bazel emits events from the moment it starts; a subscription made afterwards misses them.
kinds is the filter. A real build publishes thousands of events across dozens of kinds; this task wants one kind, so it asks for one kind.
flags is where Bazel flags go. A task’s own arguments are the ones it declares — type --nocache_test_results on the command line and the CLI will reject it, because observe never said it took such a thing. This one is built in: a cached test publishes a result without running, and there is nothing to watch in that.
Each test_summary carries the label on event.id and the outcome on event.payload:
The task collects during the build and prints afterwards, so its output never lands in the middle of Bazel’s. Bazel owns the terminal until it exits.
Your turn
Run it against a test that fails sometimes:internal/domain/forecast has a deliberately flaky test — it fails about one run in three. Run it a few times and you will see failed instead of passed.
You will not see flaky. That status only exists when Bazel retries a failing test and the retry passes, and nothing here has asked it to.
That is the next section.
Next: you won’t ship this.
