Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/changelog-guard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Changelog Guard
Comment thread
jamescrosswell marked this conversation as resolved.

on:
pull_request:
branches:
- main
- release/**

permissions:
contents: read

jobs:
no-manual-unreleased-entries:
name: No manual "## Unreleased" entries
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Verify CHANGELOG.md has no manual "## Unreleased" entries
run: ./scripts/verify-changelog.sh
Comment thread
sentry[bot] marked this conversation as resolved.
6 changes: 0 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# Changelog

## Unreleased

### Features ✨

- feat: Add exponential backoff and log deduplication to Spotlight transport by @mattico in [#5025](https://github.com/getsentry/sentry-dotnet/pull/5025)

## 6.6.0

### Features ✨
Expand Down
23 changes: 4 additions & 19 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,28 +109,13 @@ To do that, run the build locally (i.e: `./build.sh` or `build.cmd`) and commit
## Changelog

We'd love for users to update the SDK everytime and as soon as we make a new release. But in reality most users rarely update the SDK.
To help users see value in updating the SDK, we maintain a changelog file with entries split between two headings:
To help users see value in updating the SDK, we maintain a changelog file with entries split between headings such as `### Features` and `### Fixes`.

1. `### Features`
2. `### Fixes`
**Do not edit `CHANGELOG.md` manually.** The changelog is generated automatically at release time by [craft](https://github.com/getsentry/craft) (`changelogPolicy: auto` in `.craft.yml`) from the pull requests merged since the previous release. Entries are categorized from your [commit message / PR title](https://develop.sentry.dev/engineering-practices/commit-messages/) (e.g. a `feat:` PR becomes a Feature, a `fix:` PR becomes a Fix), so there's nothing to add by hand.
Comment thread
jamescrosswell marked this conversation as resolved.

We add the heading in the first PR that's adding either a feature or fixes in the current release.
After a release, the [changelog file will contain only the last release entries](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md).
Adding an entry under `## Unreleased` yourself is actively harmful: craft only auto-generates the section when it's empty, so a single leftover manual entry suppresses generation and drops every other change from the release notes. A `Changelog Guard` GitHub Action fails any PR that adds a manual entry under `## Unreleased`; you can run the same check locally with `./scripts/verify-changelog.sh`.
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated

When you open a PR in such cases, you need to add a heading 2 named `## Unreleased`, which is replaced during release with the version number chosen.
Below that, you'll add heading 3 mentioned above. For example, if you're adding a feature "Attach screenshots when capturing errors on WPF", right after a release, you'd add to the changelog:

```
## Unreleased

### Features

- Attach screenshots when capturing errors on WPF (#PR number)
```

There's a GitHub action check to verify if an entry was added.
If the entry isn't a user-facing change, you can skip the verification with either `#skip-changelog` written to the PR description or the `skip-changelog` label added to the PR.
The bot writes a comment in the PR with a suggestion entry to the changelog based on the PR title.
If the change isn't user-facing and you'd rather it not appear in the changelog at all, add the `skip-changelog` label to the PR or write `#skip-changelog` in the PR description.

## Naming tests

Expand Down
56 changes: 56 additions & 0 deletions scripts/verify-changelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
#
# Verifies that CHANGELOG.md contains no manually-added entries under an
# "## Unreleased" heading.
#
# This repository generates its changelog automatically at release time via
# craft (`changelogPolicy: auto` in .craft.yml), from the pull requests merged
# since the previous release. craft only regenerates the section when it is
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated
# empty, so a single leftover manual entry under "## Unreleased" suppresses the
# auto-generation and silently drops every other change from the release notes.
# (This is what broke the 6.7.0 release, which shipped with a single entry.)
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated
#
# Usage: scripts/verify-changelog.sh [path-to-changelog]
set -euo pipefail

CHANGELOG="${1:-CHANGELOG.md}"

if [[ ! -f "$CHANGELOG" ]]; then
echo "Changelog file not found: $CHANGELOG" >&2
exit 2
fi

# Extract the body of the "## Unreleased" section: everything between the
# "## Unreleased" heading and the next "## " (h2) heading. "### " sub-headings
# are not treated as section boundaries.
unreleased_body="$(awk '
/^## / {
if (in_section) exit
if (tolower($0) ~ /^## +unreleased/) { in_section = 1; next }
}
in_section { print }
' "$CHANGELOG")"

# A manual changelog entry is a bullet line ("- ..." or "* ..."). This
# deliberately ignores an empty "## Unreleased" heading and blank/sub-heading
# lines, so only real entries fail the check.
entry_re='^[[:space:]]*[-*][[:space:]]+[^[:space:]]'

if printf '%s\n' "$unreleased_body" | grep -Eq "$entry_re"; then
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated
echo "::error file=$CHANGELOG::Manual changelog entries found under '## Unreleased'."
echo ""
echo "This repository generates its changelog automatically at release time"
echo "(changelogPolicy: auto in .craft.yml). A manual entry under '## Unreleased'"
echo "suppresses that generation and causes other changes to be dropped from the"
echo "release notes."
echo ""
echo "Offending line(s):"
printf '%s\n' "$unreleased_body" | grep -En "$entry_re" || true
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated
echo ""
echo "Please remove them. Your change is added to the changelog automatically,"
echo "based on the PR title / commit message. If it is not user-facing, add the"
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated
echo "'skip-changelog' label or write '#skip-changelog' in the PR description."
exit 1
fi

echo "OK: no manual '## Unreleased' changelog entries."
Loading