Surfaces release highlights to admins, sourced from the GitHub release notes (no AI at runtime). Bullets are written once per release in CI via GitHub Models (see docs/ci/whatsnew-highlights.yml) into a <!-- whatsnew --> block; the app reads that block and falls back to the changelog's "### Features" for releases without it — so it works against today's releases immediately. - backend utils/whatsNew.parseWhatsNew(body): curated block else Features section, strips scope/PR-links, de-dups, caps at 8 (tested). - GET /admin/system/updates/whatsnew: highlights for every version moved through since the per-instance marker (whatsnew_last_seen_version); fresh installs self-anchor silently. Best-effort, never errors. - POST /admin/system/updates/whatsnew/seen: advance the marker (per-instance). - /admin/system/updates also returns latestHighlights for the teaser. - Frontend: WhatsNewBanner (green bar -> modal with "Full changelog" link) on the dashboard via adminService; UpdateNotification shows a "New features include:" teaser. i18n de/en. No migration (uses app_settings).
77 lines
3.5 KiB
YAML
77 lines
3.5 KiB
YAML
# What's New highlights — GitHub Models release step
|
|
#
|
|
# DRAFT — move this into `.github/workflows/` on the repo that publishes the
|
|
# canonical releases the app reads (PicPeak/picpeak). It is kept under docs/
|
|
# here so it does NOT auto-run on the fork.
|
|
#
|
|
# What it does: when a release is published (release-please), it condenses that
|
|
# release's "### Features" into <=8 short bullets via GitHub Models (free tier,
|
|
# `models: read`) and injects a `<!-- whatsnew -->` block at the top of the
|
|
# release notes. The picpeak app reads that block (utils/whatsNew.parseWhatsNew),
|
|
# and falls back to the raw Features list for releases without it — so this is
|
|
# purely a quality upgrade, never a hard dependency.
|
|
#
|
|
# Validated end-to-end on a fork (extract -> openai/gpt-4o-mini -> inject into
|
|
# real release notes; app parseWhatsNew() reads the block back). The one thing
|
|
# that can't be checked from a fork: GitHub Models must be enabled for the
|
|
# PicPeak ORG (owner setting). Failure is isolated anyway by `continue-on-error`
|
|
# + the deterministic fallback below, so it can never break a release.
|
|
|
|
name: What's New highlights
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
|
|
permissions:
|
|
contents: write # to edit the release body
|
|
models: read # GitHub Models (free tier)
|
|
|
|
jobs:
|
|
highlights:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Extract Features from the published release
|
|
id: feat
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
TAG: ${{ github.event.release.tag_name }}
|
|
run: |
|
|
BODY=$(gh release view "$TAG" --json body -q .body)
|
|
FEATURES=$(printf '%s\n' "$BODY" | awk '/^#{2,4} +Features/{f=1;next} /^#{1,4} +\S/{f=0} f')
|
|
{ echo "features<<EOF"; printf '%s\n' "$FEATURES"; echo EOF; } >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Summarize with GitHub Models
|
|
if: ${{ steps.feat.outputs.features != '' }}
|
|
id: ai
|
|
uses: actions/ai-inference@v1
|
|
with:
|
|
model: openai/gpt-4o-mini # catalog id (verified present); openai/gpt-4.1-mini or openai/gpt-5-nano also work
|
|
system-prompt: >
|
|
You write release highlights for the admins of a self-hosted
|
|
photo-gallery + CRM app. Given raw changelog "Features" lines, output
|
|
AT MOST 8 markdown bullets, each 3-4 words, user-facing, no scopes,
|
|
no jargon, no issue numbers. One bullet per distinct user-visible
|
|
feature. Output ONLY "- " bullets, nothing else.
|
|
prompt: ${{ steps.feat.outputs.features }}
|
|
|
|
- name: Inject the What's New block
|
|
if: ${{ steps.feat.outputs.features != '' }}
|
|
continue-on-error: true # never let highlights break a release
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
TAG: ${{ github.event.release.tag_name }}
|
|
AI: ${{ steps.ai.outputs.response }}
|
|
FEATURES: ${{ steps.feat.outputs.features }}
|
|
run: |
|
|
BULLETS="$AI"
|
|
# Deterministic fallback if the model returned nothing.
|
|
if [ -z "$BULLETS" ]; then
|
|
BULLETS=$(printf '%s\n' "$FEATURES" | head -8 \
|
|
| sed -E 's/^\* \*\*[^:]+:\*\* */- /; s/ \(\[[^]]*\]\([^)]*\)\)//g')
|
|
fi
|
|
BODY=$(gh release view "$TAG" --json body -q .body)
|
|
# Idempotent: strip any prior block before re-injecting.
|
|
BODY=$(printf '%s' "$BODY" | perl -0pe 's/<!--\s*whatsnew\s*-->.*?<!--\s*\/whatsnew\s*-->\n*//is')
|
|
gh release edit "$TAG" --notes "$(printf '<!-- whatsnew -->\n%s\n<!-- /whatsnew -->\n\n%s' "$BULLETS" "$BODY")"
|