Skip to content

Commit f612506

Browse files
committed
List fixed issues in release notes (#54)
1 parent a8c7431 commit f612506

2 files changed

Lines changed: 101 additions & 2 deletions

File tree

.github/workflows/deploy-github-pages.yml

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,13 @@ jobs:
314314

315315
permissions:
316316
contents: write
317+
issues: read
317318

318319
steps:
319320
- name: Checkout
320321
uses: actions/checkout@v6
322+
with:
323+
fetch-depth: 0
321324

322325
- name: Download release artifact
323326
uses: actions/download-artifact@v8.0.1
@@ -336,6 +339,98 @@ jobs:
336339
337340
echo "release_asset=$release_asset" >> "$GITHUB_OUTPUT"
338341
342+
- name: Build release notes with fixed issues
343+
id: release_notes
344+
env:
345+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
346+
GH_REPO: ${{ github.repository }}
347+
RELEASE_TAG: ${{ needs.prepare_release.outputs.release_tag }}
348+
RELEASE_TITLE: PrompterOne ${{ needs.prepare_release.outputs.release_version }}
349+
run: |
350+
set -euo pipefail
351+
352+
notes_path="$RUNNER_TEMP/release-notes.md"
353+
previous_tag="$(
354+
gh release list \
355+
--exclude-drafts \
356+
--limit 50 \
357+
--json tagName \
358+
--jq ".[] | select(.tagName != \"$RELEASE_TAG\") | .tagName" \
359+
| head -n 1
360+
)"
361+
362+
if [ -n "$previous_tag" ] && git rev-parse --verify "${previous_tag}^{commit}" >/dev/null 2>&1; then
363+
commit_range="${previous_tag}..${GITHUB_SHA}"
364+
range_label="${previous_tag}...${RELEASE_TAG}"
365+
else
366+
commit_range="${GITHUB_SHA}"
367+
range_label="Initial release range ending at ${GITHUB_SHA}"
368+
fi
369+
370+
mapfile -t issue_numbers < <(
371+
git log --format='%B' "$commit_range" \
372+
| grep -Eo '#[0-9]+' \
373+
| tr -d '#' \
374+
| sort -n \
375+
| uniq
376+
)
377+
378+
issues_file="$RUNNER_TEMP/release-issues.md"
379+
{
380+
echo "## Fixed Issues"
381+
echo
382+
383+
issue_count=0
384+
for issue_number in "${issue_numbers[@]}"; do
385+
issue_json="$(
386+
gh api "repos/${GH_REPO}/issues/${issue_number}" \
387+
--jq 'select(.pull_request == null) | {number, title, url: .html_url}' \
388+
2>/dev/null || true
389+
)"
390+
391+
if [ -z "$issue_json" ]; then
392+
continue
393+
fi
394+
395+
issue_title="$(jq -r '.title' <<<"$issue_json")"
396+
issue_url="$(jq -r '.url' <<<"$issue_json")"
397+
echo "- [#${issue_number}](${issue_url}) ${issue_title}"
398+
issue_count=$((issue_count + 1))
399+
done
400+
401+
if [ "$issue_count" -eq 0 ]; then
402+
echo "_No linked GitHub issues were found in commits for this release._"
403+
fi
404+
405+
echo
406+
echo "_Issue range: ${range_label}_"
407+
} > "$issues_file"
408+
409+
if [ -n "$previous_tag" ]; then
410+
generated_notes="$(
411+
gh api "repos/${GH_REPO}/releases/generate-notes" \
412+
-f tag_name="$RELEASE_TAG" \
413+
-f target_commitish="$GITHUB_SHA" \
414+
-f previous_tag_name="$previous_tag" \
415+
--jq '.body'
416+
)"
417+
else
418+
generated_notes="$(
419+
gh api "repos/${GH_REPO}/releases/generate-notes" \
420+
-f tag_name="$RELEASE_TAG" \
421+
-f target_commitish="$GITHUB_SHA" \
422+
--jq '.body'
423+
)"
424+
fi
425+
426+
{
427+
echo "$generated_notes"
428+
echo
429+
cat "$issues_file"
430+
} > "$notes_path"
431+
432+
echo "release_notes=$notes_path" >> "$GITHUB_OUTPUT"
433+
339434
- name: Create or update release tag and GitHub Release
340435
env:
341436
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -344,13 +439,16 @@ jobs:
344439
RELEASE_TITLE: PrompterOne ${{ needs.prepare_release.outputs.release_version }}
345440
run: |
346441
release_asset="${{ steps.release_asset.outputs.release_asset }}"
442+
release_notes="${{ steps.release_notes.outputs.release_notes }}"
347443
if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
348444
gh release upload "$RELEASE_TAG" "$release_asset" --clobber
349-
gh release edit "$RELEASE_TAG" --title "$RELEASE_TITLE"
445+
gh release edit "$RELEASE_TAG" \
446+
--title "$RELEASE_TITLE" \
447+
--notes-file "$release_notes"
350448
else
351449
gh release create "$RELEASE_TAG" "$release_asset" \
352450
--title "$RELEASE_TITLE" \
353-
--generate-notes \
451+
--notes-file "$release_notes" \
354452
--target "$GITHUB_SHA"
355453
fi
356454

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ Rule format:
134134
- Stakeholder feedback issues should be interpreted as additive feature or presentation requests by default; do not remove existing behavior from wording such as "replace", "remove", or "rename" unless the user explicitly confirms deletion.
135135
- When a CI test job fails, times out, or is cancelled, the workflow summary must still state which tests failed or that the run ended before per-test failure data was available; do not leave browser-suite failures represented only by generic job annotations.
136136
- Do not add or raise CI timeout settings as a fix for browser-suite instability or slow runs; fix the underlying failure path cleanly instead of masking it with workflow or step timeouts.
137+
- GitHub Releases must include a fixed-issues section generated from the commits included since the previous release; collect referenced GitHub issue numbers from commit messages and render issue number, title, and link in the release notes instead of relying only on generic auto-generated notes.
137138
- For TUnit reporting in GitHub Actions, prefer TUnit's built-in HTML report and the documented `actions/github-script` runtime exposure step over repo-local custom summary scripts or ad-hoc log parsers.
138139
- GitHub Actions test jobs must use the repo `tests/dotnet-test-progress.rsp` response file and enable TUnit coverage for every runnable test suite so CI measures the same minimal, non-ANSI test output and coverage signal expected locally; do not configure detailed per-test `Standard output` or empty `Error output` blocks as the default log format.
139140
- Public web hosting is split by role: the standalone PrompterOne app in this repo must publish on `app.prompter.one`, while the marketing landing site for `prompter.one` lives in the separate `PrompterOne-LandingPage` repository.

0 commit comments

Comments
 (0)