Skip to content

Add CHANGELOG.md and use it as the release body (closes #17) - #26

Merged
dolph merged 1 commit into
mainfrom
claude/changelog
Apr 27, 2026
Merged

Add CHANGELOG.md and use it as the release body (closes #17)#26
dolph merged 1 commit into
mainfrom
claude/changelog

Conversation

@dolph

@dolph dolph commented Apr 27, 2026

Copy link
Copy Markdown
Owner

Closes #17.

Summary

Adds a hand-curated CHANGELOG.md covering v1.0.0–v1.0.2 reconstructed from the git history, plus an [Unreleased] section for the work merged on main since v1.0.2. The release workflow now uses CHANGELOG.md as the release body instead of the project README — so adopters reading "what changed in v1.4 vs v1.3?" on a release page actually get an answer.

Why this shape

Keep a Changelog is the closest thing to an industry-standard format for hand-curated release notes — categorized (Added / Changed / Deprecated / Removed / Fixed / Security), reverse-chronological, dated, with comparison links between releases. It's better than auto-generated PR-title release notes (generate_release_notes: true) for a security-sensitive tool because every change gets a deliberate human-readable line that says what and why, rather than the PR title du jour. The [Unreleased] section keeps an always-current preview of what the next tag will contain, which is the discipline that keeps the file from rotting.

Reconstructed history

Tag Date Highlights
v1.0.0 2023-04-27 Initial release.
v1.0.1 2023-04-29 Apache 2.0 re-license; install.sh switched from build-from-source to download-prebuilt; README path fix.
v1.0.2 2023-04-30 Security: fixed isExecutableWritable — the previous mask was checking owner-read (1<<7) and the sticky-bit area (1<<9) instead of group-write (0o020) and other-write (0o002), so the gate was a no-op against the bits its name claims to refuse.

The companion just use constants commit (68af9c7) is a readability rewrite of the same lines and isn't called out separately — it's part of the same release.

[Unreleased] section

Captures the post-v1.0.2 main-branch work, categorized:

Workflow change

- body_path: README.md
+ body_path: CHANGELOG.md

That's the entire release-body change. Combined with the hand-curated content, it directly resolves #17 (release body hard-coded to README.md).

README

Adds a small "Changelog" section pointing at the file and noting the Keep-a-Changelog + SemVer commitments.

Going-forward discipline

Every PR with adopter-visible behavior should add a bullet under [Unreleased] in the appropriate category. At release time, [Unreleased] gets renamed to the new version with the release date, and a fresh empty [Unreleased] is added at the top. (Worth capturing in CONTRIBUTING.md if/when that lands — separate scope.)

Test plan

  • ./build.sh green; tests still pass; coverage unchanged at 39.5% (no source change).
  • shellcheck install.sh build.sh green.
  • CHANGELOG.md renders cleanly as Markdown; reference-style links resolve.
  • CI shellcheck + build jobs both green on the PR.
  • (post-merge, once a tag fires) GitHub release page shows the CHANGELOG content as the body.

Out of scope

  • Backfilling existing release pages. GitHub releases for v1.0.0–v1.0.2 already exist with whatever body they were created with (currently the README content per the old workflow). The release body is independent of the source CHANGELOG; updating those pages is a one-shot UI / API edit. Happy to do it — say the word and I'll patch each release body via the GitHub API to match the corresponding CHANGELOG.md section.
  • Automated changelog generation (release-please, git-cliff, etc.). Hand-curated is the right fit for a security-sensitive tool at this size; revisit if PR volume grows.
  • Auto-generated GitHub release notes as a supplement (generate_release_notes: true in addition to body_path). softprops/action-gh-release v1 doesn't merge them with a body_path; choosing one. Hand-curated wins here.

https://claude.ai/code/session_013HnepY8MhhxrJJjE5ysW47


Generated by Claude Code

Closes #17.

Adopts Keep a Changelog (https://keepachangelog.com) as the per-release
history and notes that the project follows SemVer. The CHANGELOG covers
v1.0.0 through v1.0.2 reconstructed from the git history, plus an
[Unreleased] section capturing the post-v1.0.2 work merged on main —
shellcheck CI (#6, #7), cache TTL (#8 / #3), the log.Fatal blast-radius
fix (#10 / #2), and release-artifact verification (#25 / #12 / #1) —
categorized as Added / Changed / Fixed / Security.

The release workflow now points at CHANGELOG.md instead of README.md
for the release body. Adopters reading "what changed in v1.4 vs v1.3?"
on a release page get an actual answer instead of the project
description, which is the trust-model gap #17 was about.

Mechanics:

- v1.0.2 entry calls out the isExecutableWritable fix as Security: the
  previous mask was checking owner-read (1<<7) and the sticky-bit area
  (1<<9) instead of group-write (0o020) and other-write (0o002), so the
  startup gate was a no-op against the bits its name claims to refuse.
- Release dates derive from the lightweight tag commit dates (no
  tagger metadata exists on these tags).
- Each release header is linked to a compare URL; PR/issue numbers in
  the body are reference-style links collected at the bottom.
- README grows a small Changelog section pointing at the file.

Discipline going forward: every PR with adopter-visible behavior
should add a bullet under [Unreleased] in the appropriate category.
At release time, [Unreleased] gets renamed to the new version with a
date, and a fresh [Unreleased] is added at the top.
@dolph
dolph merged commit 60e4f95 into main Apr 27, 2026
4 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.

Release body is hard-coded to README.md; adopters have no way to see what changed

2 participants