Skip to content

chore(release): append en.dev sponsor blurb to release notes#431

Merged
jdx merged 3 commits intomainfrom
claude/sponsor-blurb-release-notes
Apr 23, 2026
Merged

chore(release): append en.dev sponsor blurb to release notes#431
jdx merged 3 commits intomainfrom
claude/sponsor-blurb-release-notes

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 23, 2026

Summary

  • Appends a Sponsor fnox section to every GitHub Release body, run after communique generate in the enhance-release job in .github/workflows/release.yml.
  • Same pattern as mise#9272, adapted for fnox.

What it looks like

Rendered at the bottom of each release body:

💚 Sponsor fnox

fnox is maintained by @jdx under en.dev — a small independent studio building developer tooling like mise, aube, hk, and more. Keeping fnox secure, maintained, and free is funded by sponsors.

If fnox is handling secrets or config for you or your team, please consider sponsoring at en.dev. Sponsorships are what let fnox stay independent and the project keep moving.

Test plan

  • `actionlint` + `yamllint` pass on the modified workflow
  • Next tagged release produces a GitHub Release whose body ends with the sponsor section

🤖 Generated with Claude Code

Adds a "Sponsor fnox" section at the bottom of each GitHub Release body
after communique generates the narrative notes, so readers who land on
a release see how fnox is funded and where to sponsor.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR adds a sponsor blurb append step to the enhance-release workflow job and refactors TUI match arms in app.rs and event.rs to use match guard syntax. The workflow change is straightforward; the Rust changes are mostly clean, except that event.rs encodes side effects (channel sends) inside match guards rather than arm bodies.

Confidence Score: 5/5

Safe to merge — only one P2 style finding in event.rs; all logic is functionally correct.

The workflow change is correct and the Rust refactors are functionally equivalent. The single flagged issue (side effects in match guards in event.rs) does not affect runtime behavior and is a style concern only.

src/tui/event.rs — the match-guard side-effect pattern warrants a second look, though it is not a bug today.

Important Files Changed

Filename Overview
.github/workflows/release.yml Adds a new "Append en.dev sponsor blurb" step to the enhance-release job that reads the current release body, appends the sponsor section via heredoc, and writes it back with gh release edit.
src/tui/app.rs Refactors several match arms to lift inner if conditions into match guards — semantically equivalent, cleaner code. No logic changes.
src/tui/event.rs Refactors event-dispatch match arms to use match guards with side-effectful send() calls as the guard predicate — functionally correct but unconventional and could confuse future maintainers.

Sequence Diagram

sequenceDiagram
    participant GH as GitHub Tag Push
    participant BB as build-binaries
    participant CR as create-release
    participant ER as enhance-release

    GH->>BB: trigger on push/tag
    BB-->>CR: artifacts uploaded
    CR->>CR: extract CHANGELOG notes
    CR->>CR: gh release create (with assets)
    CR-->>ER: release created
    ER->>ER: communique generate (AI-enhanced notes)
    ER->>ER: gh release view (fetch body)
    ER->>ER: append sponsor blurb via heredoc
    ER->>GH: gh release edit (write final notes)
Loading

Fix All in Claude Code

Reviews (3): Last reviewed commit: "[autofix.ci] apply automated fixes (atte..." | Re-trigger Greptile

Comment on lines +139 to +141
{
gh release view "$TAG_NAME" --json body --jq .body
cat <<'EOF'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Non-idempotent append on workflow re-run

The step always appends the sponsor blurb to whatever gh release view returns at that moment. If the enhance-release job (or just this step) is re-run — due to a transient failure, a manual retry, or a re-triggered release — the section will be appended a second time. Adding an idempotency guard prevents this:

Suggested change
{
gh release view "$TAG_NAME" --json body --jq .body
cat <<'EOF'
BODY=$(gh release view "$TAG_NAME" --json body --jq .body)
if echo "$BODY" | grep -qF '## 💚 Sponsor fnox'; then
echo "Sponsor blurb already present, skipping."
exit 0
fi
{
echo "$BODY"
cat <<'EOF'

Fix in Claude Code

@jdx jdx enabled auto-merge (squash) April 23, 2026 17:07
@jdx jdx disabled auto-merge April 23, 2026 17:09
@jdx jdx enabled auto-merge (squash) April 23, 2026 17:09
@jdx jdx disabled auto-merge April 23, 2026 17:09
@jdx jdx enabled auto-merge (squash) April 23, 2026 17:10
@jdx jdx merged commit 151720f into main Apr 23, 2026
14 checks passed
@jdx jdx deleted the claude/sponsor-blurb-release-notes branch April 23, 2026 17:25
jdx added a commit that referenced this pull request Apr 23, 2026
The provider codegen in build/generate_providers.rs sorted providers by
category only. Stable sort preserves input order for equal keys, and
fs::read_dir returns entries in OS-dependent order, so providers within
the same category were ordered by whatever the filesystem produced. That
non-determinism flowed into the generated ProviderConfig enum and then
into docs/public/schema.json, causing autofix.ci to produce schema diffs
that flip 100+ lines back and forth between runs (see #431 where three
autofix passes kept reshuffling the same oneOf variants).

Add a secondary sort by provider name so within-category ordering is
deterministic, and regenerate docs/public/schema.json.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
jdx added a commit that referenced this pull request Apr 23, 2026
## Summary

- Providers within a category were ordered by `fs::read_dir`
(OS/filesystem-dependent).
- That non-determinism flowed into the generated `ProviderConfig` enum
and then into [docs/public/schema.json](docs/public/schema.json),
causing
[autofix.ci](https://github.com/jdx/fnox/blob/main/.github/workflows/autofix.yml)
to keep reshuffling 100+ lines between runs. You can see this on
[#431](#431) — three autofix passes each
re-ordered the same `oneOf` variants without converging.
- Adds a secondary sort by provider name in
[`build/generate_providers.rs`](build/generate_providers.rs) so
within-category ordering is fully deterministic, then regenerates
[docs/public/schema.json](docs/public/schema.json) with the stable
ordering.

## Root cause

```rust
// before — stable sort on category only; within-category order = read_dir order
providers.sort_by(|a, b| cat_order(&a.1.category).cmp(&cat_order(&b.1.category)));
```

Stable sort preserves input order on ties, and input order comes from
`fs::read_dir`, which is not guaranteed to be sorted. Fix is a secondary
`.then_with(|| a.0.cmp(&b.0))` on name.

## Test plan

- [x] `mise run render:schema` locally
- [x] Running `fnox schema` twice produces byte-identical output
- [ ] `autofix.ci` on this PR does not re-touch
`docs/public/schema.json`
- [ ] Future PRs that don't touch provider definitions should not see
schema churn

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: only changes provider sorting in a build-time codegen script
and regenerates `docs/public/schema.json`; no runtime logic or
security-sensitive behavior is modified.
> 
> **Overview**
> Ensures provider definitions are loaded in a *fully deterministic*
order during schema/code generation by sorting first by category and
then by provider name (avoiding OS/filesystem-dependent `read_dir`
ordering).
> 
> Regenerates `docs/public/schema.json` so the `ProviderConfig` `oneOf`
variants appear in stable order, eliminating cross-machine/CI churn in
the generated schema output.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
291cd31. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
jdx pushed a commit that referenced this pull request Apr 26, 2026
### 🚀 Features

- **(library)** top-level Fnox::discover() / get / list convenience API
by [@bglusman](https://github.com/bglusman) in
[#442](#442)

### 🐛 Bug Fixes

- **(docs)** stack banner and pin close button on mobile by
[@jdx](https://github.com/jdx) in
[#437](#437)
- **(set)** fall back to current provider when updating secrets by
[@rpendleton](https://github.com/rpendleton) in
[#439](#439)

### 📚 Documentation

- **(site)** show release version and github stars by
[@jdx](https://github.com/jdx) in
[#443](#443)
- add cross-site announcement banner by [@jdx](https://github.com/jdx)
in [#434](#434)
- respect banner expires field by [@jdx](https://github.com/jdx) in
[#436](#436)

### 🛡️ Security

- **(build)** deterministic provider ordering in generated schema by
[@jdx](https://github.com/jdx) in
[#432](#432)

### 🔍 Other Changes

- **(release)** append en.dev sponsor blurb to release notes by
[@jdx](https://github.com/jdx) in
[#431](#431)

### 📦️ Dependency Updates

- bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in
[#435](#435)
- bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in
[#438](#438)

### New Contributors

- @bglusman made their first contribution in
[#442](#442)
jdx pushed a commit that referenced this pull request Apr 26, 2026
### 🚀 Features

- **(library)** top-level Fnox::discover() / get / list convenience API
by [@bglusman](https://github.com/bglusman) in
[#442](#442)

### 🐛 Bug Fixes

- **(docs)** stack banner and pin close button on mobile by
[@jdx](https://github.com/jdx) in
[#437](#437)
- **(set)** fall back to current provider when updating secrets by
[@rpendleton](https://github.com/rpendleton) in
[#439](#439)

### 📚 Documentation

- **(site)** show release version and github stars by
[@jdx](https://github.com/jdx) in
[#443](#443)
- add cross-site announcement banner by [@jdx](https://github.com/jdx)
in [#434](#434)
- respect banner expires field by [@jdx](https://github.com/jdx) in
[#436](#436)

### 🛡️ Security

- **(build)** deterministic provider ordering in generated schema by
[@jdx](https://github.com/jdx) in
[#432](#432)

### 🔍 Other Changes

- **(release)** append en.dev sponsor blurb to release notes by
[@jdx](https://github.com/jdx) in
[#431](#431)

### 📦️ Dependency Updates

- bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in
[#435](#435)
- bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in
[#438](#438)
- bump communique to 1.1.2 by [@jdx](https://github.com/jdx) in
[#444](#444)

### New Contributors

- @bglusman made their first contribution in
[#442](#442)
NorthIsUp pushed a commit to NorthIsUp/fnox that referenced this pull request Apr 28, 2026
## Summary

- Appends a **Sponsor fnox** section to every GitHub Release body, run
after `communique generate` in the `enhance-release` job in
[`.github/workflows/release.yml`](.github/workflows/release.yml).
- Same pattern as [mise#9272](jdx/mise#9272),
adapted for fnox.

## What it looks like

Rendered at the bottom of each release body:

> ## 💚 Sponsor fnox
>
> fnox is maintained by [@jdx](https://github.com/jdx) under
[**en.dev**](https://en.dev) — a small independent studio building
developer tooling like [mise](https://mise.jdx.dev/),
[aube](https://aube.en.dev/), hk, and more. Keeping fnox secure,
maintained, and free is funded by sponsors.
>
> If fnox is handling secrets or config for you or your team, please
consider [sponsoring at en.dev](https://en.dev). Sponsorships are what
let fnox stay independent and the project keep moving.

## Test plan

- [x] \`actionlint\` + \`yamllint\` pass on the modified workflow
- [ ] Next tagged release produces a GitHub Release whose body ends with
the sponsor section

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
NorthIsUp pushed a commit to NorthIsUp/fnox that referenced this pull request Apr 28, 2026
)

## Summary

- Providers within a category were ordered by `fs::read_dir`
(OS/filesystem-dependent).
- That non-determinism flowed into the generated `ProviderConfig` enum
and then into [docs/public/schema.json](docs/public/schema.json),
causing
[autofix.ci](https://github.com/jdx/fnox/blob/main/.github/workflows/autofix.yml)
to keep reshuffling 100+ lines between runs. You can see this on
[jdx#431](jdx#431) — three autofix passes each
re-ordered the same `oneOf` variants without converging.
- Adds a secondary sort by provider name in
[`build/generate_providers.rs`](build/generate_providers.rs) so
within-category ordering is fully deterministic, then regenerates
[docs/public/schema.json](docs/public/schema.json) with the stable
ordering.

## Root cause

```rust
// before — stable sort on category only; within-category order = read_dir order
providers.sort_by(|a, b| cat_order(&a.1.category).cmp(&cat_order(&b.1.category)));
```

Stable sort preserves input order on ties, and input order comes from
`fs::read_dir`, which is not guaranteed to be sorted. Fix is a secondary
`.then_with(|| a.0.cmp(&b.0))` on name.

## Test plan

- [x] `mise run render:schema` locally
- [x] Running `fnox schema` twice produces byte-identical output
- [ ] `autofix.ci` on this PR does not re-touch
`docs/public/schema.json`
- [ ] Future PRs that don't touch provider definitions should not see
schema churn

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: only changes provider sorting in a build-time codegen script
and regenerates `docs/public/schema.json`; no runtime logic or
security-sensitive behavior is modified.
> 
> **Overview**
> Ensures provider definitions are loaded in a *fully deterministic*
order during schema/code generation by sorting first by category and
then by provider name (avoiding OS/filesystem-dependent `read_dir`
ordering).
> 
> Regenerates `docs/public/schema.json` so the `ProviderConfig` `oneOf`
variants appear in stable order, eliminating cross-machine/CI churn in
the generated schema output.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
291cd31. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
NorthIsUp pushed a commit to NorthIsUp/fnox that referenced this pull request Apr 28, 2026
### 🚀 Features

- **(library)** top-level Fnox::discover() / get / list convenience API
by [@bglusman](https://github.com/bglusman) in
[jdx#442](jdx#442)

### 🐛 Bug Fixes

- **(docs)** stack banner and pin close button on mobile by
[@jdx](https://github.com/jdx) in
[jdx#437](jdx#437)
- **(set)** fall back to current provider when updating secrets by
[@rpendleton](https://github.com/rpendleton) in
[jdx#439](jdx#439)

### 📚 Documentation

- **(site)** show release version and github stars by
[@jdx](https://github.com/jdx) in
[jdx#443](jdx#443)
- add cross-site announcement banner by [@jdx](https://github.com/jdx)
in [jdx#434](jdx#434)
- respect banner expires field by [@jdx](https://github.com/jdx) in
[jdx#436](jdx#436)

### 🛡️ Security

- **(build)** deterministic provider ordering in generated schema by
[@jdx](https://github.com/jdx) in
[jdx#432](jdx#432)

### 🔍 Other Changes

- **(release)** append en.dev sponsor blurb to release notes by
[@jdx](https://github.com/jdx) in
[jdx#431](jdx#431)

### 📦️ Dependency Updates

- bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in
[jdx#435](jdx#435)
- bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in
[jdx#438](jdx#438)

### New Contributors

- @bglusman made their first contribution in
[jdx#442](jdx#442)
NorthIsUp pushed a commit to NorthIsUp/fnox that referenced this pull request Apr 28, 2026
### 🚀 Features

- **(library)** top-level Fnox::discover() / get / list convenience API
by [@bglusman](https://github.com/bglusman) in
[jdx#442](jdx#442)

### 🐛 Bug Fixes

- **(docs)** stack banner and pin close button on mobile by
[@jdx](https://github.com/jdx) in
[jdx#437](jdx#437)
- **(set)** fall back to current provider when updating secrets by
[@rpendleton](https://github.com/rpendleton) in
[jdx#439](jdx#439)

### 📚 Documentation

- **(site)** show release version and github stars by
[@jdx](https://github.com/jdx) in
[jdx#443](jdx#443)
- add cross-site announcement banner by [@jdx](https://github.com/jdx)
in [jdx#434](jdx#434)
- respect banner expires field by [@jdx](https://github.com/jdx) in
[jdx#436](jdx#436)

### 🛡️ Security

- **(build)** deterministic provider ordering in generated schema by
[@jdx](https://github.com/jdx) in
[jdx#432](jdx#432)

### 🔍 Other Changes

- **(release)** append en.dev sponsor blurb to release notes by
[@jdx](https://github.com/jdx) in
[jdx#431](jdx#431)

### 📦️ Dependency Updates

- bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in
[jdx#435](jdx#435)
- bump communique 1.0.3 → 1.0.4 by [@jdx](https://github.com/jdx) in
[jdx#438](jdx#438)
- bump communique to 1.1.2 by [@jdx](https://github.com/jdx) in
[jdx#444](jdx#444)

### New Contributors

- @bglusman made their first contribution in
[jdx#442](jdx#442)
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