Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
[[ "$MAIN_SHA" == "$GITHUB_SHA" ]] || { echo "main moved during the build; rerun from the current main commit." >&2; exit 1; }
PREVIOUS_TAG="$(gh release list --limit 100 \
--json tagName,isDraft,isPrerelease,publishedAt \
| jq -er '[.[] | select(.isDraft == false and .isPrerelease == false)] | sort_by(.publishedAt) | last | .tagName')"
| jq -r '[.[] | select(.isDraft == false and .isPrerelease == false)] | sort_by(.publishedAt) | last | .tagName // empty')"
NOTES_FILE="${RUNNER_TEMP}/release-notes.md"
GITHUB_REPOSITORY="${GITHUB_REPOSITORY}" \
./scripts/generate_macos_release_notes.sh \
Expand Down
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@

## Chores

- 2026-09-29: Ersten Release ohne vorhandene Tags oder vorherige Releases vorbereitet.
- Dateien: `.github/workflows/release.yml`, `scripts/generate_macos_release_notes.sh`, `docs/distribution.md`, `changelog.md`.
- Funktionalität: Die Vorbereitung eines ersten Releases akzeptiert jetzt einen leeren Release-Verlauf. GitHub generiert Notizen ohne vorherigen Tag; direkte Commits werden ab dem Repository-Root aufgenommen. Kein Produktversionsbump, da dies Release-Tooling ist.

- 2026-09-29: Emoji aus automatisch generierten Release-Notizen entfernt.
- Dateien: `.github/release.yml`, `.github/PULL_REQUEST_TEMPLATE.md`, `scripts/generate_macos_release_notes.sh`, `docs/distribution.md`, `changelog.md`.
- Funktionalität: Kategorieüberschriften sind textbasiert. Der Release-Notizgenerator entfernt Emoji-Zeichen und ihre Unicode-Sequenzbestandteile aus PR-Titeln, direkten Commit-Nachrichten, Beitragendennamen und dem übrigen generierten Text. Die PR-Vorlage bittet um emoji-freie Titel. Die Produktversion bleibt unverändert, da sich nur Release-Tooling und Dokumentation ändern.
Expand Down
2 changes: 1 addition & 1 deletion docs/distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Expected assets:

The Finder DMG layout uses the matching 800 × 500 SVG background and `dmgbuild` metadata. `create_macos_dmg.sh` verifies the app's ad-hoc signature after packaging. Release builds contain no speech model; onboarding downloads one on first launch. The Whisper CLI is linked statically against Whisper/GGML, and `validate_macos_app_runtime.sh` verifies the executable and runtime manifest.

To prepare a draft from `main`, run **Actions → macOS Release** with `action=prepare` and the value from `VERSION`. The workflow finds the previous published release, asks GitHub's Release Notes API to summarize merged PRs, groups them using `.github/release.yml`, and includes contributors plus a full changelog link. A helper adds commit subjects and authors for direct commits that have no associated PR, so older work is not lost. PR titles must be descriptive on their own; apply one category label listed in `.github/PULL_REQUEST_TEMPLATE.md` before merging. The generated body removes emoji characters from PR titles, commit subjects, author names, and category headings. It also includes concise install guidance and a machine-readable source commit used by the publish check. The notes are suitable both for the draft and published release; there is no internal “publish this draft” text.
To prepare a draft from `main`, run **Actions → macOS Release** with `action=prepare` and the value from `VERSION`. The workflow finds the previous published release, asks GitHub's Release Notes API to summarize merged PRs, groups them using `.github/release.yml`, and includes contributors plus a full changelog link. A helper adds commit subjects and authors for direct commits that have no associated PR, so older work is not lost. When no previous published release is found, the workflow omits the previous-tag parameter; if the repository also has no Git tags, GitHub generates notes across the repository's full history and the helper includes direct commits from the repository root. PR titles must be descriptive on their own; apply one category label listed in `.github/PULL_REQUEST_TEMPLATE.md` before merging. The generated body removes emoji characters from PR titles, commit subjects, author names, and category headings. It also includes concise install guidance and a machine-readable source commit used by the publish check. The notes are suitable both for the draft and published release; there is no internal “publish this draft” text.

GitHub does not create the release tag while the release is a draft. After installation testing, run the same workflow with `action=publish` and the same version. The workflow checks branch, version, source commit, draft state and assets, then verifies the downloaded checksum and DMG before creating the tag at the tested source commit while publishing. For manual local verification steps, see [`macos-release-checklist.md`](macos-release-checklist.md). The old Developer ID archive, export, notarization, stapling, and Sparkle appcast scripts remain available for a future signed distribution, but they are not part of the current release path.

Expand Down
38 changes: 21 additions & 17 deletions scripts/generate_macos_release_notes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -euo pipefail

if [[ "$#" -ne 4 ]]; then
echo "Usage: $0 <version> <source-commit> <previous-release-tag> <output-file>" >&2
echo "Usage: $0 <version> <source-commit> <previous-release-tag-or-empty> <output-file>" >&2
exit 2
fi

Expand All @@ -25,26 +25,30 @@ strip_release_emojis() {
echo "Source commit must be a full lowercase Git SHA: ${SOURCE_COMMIT}" >&2
exit 2
}
[[ -n "${PREVIOUS_TAG}" ]] || {
echo "A previous published release tag is required to generate release notes." >&2
exit 2
}
git cat-file -e "${SOURCE_COMMIT}^{commit}"
git rev-parse --verify "refs/tags/${PREVIOUS_TAG}^{commit}" >/dev/null
git merge-base --is-ancestor "${PREVIOUS_TAG}" "${SOURCE_COMMIT}" || {
echo "Previous release ${PREVIOUS_TAG} is not an ancestor of ${SOURCE_COMMIT}." >&2
exit 1
}
NOTES_ARGUMENTS=(
--method POST
"repos/${GITHUB_REPOSITORY_VALUE}/releases/generate-notes"
-f "tag_name=${RELEASE_TAG}"
-f "target_commitish=${SOURCE_COMMIT}"
-f "configuration_file_path=.github/release.yml"
)
COMMIT_RANGE="${SOURCE_COMMIT}"

if [[ -n "${PREVIOUS_TAG}" ]]; then
git rev-parse --verify "refs/tags/${PREVIOUS_TAG}^{commit}" >/dev/null
git merge-base --is-ancestor "${PREVIOUS_TAG}" "${SOURCE_COMMIT}" || {
echo "Previous release ${PREVIOUS_TAG} is not an ancestor of ${SOURCE_COMMIT}." >&2
exit 1
}
NOTES_ARGUMENTS+=(-f "previous_tag_name=${PREVIOUS_TAG}")
COMMIT_RANGE="${PREVIOUS_TAG}..${SOURCE_COMMIT}"
fi

NOTES_RESPONSE="$(gh api --method POST \
"repos/${GITHUB_REPOSITORY_VALUE}/releases/generate-notes" \
-f "tag_name=${RELEASE_TAG}" \
-f "target_commitish=${SOURCE_COMMIT}" \
-f "previous_tag_name=${PREVIOUS_TAG}" \
-f "configuration_file_path=.github/release.yml")"
NOTES_RESPONSE="$(gh api "${NOTES_ARGUMENTS[@]}")"
GENERATED_NOTES="$(jq -r '.body' <<<"${NOTES_RESPONSE}")"

DIRECT_COMMITS="$(git rev-list --no-merges "${PREVIOUS_TAG}..${SOURCE_COMMIT}")"
DIRECT_COMMITS="$(git rev-list --no-merges "${COMMIT_RANGE}")"
DIRECT_NOTES=()
while IFS= read -r COMMIT; do
[[ -n "${COMMIT}" ]] || continue
Expand Down
Loading