Skip to content
Closed
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
68 changes: 68 additions & 0 deletions .github/prompts/release-announcement.prompt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# AI prompt for maintaining ReleaseAnnouncement.md.
# Used by .github/workflows/update-release-announcement.yml via actions/ai-inference.
# Edit this file to adjust the style or rules without touching the workflow YAML.

messages:
- role: system
content: |
You are a technical writer maintaining the working Release Announcement draft for Jamulus —
a free, open-source application that lets musicians rehearse, perform, and jam together in
real time over the internet.

The announcement is a single flat list of bullet points covering user-relevant changes,
written in the same friendly, conversational style used in real Jamulus beta and release
announcements. Here are real examples of entries from those announcements:

- the big one: extended SRV record support ([@rdica](https://github.com/rdica) and [@softins](https://github.com/softins))
- Windows and macOS moving to Qt 6.10.2
- a new Japanese translation ([@tsukurun](https://github.com/tsukurun))
- fixed a crash in the Connect dialog ([@ann0see](https://github.com/ann0see))
- Windows: Jamulus now prevents the screen saver from activating while you are connected ([@ann0see](https://github.com/ann0see))
- added a JSON-RPC method to control server directory settings ([@pljones](https://github.com/pljones))
- client RPC support for controlling fader levels ([@corrados](https://github.com/corrados))

Rules:
- Add each new change as a bullet point (- ) in the "Here's what's new" section of the
document. Do not add, remove, or modify any headings, the maintainer note block, or the
REMINDER section.
- Write in plain, friendly language. Use past tense for bug fixes, present tense for new
features or improvements.
- Use the CHANGELOG: line in the PR description (if present) as the primary source for
the description. Strip the category prefix (Client:, Server:, Build:, Tools:, etc.)
unless keeping it adds helpful context for a non-technical reader — e.g. keep "Windows:",
"macOS:", "iOS:", "Android:" for OS-specific changes; keep "Server:" when distinguishing
a server-only change is genuinely useful.
- Always credit contributors: ([@username](https://github.com/username))
For multiple contributors: ([@a](https://github.com/a) and [@b](https://github.com/b))
- Only include changes that are relevant to end users or server operators.
Omit purely internal changes: CI configuration, build system, code style, developer
tooling, and routine dependency bumps — unless they have a direct, noticeable impact on
users (e.g. a bundled library upgrade that fixes a crash or enables a new feature).
- Place more impactful changes nearer the top of the bullet list.
- Preserve all existing bullet points — never remove, merge, or rewrite them.
- If this PR introduces no user-relevant changes, return the announcement completely
unchanged.
- Output the COMPLETE updated Markdown document and nothing else. Do not add any
explanation, preamble, or commentary outside the document.

- role: user
content: |
Current working announcement:
---
{{current_announcement}}
---

Newly merged pull request:
{{pr_info}}
---

Update the Release Announcement to include any user-relevant changes from this PR.
Return the complete updated Markdown document only.

model: openai/gpt-4o-mini
modelParameters:
# High token limit to ensure the full document is always returned without truncation.
# The default max-tokens in actions/ai-inference is only 200, which would cut off the document.
maxCompletionTokens: 16384
# Low temperature for consistent, deterministic output when editing a structured document.
temperature: 0.1
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<!-- Explain what your PR does -->

CHANGELOG: <!-- Insert a short, end-user understandable sentence in past tense right here, e.g.: Client: Fixed crash when clicking the connect button too fast or SKIP if the change should not be documented in the ChangeLog -->
CHANGELOG: <!-- Insert a short, end-user understandable sentence in past tense right here, e.g.: Client: Fixed crash when clicking the connect button too fast or SKIP if the change should not be documented in the ChangeLog or Release Announcement -->

**Context: Fixes an issue?**

Expand Down
25 changes: 25 additions & 0 deletions .github/release-announcement-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Jamulus Next Release — Working Announcement Draft

> **Note for maintainers:** This is a working draft, automatically updated by GitHub Copilot
> as PRs are merged to `main`. Please review, polish, and publish to
> [GitHub Discussions (Announcements)](https://github.com/orgs/jamulussoftware/discussions)
> and other channels when the release is ready.
>
> Run [`tools/get_release_contributors.py`](tools/get_release_contributors.py) to compile
> the full contributor list before publishing.
>
> See the [ChangeLog](ChangeLog) for the complete technical record of all changes.

Here's what's new in the next release of Jamulus:

<!-- Changes will appear here automatically as pull requests are merged -->

As always, all feedback on the new version is welcome. Please raise any problems in a new bug report or discussion topic.

---

**REMINDER:** Those of you with virus checkers are likely to find the Windows installer incorrectly flagged as a virus. This is because the installer is open source and virus checkers cannot be bothered to check what it installs, so assume that it's going to be malign. If you download the installer _only from the official release_, you should be safe to ignore any warning.

---

*This draft is automatically maintained by the [Update Release Announcement](.github/workflows/update-release-announcement.yml) workflow.*
6 changes: 6 additions & 0 deletions .github/workflows/autobuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ on:
- 'COMPILING.md'
- 'COPYING'
- 'APPLEAPPSTORE.LICENCE.WAIVER'
- 'ReleaseAnnouncement.md'
- '.github/release-announcement-template.md'
- '.github/prompts/**'
- '.github/ISSUE_TEMPLATE/*'
- '.github/pull_request_template.md'
pull_request:
Expand All @@ -52,6 +55,9 @@ on:
- 'COMPILING.md'
- 'COPYING'
- 'APPLEAPPSTORE.LICENCE.WAIVER'
- 'ReleaseAnnouncement.md'
- '.github/release-announcement-template.md'
- '.github/prompts/**'
- '.github/ISSUE_TEMPLATE/*'
- '.github/pull_request_template.md'

Expand Down
253 changes: 253 additions & 0 deletions .github/workflows/update-release-announcement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
name: Update Release Announcement

# This workflow maintains ReleaseAnnouncement.md — a working draft of the release
# announcement for Client users and Server operators — separate from the technical ChangeLog.
#
# On every merged PR to main: GitHub Copilot updates the draft with any user-relevant
# changes from that PR, in the same conversational bullet-point style used in real
# Jamulus beta/release announcements on GitHub Discussions.
#
# On every push to an autobuild* branch: GitHub Copilot updates the draft on that branch
# with any user-relevant changes from the HEAD commit. This lets developers preview how
# their changes would appear in the announcement before the PR is merged.
#
# On every full release tag (r<x>_<y>_<z>, no suffix): the draft is reset to the pristine
# template, ready for the next development cycle. Pre-release tags (beta, rc) do NOT reset
# the draft, so it can continue to build up until the final release.
#
# Security note (pull_request_target):
# - The workflow file and the AI prompt always come from main, never from the PR branch.
# - PR content is written to a temp file via an env variable before being passed to the
# AI — it never touches a YAML value directly, preventing injection issues.
# - No code from the PR is ever checked out or executed.
# See: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/

on:
pull_request_target:
types:
- closed
branches:
- main
push:
branches:
- "autobuild**"
tags:
- "r*"

permissions: {}

jobs:
update-announcement:
name: Update announcement for merged PR
# Only run on actual merges (not just closed PRs) in the main jamulussoftware repo.
if: >-
github.repository_owner == 'jamulussoftware' &&
github.event.pull_request.merged == true
runs-on: ubuntu-latest
permissions:
contents: write
models: read

steps:
- uses: actions/checkout@v6
with:
# Always check out the base branch (main), never the PR branch.
ref: main

- name: Check if announcement update should be skipped
id: check-skip
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: |
# Skip when the PR author explicitly marked the change as not user-facing.
if printf '%s\n' "$PR_BODY" | grep -qE '^CHANGELOG:[[:space:]]*SKIP[[:space:]]*$'; then
echo "Skipping: PR is marked CHANGELOG: SKIP"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Prepare PR metadata for AI prompt
id: prep-pr-info
if: steps.check-skip.outputs.skip == 'false'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_BODY: ${{ github.event.pull_request.body }}
run: |
# Write all PR metadata to a temp file so it can be safely passed to the AI
# via file_input, avoiding any YAML injection from PR body content.
printf 'PR #%s — %s\nby @%s\n\n%s\n' \
"$PR_NUMBER" "$PR_TITLE" "$PR_AUTHOR" "$PR_BODY" \
> "${RUNNER_TEMP}/pr_info.txt"

- name: Update Release Announcement with GitHub Copilot
id: update-announcement
if: steps.check-skip.outputs.skip == 'false'
uses: actions/ai-inference@v1
with:
prompt-file: '.github/prompts/release-announcement.prompt.yml'
file_input: |
current_announcement: ReleaseAnnouncement.md
pr_info: ${{ runner.temp }}/pr_info.txt

- name: Write updated Release Announcement
if: steps.check-skip.outputs.skip == 'false'
env:
RESPONSE_FILE: ${{ steps.update-announcement.outputs.response-file }}
run: |
# Guard against an empty or missing response, which would wipe the file.
if [ ! -s "$RESPONSE_FILE" ]; then
echo "Warning: AI returned an empty response — skipping update."
exit 0
fi
cp "$RESPONSE_FILE" ReleaseAnnouncement.md

- name: Commit and push updated announcement
if: steps.check-skip.outputs.skip == 'false'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.email "actions@github.com"
git config --global user.name "github-actions[bot]"
git add ReleaseAnnouncement.md
# Exit cleanly if the AI returned the document unchanged (nothing to commit).
git diff --staged --quiet && exit 0
git commit -m "docs: update Release Announcement for PR #${{ github.event.pull_request.number }}"
git push

update-announcement-on-autobuild:
name: Update announcement for autobuild push
# Run on autobuild branch pushes in the main jamulussoftware repo.
# Skip when the pusher is the bot itself to prevent an infinite commit loop:
# autobuild.yml already has ReleaseAnnouncement.md in paths-ignore, so the
# bot commit will not re-trigger the build, but it would re-trigger this workflow.
if: >-
github.repository_owner == 'jamulussoftware' &&
startsWith(github.ref, 'refs/heads/autobuild') &&
github.actor != 'github-actions[bot]'
runs-on: ubuntu-latest
permissions:
contents: write
models: read

steps:
- uses: actions/checkout@v6
with:
# Check out the autobuild branch being pushed, so the announcement is
# updated and committed directly on that branch.
ref: ${{ github.ref }}

- name: Check if announcement update should be skipped
id: check-skip
env:
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
run: |
# Skip when the commit message explicitly marks the change as not user-facing.
if printf '%s\n' "$COMMIT_MESSAGE" | grep -qE '^CHANGELOG:[[:space:]]*SKIP[[:space:]]*$'; then
echo "Skipping: commit is marked CHANGELOG: SKIP"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Prepare commit metadata for AI prompt
id: prep-commit-info
if: steps.check-skip.outputs.skip == 'false'
env:
COMMIT_SHA: ${{ github.event.head_commit.id }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COMMIT_AUTHOR: ${{ github.event.head_commit.author.username }}
BRANCH_NAME: ${{ github.ref_name }}
run: |
# Write commit metadata to a temp file so it can be safely passed to the AI
# via file_input, avoiding any YAML injection from the commit message content.
printf 'Commit %s on branch %s\nby @%s\n\n%s\n' \
"$COMMIT_SHA" "$BRANCH_NAME" "$COMMIT_AUTHOR" "$COMMIT_MESSAGE" \
> "${RUNNER_TEMP}/commit_info.txt"

- name: Update Release Announcement with GitHub Copilot
id: update-announcement
if: steps.check-skip.outputs.skip == 'false'
uses: actions/ai-inference@v1
with:
prompt-file: '.github/prompts/release-announcement.prompt.yml'
file_input: |
current_announcement: ReleaseAnnouncement.md
pr_info: ${{ runner.temp }}/commit_info.txt

- name: Write updated Release Announcement
if: steps.check-skip.outputs.skip == 'false'
env:
RESPONSE_FILE: ${{ steps.update-announcement.outputs.response-file }}
run: |
# Guard against an empty or missing response, which would wipe the file.
if [ ! -s "$RESPONSE_FILE" ]; then
echo "Warning: AI returned an empty response — skipping update."
exit 0
fi
cp "$RESPONSE_FILE" ReleaseAnnouncement.md

- name: Commit and push updated announcement
if: steps.check-skip.outputs.skip == 'false'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.email "actions@github.com"
git config --global user.name "github-actions[bot]"
git add ReleaseAnnouncement.md
# Exit cleanly if the AI returned the document unchanged (nothing to commit).
git diff --staged --quiet && exit 0
git commit -m "docs: update Release Announcement for ${{ github.sha }}"
git push

reset-after-release:
name: Reset announcement after full release
# Only run on tag pushes in the main jamulussoftware repo.
if: >-
github.repository_owner == 'jamulussoftware' &&
github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v6
with:
ref: main

- name: Check if this is a full (non-prerelease) release tag
id: check-tag
run: |
# Match only clean version tags like r3_12_0.
# Tags with any suffix (e.g. r3_12_0beta1, r3_12_0rc1) are pre-releases
# and intentionally do NOT reset the draft, so it keeps building up
# towards the final release announcement.
if [[ "${GITHUB_REF_NAME}" =~ ^r([0-9]+)_([0-9]+)_([0-9]+)$ ]]; then
major="${BASH_REMATCH[1]}"
minor="${BASH_REMATCH[2]}"
patch="${BASH_REMATCH[3]}"
echo "is_full_release=true" >> "$GITHUB_OUTPUT"
echo "version=${major}.${minor}.${patch}" >> "$GITHUB_OUTPUT"
else
echo "is_full_release=false" >> "$GITHUB_OUTPUT"
fi

- name: Reset Release Announcement to template
if: steps.check-tag.outputs.is_full_release == 'true'
run: |
cp .github/release-announcement-template.md ReleaseAnnouncement.md

- name: Commit and push reset announcement
if: steps.check-tag.outputs.is_full_release == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.email "actions@github.com"
git config --global user.name "github-actions[bot]"
git add ReleaseAnnouncement.md
git diff --staged --quiet && exit 0
git commit -m "docs: reset Release Announcement after v${{ steps.check-tag.outputs.version }} release"
git push

2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Admins reserve the right to do this as they see fit.

The ChangeLog must be updated for each new feature or bug fix. Please include a single-sentence suggestion for that as part of your pull request description after the `CHANGELOG: ` keyword. Do not modify the ChangeLog file as part of your PR as it will lead to conflicts.

The same `CHANGELOG:` line is also used to automatically update the working [Release Announcement draft](ReleaseAnnouncement.md), which is a curated summary for end users and server operators. Use `CHANGELOG: SKIP` to skip both the ChangeLog entry and the Release Announcement update for purely internal changes (CI, build system, code style fixes, etc.).

If you are a first-time contributor/translator, please add your name to the contributors/translators list in the About dialog of Jamulus (see in `src/util.cpp` in the constructor function `CAboutDlg::CAboutDlg()`).

### Merging pull requests
Expand Down
Loading
Loading