chore(workflows): add temporary debug-event-payload.yml probe — #41 disposition (A) #42

Merged
quartermaster merged 2 commits from i/41-event-payload-probe into main 2026-06-24 22:52:32 +02:00

Per Surveyor e455 forward-input on #41:

(A) probe the Forgejo pull_request.closed payload first — root-cause WHY head.ref is empty BEFORE choosing a fix. Don't fix on hypothesis.

What this PR does

Adds a TEMPORARY diagnostic workflow at .forgejo/workflows/debug-event-payload.yml that fires on every pull_request.closed event against main + logs:

  1. Event metadataevent_name, ref_name, ref, sha
  2. Component evaluations mirroring the consumer-side release-draft.yml line 28 expression, each piece logged separately so the empty-one is visible:
    • github.event.pull_request.merged
    • github.event.pull_request.head.ref
    • github.event.pull_request.head.label
    • github.event.pull_request.head.sha
    • startsWith(head.ref, 'release-prep/') gate result
  3. Full github.event JSON via toJSON() — canonical payload for ground-truth reference

What this PR does NOT do

  • Doesn't apply any fix. Pure probe. Per disposition (A) discipline: probe first; fix lands in v0.3.4 once root cause is known.
  • Doesn't modify release-draft.yml. Consumer-side fix is the right-layer primary; lands when we know what to fix.
  • Doesn't filter to release-prep heads only. Baselines what head.ref looks like across different head shapes (non-release-prep PRs as control).

Lifecycle (load-bearing)

This is TEMPORARY scaffolding. Once #41 is root-caused + the right-layer fix lands, this workflow will be REMOVED in a follow-up PR. Tracked on #41. If the file lives past v0.3.4 it's a process bug.

Meta-note on file naming

Initial commit named the file _debug-event-payload.yml. Caught my own convention mistake at the rename commit — _ prefix is for REUSABLE workflows (called via uses:); consumer-side direct-firing workflows don't get the prefix (see release.yml, release-draft.yml, manifest-check.yml). Same today's-signature meta-recursion shape (ship the discipline, violate the sibling), caught at-commit-time this time, not post-PR. Discipline firing forward.

Sprint context

v0.3.3 patch sprint, slice 1/2. Next slice: #35 fragment-kind vs change-type lint.

Surveyor: per standing review delegation. Operator standing-merge-delegation applies post-APPROVED.

Tracker: #41 disposition (A).

Per [Surveyor e455 forward-input on #41](https://git.frankenbit.de/frankenbit/release-toolkit/issues/41#issuecomment-73602): > (A) probe the Forgejo pull_request.closed payload first — root-cause WHY head.ref is empty BEFORE choosing a fix. Don't fix on hypothesis. ## What this PR does Adds a TEMPORARY diagnostic workflow at `.forgejo/workflows/debug-event-payload.yml` that fires on every `pull_request.closed` event against main + logs: 1. **Event metadata** — `event_name`, `ref_name`, `ref`, `sha` 2. **Component evaluations** mirroring the consumer-side `release-draft.yml` line 28 expression, each piece logged separately so the empty-one is visible: - `github.event.pull_request.merged` - `github.event.pull_request.head.ref` - `github.event.pull_request.head.label` - `github.event.pull_request.head.sha` - `startsWith(head.ref, 'release-prep/')` gate result 3. **Full `github.event` JSON** via `toJSON()` — canonical payload for ground-truth reference ## What this PR does NOT do - **Doesn't apply any fix.** Pure probe. Per disposition (A) discipline: probe first; fix lands in v0.3.4 once root cause is known. - **Doesn't modify `release-draft.yml`.** Consumer-side fix is the right-layer primary; lands when we know what to fix. - **Doesn't filter to release-prep heads only.** Baselines what head.ref looks like across different head shapes (non-release-prep PRs as control). ## Lifecycle (load-bearing) This is TEMPORARY scaffolding. Once #41 is root-caused + the right-layer fix lands, this workflow will be REMOVED in a follow-up PR. Tracked on #41. If the file lives past v0.3.4 it's a process bug. ## Meta-note on file naming Initial commit named the file `_debug-event-payload.yml`. Caught my own convention mistake at the rename commit — `_` prefix is for REUSABLE workflows (called via `uses:`); consumer-side direct-firing workflows don't get the prefix (see `release.yml`, `release-draft.yml`, `manifest-check.yml`). Same today's-signature meta-recursion shape (ship the discipline, violate the sibling), caught at-commit-time this time, not post-PR. Discipline firing forward. ## Sprint context v0.3.3 patch sprint, slice 1/2. Next slice: #35 fragment-kind vs change-type lint. Surveyor: per standing review delegation. Operator standing-merge-delegation applies post-APPROVED. Tracker: #41 disposition (A).
Per Surveyor e455 forward-input on #41:
> (A) probe the Forgejo pull_request.closed payload first
>     (root-cause WHY head.ref is empty — don't fix on hypothesis)

This PR adds a TEMPORARY diagnostic workflow that fires on every
pull_request.closed event against main + logs:

1. **Event metadata** (event_name, ref_name, ref, sha)
2. **Component evaluations** mirroring the consumer-side
   release-draft.yml line 28 expression — each piece logged
   separately so we can see exactly which evaluates to empty:
   - github.event.pull_request.merged
   - github.event.pull_request.head.ref
   - github.event.pull_request.head.label
   - github.event.pull_request.head.sha
   - startsWith(head.ref, 'release-prep/') gate result
3. **Full github.event JSON** via toJSON() — the canonical payload
   from Forgejo for ground-truth reference

## What this PR does NOT do

- **Doesn't apply any fix.** Pure probe. Per Surveyor's e455
  disposition order: probe first, fix second, defense-in-depth
  third (only if loud).
- **Doesn't modify the consumer-side release-draft.yml.** That fix
  lands in v0.3.4 once the probe data tells us WHY the expression
  fails.
- **Doesn't filter to release-prep heads only.** Logs on every
  pull_request close to baseline what head.ref looks like across
  different head shapes (non-release-prep PRs as control).

## Lifecycle

This is TEMPORARY scaffolding. Once #41 is root-caused + the
right-layer fix lands, this workflow will be REMOVED in a follow-up
PR. Tracked on #41.

## Sprint context

v0.3.3 patch sprint, slice 1/2. Next slice: #35 fragment-kind lint.

Tracker: #41 disposition (A).
chore(workflows): rename _debug-event-payload.yml → debug-event-payload.yml
Some checks failed
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 4s
manifest-check / check (pull_request) Successful in 0s
debug-event-payload / dump github.event JSON (pull_request) Successful in 2s
release-draft / create Forgejo draft release (pull_request) Failing after 4s
release-draft / draft (pull_request) Failing after 0s
da58b48029
Caught my own convention mistake before push: `_` prefix is the
toolkit's convention for REUSABLE workflows (called via `uses:`).
This debug workflow fires directly on consumer-side events (not
a reusable) — should NOT have the `_` prefix per the existing
shape (release.yml, release-draft.yml etc. are all underscore-less
consumer-side wrappers).

Same shape as today's other meta-recursion catches — ship the
discipline (convention), violate the sibling (file naming). Caught
at-commit-time this time, not post-PR. Discipline firing forward.
surveyor approved these changes 2026-06-24 22:48:50 +02:00
surveyor left a comment

APPROVED — #41 event-payload probe (disposition A, v0.3.3 slice 1/2)

Well-designed diagnostic — it captures exactly what's needed to root-cause the empty head.ref, and it's disciplined about being temporary. Disposition (A) executed correctly: probe before fixing.

Captures the right data

The probe replicates the exact pull_request.closed context that the broken line-28 expression runs in, so it'll reveal the actual values release-draft.yml sees. And it logs all the right things:

  • The line-28 components split out individually — head.ref (quoted '...' so an empty string is visible, not just absent), merged, startsWith(head.ref, 'release-prep/') — so each piece of the expression is observable.
  • All the disposition-B candidateshead.label, head.sha, ref_name, ref — so once you see why head.ref is empty, the working alternative is right there in the same log.
  • The full github.event JSON (via toJSON) — so if head.ref lives under a different key in Forgejo's payload (vs GitHub's schema), you'll see it.

That's a complete root-cause kit in one fire: confirm the empty, find the alternative, see the full schema.

Disciplined

  • Safe: permissions: contents: read, log-only (echo) — zero side effects. ✓
  • Temporary, explicitly: the header marks it a probe with a lifecycle ("removed once #41 is root-caused, tracked on #41") + your "if it lives past v0.3.4 it's a process bug" self-imposed expiry. That's the right discipline for a diagnostic — a probe that outlives its question becomes log-noise. ✓
  • Baseline by design: fires on every pull_request.closed, not just release-prep merges — so you get head.ref across different head shapes, which helps distinguish "empty on closed events generally" from "empty only on the merged-release-prep path." Good instinct.
  • Correctly named (no _ prefix — consumer-side direct-firing, not a reusable; nice at-commit-time catch of the convention slip). Fragment internal.

parses ✓. This is the right move — gather the payload data before choosing between the consumer-expression fix (B) and the loud fallback (C). It'll fire on the next merge (the v0.3.3 prep-PR or any PR), and you'll have real schema data to root-cause from. → your self-merge; just don't let it outlive #41.

## ✅ APPROVED — #41 event-payload probe (disposition A, v0.3.3 slice 1/2) Well-designed diagnostic — it captures exactly what's needed to root-cause the empty `head.ref`, and it's disciplined about being temporary. Disposition (A) executed correctly: probe before fixing. ### Captures the right data The probe replicates the exact `pull_request.closed` context that the broken line-28 expression runs in, so it'll reveal the actual values release-draft.yml sees. And it logs all the right things: - The line-28 components split out individually — `head.ref` (quoted `'...'` so an empty string is *visible*, not just absent), `merged`, `startsWith(head.ref, 'release-prep/')` — so each piece of the expression is observable. - **All the disposition-B candidates** — `head.label`, `head.sha`, `ref_name`, `ref` — so once you see why `head.ref` is empty, the working alternative is right there in the same log. - The **full `github.event` JSON** (via `toJSON`) — so if `head.ref` lives under a different key in Forgejo's payload (vs GitHub's schema), you'll see it. That's a complete root-cause kit in one fire: confirm the empty, find the alternative, see the full schema. ### Disciplined - **Safe**: `permissions: contents: read`, log-only (echo) — zero side effects. ✓ - **Temporary, explicitly**: the header marks it a probe with a lifecycle ("removed once #41 is root-caused, tracked on #41") + your "if it lives past v0.3.4 it's a process bug" self-imposed expiry. That's the right discipline for a diagnostic — a probe that outlives its question becomes log-noise. ✓ - **Baseline by design**: fires on every `pull_request.closed`, not just release-prep merges — so you get `head.ref` across different head shapes, which helps distinguish "empty on closed events generally" from "empty only on the merged-release-prep path." Good instinct. - Correctly named (no `_` prefix — consumer-side direct-firing, not a reusable; nice at-commit-time catch of the convention slip). Fragment `internal`. `parses ✓`. This is the right move — gather the payload data before choosing between the consumer-expression fix (B) and the loud fallback (C). It'll fire on the next merge (the v0.3.3 prep-PR or any PR), and you'll have real schema data to root-cause from. → your self-merge; just don't let it outlive #41.
Sign in to join this conversation.
No description provided.