diff --git a/scripts/generate-release-notes.sh b/scripts/generate-release-notes.sh index 03e56309f..979a731bb 100755 --- a/scripts/generate-release-notes.sh +++ b/scripts/generate-release-notes.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Generate release notes using LLM analysis of git commits +# Generate release notes using LLM analysis of actual code diffs (not commit messages) # Usage: ./scripts/generate-release-notes.sh [previous-tag] set -euo pipefail @@ -18,139 +18,171 @@ fi if [ -z "$PREVIOUS_TAG" ]; then PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") if [ -z "$PREVIOUS_TAG" ]; then - echo "No previous tag found, using all commits" - PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD) + echo "No previous tag found, cannot generate diff-based release notes" + exit 1 fi fi echo "Generating release notes for v${VERSION}..." -echo "Analyzing commits since ${PREVIOUS_TAG}..." +echo "Comparing code changes from ${PREVIOUS_TAG} to HEAD..." -# Get commit log -COMMIT_LOG=$(git log ${PREVIOUS_TAG}..HEAD --pretty=format:"%h %s" --no-merges) +# Get diff stats (excluding non-user-facing files) +DIFF_STAT=$(git diff ${PREVIOUS_TAG}..HEAD --stat \ + -- ':!*.md' ':!*.test.go' ':!*_test.go' ':!*_test.tsx' ':!*_test.ts' \ + ':!.github/*' ':!tests/*' ':!docs/*' ':!*.txt' ':!*.json' ':!go.sum' \ + ':!frontend-modern/src/**/__tests__/*' \ + | tail -20) -if [ -z "$COMMIT_LOG" ]; then - echo "No commits found since ${PREVIOUS_TAG}" - exit 1 -fi +# Get list of changed user-facing files +CHANGED_FILES=$(git diff ${PREVIOUS_TAG}..HEAD --name-only \ + -- ':!*.md' ':!*.test.go' ':!*_test.go' ':!*_test.tsx' ':!*_test.ts' \ + ':!.github/*' ':!tests/*' ':!docs/*' ':!*.txt' ':!go.sum' \ + ':!frontend-modern/src/**/__tests__/*' \ + | head -100) -# Count commits -COMMIT_COUNT=$(echo "$COMMIT_LOG" | wc -l) -echo "Found ${COMMIT_COUNT} commits" +# Get specific diffs for key user-facing areas (truncated for API limits) -# Generate release notes using LLM API -# Supports both OpenAI and Anthropic Claude -# Set either OPENAI_API_KEY or ANTHROPIC_API_KEY +# API routes/handlers - new endpoints +API_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'internal/api/*.go' ':!*_test.go' \ + | grep -E '^\+.*func.*Handle|^\+.*router\.(GET|POST|PUT|DELETE|PATCH)|^\+.*\.Path\(' \ + | head -30 || echo "") +# Frontend pages and components - new features +FRONTEND_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'frontend-modern/src/components/*.tsx' 'frontend-modern/src/pages/*.tsx' \ + ':!*_test.tsx' ':!*__tests__*' \ + | grep -E '^\+.*export|^\+.*function.*\(|^\+.*const.*=' \ + | head -40 || echo "") + +# Config options - new settings users can configure +CONFIG_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'internal/config/*.go' ':!*_test.go' \ + | grep -E '^\+.*`json:|^\+.*`yaml:' \ + | head -20 || echo "") + +# Notifications/alerts - webhook changes, alert features +ALERT_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'internal/notifications/*.go' 'internal/alerts/*.go' ':!*_test.go' \ + | grep -E '^\+' \ + | head -30 || echo "") + +# Agent changes - host/docker agent features +AGENT_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'cmd/pulse-agent/*.go' 'internal/agent/*.go' ':!*_test.go' \ + | grep -E '^\+' \ + | head -20 || echo "") + +# Install script changes +INSTALL_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'scripts/install.sh' 'install.sh' \ + | grep -E '^\+' \ + | head -20 || echo "") + +# Models/types - new data structures +MODELS_DIFF=$(git diff ${PREVIOUS_TAG}..HEAD -- 'internal/models/*.go' ':!*_test.go' \ + | grep -E '^\+.*type.*struct|^\+.*`json:' \ + | head -20 || echo "") + +echo "Collected diffs from key areas" + +# Check for LLM API keys if [ -n "${ANTHROPIC_API_KEY:-}" ]; then LLM_PROVIDER="anthropic" elif [ -n "${OPENAI_API_KEY:-}" ]; then LLM_PROVIDER="openai" else - echo "No LLM API keys detected – falling back to deterministic release notes." - LLM_PROVIDER="fallback" + echo "No LLM API keys detected – cannot generate diff-based notes." + echo "Set ANTHROPIC_API_KEY or OPENAI_API_KEY" + exit 1 fi echo "Using LLM provider: ${LLM_PROVIDER}" -# Prepare prompt for LLM +# Build the prompt with actual code changes read -r -d '' PROMPT <&2 - if ! RELEASE_NOTES=$(generate_with_openai); then - echo "OpenAI fallback failed; generating heuristic release notes." >&2 - RELEASE_NOTES=$(generate_fallback_release_notes) - fi - LLM_PROVIDER="openai" + RELEASE_NOTES=$(generate_with_openai) || { + echo "Both LLM providers failed" >&2 + exit 1 + } else - echo "Anthropic generation failed and no OpenAI fallback is available; generating heuristic release notes." >&2 - RELEASE_NOTES=$(generate_fallback_release_notes) + echo "Anthropic generation failed and no OpenAI fallback" >&2 + exit 1 fi fi else - if ! RELEASE_NOTES=$(generate_with_openai); then - echo "OpenAI generation failed; generating heuristic release notes." >&2 - RELEASE_NOTES=$(generate_fallback_release_notes) - fi + RELEASE_NOTES=$(generate_with_openai) || { + echo "OpenAI generation failed" >&2 + exit 1 + } fi if [ -z "$RELEASE_NOTES" ] || [ "$RELEASE_NOTES" = "null" ]; then