Skip to content

ci(release): filter non-faigate topics from release notes#224

Merged
github-actions[bot] merged 1 commit intomainfrom
release-content-boundary
Apr 26, 2026
Merged

ci(release): filter non-faigate topics from release notes#224
github-actions[bot] merged 1 commit intomainfrom
release-content-boundary

Conversation

@typelicious
Copy link
Copy Markdown
Collaborator

Summary

  • Adds .github/workflows/prerelease.yml that runs on tag push and rewrites the GitHub release body with filtered notes.
  • Adds .github/scripts/filter-changelog.py with a deny-list of non-faigate patterns and a self-test that runs in CI.
  • Adds a Content boundary section to AGENTS.md documenting the rule for humans and agents.

How the filter works

  1. git-cliff --tag <vX.Y.Z> --strip header --unreleased generates raw notes.
  2. filter-changelog.py raw-notes.md > filtered-notes.md drops bullet lines whose content matches any deny pattern (case-insensitive).
  3. Empty section headings (whose bullets all got filtered) are pruned automatically.
  4. gh release edit/create --notes-file filtered-notes.md publishes the cleaned notes.

The filter only touches bullet lines. Prose paragraphs are kept verbatim — the operator-author is trusted there.

What gets filtered

Patterns currently in the deny list:

  • personal memory / env-management tooling names
  • absolute operator paths under /Users/<name>/, ~/Library/, ~/Documents/
  • a few specific tool names that surface in commit messages but never belong in public release notes

The script logs the dropped lines to stderr so the workflow run page shows what the filter caught.

Self-test

python3 .github/scripts/filter-changelog.py --self-test

The workflow runs this before every filter pass, so a regression in the deny list fails the run rather than silently letting bad content through.

Manual override: python3 .github/scripts/filter-changelog.py --check raw.md exits 1 if anything would be dropped — useful for local pre-tag checks.

Test plan

  • python3 .github/scripts/filter-changelog.py --self-test — pass
  • python3 -c 'import yaml; yaml.safe_load(open(".github/workflows/prerelease.yml"))' — valid YAML
  • Reviewer: confirm the deny-list patterns in filter-changelog.py cover the cases you've seen leak. Pattern set is a single list at top of file — easy to extend.
  • After merge: cut a vX.Y.Z tag and verify the prerelease workflow rewrites the release body. Filtered + raw notes are also uploaded as artifacts (30d retention) so anything wrongly dropped can be recovered manually.

Why no test for the workflow itself

The workflow's testable logic lives in the Python script, which has the self-test. The yaml itself is mostly glue (gh release edit ...); a full end-to-end check needs a real tag — the dry-run on next release will be the smoke test.

🤖 Generated with Claude Code

Adds .github/workflows/prerelease.yml that runs on tag push (or manual
dispatch). It generates the unreleased changelog with git-cliff, strips
bullet lines that mention personal tooling or local setup details via
.github/scripts/filter-changelog.py, and attaches the cleaned notes to
the GitHub release.

The filter has a deny list of patterns and a self-test ('--self-test')
that runs in CI before each filter pass to fail fast if the rule set
regresses. Empty headings are pruned automatically when their bullets
all get filtered out.

AGENTS.md gains a 'Content boundary' section documenting the rule:
release notes, changelogs, PR descriptions, and commit messages must
not reference non-faigate topics. The workflow is a safety net; the
rule keeps the source clean.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@github-actions github-actions Bot enabled auto-merge (squash) April 26, 2026 18:33
@github-actions github-actions Bot merged commit 3f8c026 into main Apr 26, 2026
15 checks passed
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