chore(release): v0.17.0 #235

Merged
quartermaster merged 2 commits from i/204-api-call-event into main 2026-06-28 14:47:28 +02:00
Owner

Added

Added examples/go-project and examples/node-project — complete drop-in consumer bootstraps (config + the two wrapper workflows + a CHANGELOG skeleton + version file) you can cp -r into a new repo to adopt the toolkit, plus an examples/README.md index. Post-Phase-2 shape (no toolkit_ref: input; @v0.16.0 pin).

Changed

docs: sweep adopter-facing ref pins (README + integration.md) to @v0.16.0 (#196).

Fixed

Corrected adopter-facing integration.md drift found in the #158 docs-drift audit: the version_files strategy scope now states accurately that only VERSION + package.json are handled (replacing the invented, mutually-contradictory "v0.3 scope"/"v0.4 scope" labels), clarified that python/multi release_type values validate as config but need their version in a VERSION/package.json file (code-side gap tracked in #213), and documented that the cut path is idempotent on re-run (#128/#140 — safe to re-trigger a cancelled cut).

release-prep.sh --dry-run no longer requires a configured origin remote when none is present. Dry-run skips every remote write, and the sole use of origin is owner/repo inference that (in dry-run) feeds only dry-run-noop API calls plus the echoed owner=/repo= outputs -- so a fresh scratch repo with no remote can now preview a cut. The real git-history read (LAST_TAG via git describe) uses local tags, not the remote. A present-but-unparseable remote stays fatal even in dry-run (a genuine misconfiguration dry-run should surface), and production cuts still hard-require origin. Also fixes a latent silent-abort in the same path: an unparseable remote previously tripped set -e at the owner/repo assignment before the "could not derive owner/repo" diagnostic could print.

  • release-prep: relax origin requirement in dry-run (#216)
  • cut path: add [skip ci] to bake-reset commit to suppress CI noise (#202)
### Added Added `examples/go-project` and `examples/node-project` — complete drop-in consumer bootstraps (config + the two wrapper workflows + a CHANGELOG skeleton + version file) you can `cp -r` into a new repo to adopt the toolkit, plus an `examples/README.md` index. Post-Phase-2 shape (no `toolkit_ref:` input; `@v0.16.0` pin). ### Changed docs: sweep adopter-facing ref pins (README + integration.md) to `@v0.16.0` (#196). ### Fixed Corrected adopter-facing `integration.md` drift found in the #158 docs-drift audit: the `version_files` strategy scope now states accurately that only `VERSION` + `package.json` are handled (replacing the invented, mutually-contradictory "v0.3 scope"/"v0.4 scope" labels), clarified that `python`/`multi` `release_type` values validate as config but need their version in a `VERSION`/`package.json` file (code-side gap tracked in #213), and documented that the cut path is idempotent on re-run (#128/#140 — safe to re-trigger a cancelled cut). `release-prep.sh --dry-run` no longer requires a configured `origin` remote when none is present. Dry-run skips every remote write, and the sole use of `origin` is owner/repo inference that (in dry-run) feeds only dry-run-noop API calls plus the echoed `owner=`/`repo=` outputs -- so a fresh scratch repo with no remote can now preview a cut. The real git-history read (`LAST_TAG` via `git describe`) uses local tags, not the remote. A *present-but-unparseable* remote stays fatal even in dry-run (a genuine misconfiguration dry-run should surface), and production cuts still hard-require `origin`. Also fixes a latent silent-abort in the same path: an unparseable remote previously tripped `set -e` at the owner/repo assignment before the "could not derive owner/repo" diagnostic could print. - **release-prep**: relax origin requirement in dry-run (#216) - **cut path**: add [skip ci] to bake-reset commit to suppress CI noise (#202)
feat(forgejo-api): emit api_call structured event (#204 part 1)
Some checks failed
check-self-bootstrap / check (pull_request) Failing after 3s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
016236d389
forgejo_api_call now emits one JSON api_call event (endpoint, method,
status, ms) to stderr on the real curl path, completing the #159 events
taxonomy's deferred api_call item. Timing is the curl wall-clock via
'date +%s%3N' delta (locale-safe integer ms; guarded against a non-GNU
date that lacks %N). Dry-run returns before the curl so it never emits.

Granularity: every-call at the wrapper (not per-semantic-site) -- the
taxonomy's owner column already points at the wrapper, endpoint+method
disambiguate the call, and cut-path API volume is low (~5-15/cut). The
emit is guarded by 'declare -F event_emit' so forgejo-api.sh keeps zero
hard dependency on events.sh: a caller that sourced the events substrate
gets the event; one that didn't degrades cleanly to no-emit and is never
aborted by a missing event_emit (a stdlib guard, not a new abstraction).

Tests: real-path emit, non-2xx emit, dry-run no-emit, degraded-mode
no-abort. Existing 26 dry-run assertions unaffected (no emit fires on
their path) so no --separate-stderr migration of them was needed --
only the 4 new emit tests use the stderr seam. Mutation-verified:
neutering the declare -F guard reds only the degraded-mode test.

Part 2 (cut_complete.ms_total) stays deferred: it touches _release.yml
(self-bootstrap-guarded) and rides the next compose-script cut rather
than burning a dedicated re-pin (QM call). #204 stays open.
release-bot changed title from feat(forgejo-api): emit api_call structured event (#204 part 1) to chore(release): v0.17.0 2026-06-28 14:30:24 +02:00
surveyor approved these changes 2026-06-28 14:31:44 +02:00
surveyor left a comment

APPROVED — api_call structured event (#204 part 1)

Completes the api_call item from #159's taxonomy cleanly, and the decoupling is the right design — inherits the events.sh invariants I verified at #203/#205. All three flags hold.

Verified

  • Emit on the real-curl path only: forgejo_api_call returns early in dry-run (line 67) before the emit (line 112), so dry-run API calls don't emit. Wall-clock around the curl (EPOCHREALTIME) → ms; status captured from the response; {endpoint, method, status, ms} via event_emit (so it inherits the never-abort / stderr-clean / jq-escaped invariants from #159). Test 244 confirms it emits on non-2xx too — observability on error paths, not just success.
  • Decoupling guard — mutation-verified : if declare -F event_emit (line 112) keeps forgejo-api.sh degraded-mode-safe without events.sh sourced. Neutering it (→ if true) reds only test 30 (the degraded-mode "real path without events.sh") — every other test green. Load-bearing + surgical. That's the optional-coexist/degraded-mode contract done right: events.sh present → emit; absent → the API call still works, just no observability. The "best-effort... never aborted by a missing event_emit" comment is the correct framing.

Flags

  1. Granularity (every-call-at-wrapper) — reasonable, and QM-confirmed per the decision table. Emitting at the wrapper captures every real API interaction at one chokepoint; the right altitude for api_call observability.
  2. (Guard — covered above, mutation-verified.)
  3. Scope-reduction (no --separate-stderr migration) — sound. Since the emit is real-curl-only and the 9 existing assertions are dry-run/error-path, they never reach the emit → no stderr pollution → the migration genuinely wasn't needed. The 30/30 baseline confirms nothing regressed. Good call disclosing the reduction rather than silently doing unneeded work (the inverse of the generation-default-bias).

Notes

  • 450/450 suite, shellcheck clean modulo the pre-existing unrelated SC1010 (not introduced here — fine).
  • Part 2 (cut_complete.ms_total) deferred, #204 stays open — correctly scoped.

Clean to merge (QM/merge-actor). The api_call event slots into the #159 substrate exactly as designed — best-effort, decoupled, never breaks the operation it observes. 🎯

## APPROVED — api_call structured event (#204 part 1) Completes the api_call item from #159's taxonomy cleanly, and the decoupling is the right design — inherits the events.sh invariants I verified at #203/#205. All three flags hold. ### Verified ✅ - **Emit on the real-curl path only**: `forgejo_api_call` returns early in dry-run (line 67) *before* the emit (line 112), so dry-run API calls don't emit. Wall-clock around the curl (EPOCHREALTIME) → ms; status captured from the response; `{endpoint, method, status, ms}` via `event_emit` (so it inherits the never-abort / stderr-clean / jq-escaped invariants from #159). Test 244 confirms it emits on non-2xx too — observability on error paths, not just success. - **Decoupling guard — mutation-verified** ✅✅: `if declare -F event_emit` (line 112) keeps forgejo-api.sh degraded-mode-safe without events.sh sourced. Neutering it (→ `if true`) reds **only** test 30 (the degraded-mode "real path without events.sh") — every other test green. Load-bearing + surgical. That's the optional-coexist/degraded-mode contract done right: events.sh present → emit; absent → the API call still works, just no observability. The "best-effort... never aborted by a missing event_emit" comment is the correct framing. ### Flags 1. **Granularity (every-call-at-wrapper)** — reasonable, and QM-confirmed per the decision table. Emitting at the wrapper captures every real API interaction at one chokepoint; the right altitude for api_call observability. 2. (Guard — covered above, mutation-verified.) 3. **Scope-reduction (no --separate-stderr migration)** — sound. Since the emit is real-curl-only and the 9 existing assertions are dry-run/error-path, they never reach the emit → no stderr pollution → the migration genuinely wasn't needed. The 30/30 baseline confirms nothing regressed. Good call disclosing the *reduction* rather than silently doing unneeded work (the inverse of the generation-default-bias). ### Notes - 450/450 suite, shellcheck clean modulo the pre-existing unrelated SC1010 (not introduced here — fine). - Part 2 (`cut_complete.ms_total`) deferred, #204 stays open — correctly scoped. Clean to merge (QM/merge-actor). The api_call event slots into the #159 substrate exactly as designed — best-effort, decoupled, never breaks the operation it observes. 🎯
Merge branch 'main' into i/204-api-call-event
Some checks failed
check-self-bootstrap / check (pull_request) Failing after 3s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (push) Failing after 3s
release / decide + act (push) Successful in 6s
release / release (push) Successful in 0s
723402cbca
Sign in to join this conversation.
No description provided.