diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index acf04a99f..be23c4dfd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -156,6 +156,34 @@ jobs: exit 1 } + - name: Generate release notes + id: generate_notes + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + run: | + echo "Generating release notes using LLM..." + + # Find previous release tag + PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 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) + fi + + echo "Comparing v${{ inputs.version }} with ${PREVIOUS_TAG}..." + + # Generate notes and capture output + RELEASE_NOTES=$(./scripts/generate-release-notes.sh ${{ inputs.version }} "${PREVIOUS_TAG}" 2>&1 | sed -n '/^Generated release notes:/,/^━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$/{ /^Generated release notes:/d; /^━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$/d; p; }') + + # Save to output (escape for GitHub Actions multiline) + echo "RELEASE_NOTES<> $GITHUB_OUTPUT + echo "$RELEASE_NOTES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + echo "✅ Release notes generated successfully" + - name: Create draft release id: create_release env: @@ -166,30 +194,14 @@ jobs: echo "Creating draft release for ${TAG}..." - # Create draft release with placeholder body + # Use LLM-generated release notes + NOTES="${{ steps.generate_notes.outputs.RELEASE_NOTES }}" + + # Create draft release with generated notes gh release create "${TAG}" \ --draft \ --title "Pulse ${TAG}" \ - --notes "Release ${TAG} - - ## What's Changed - - - - ## Installation - - Quick install on Linux: - \`\`\`bash - curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | sudo bash - \`\`\` - - Or download platform-specific archives below. - - ## Docker Images - - Docker images are available for this release: - - \`rcourtman/pulse:${TAG}\` - - \`rcourtman/pulse-docker-agent:${TAG}\`" + --notes "$NOTES" echo "release_url=$(gh release view ${TAG} --json url -q .url)" >> $GITHUB_OUTPUT echo "tag=${TAG}" >> $GITHUB_OUTPUT diff --git a/scripts/generate-release-notes.sh b/scripts/generate-release-notes.sh new file mode 100755 index 000000000..1a359e96f --- /dev/null +++ b/scripts/generate-release-notes.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +# Generate release notes using LLM analysis of git commits +# Usage: ./scripts/generate-release-notes.sh [previous-tag] + +set -euo pipefail + +VERSION=${1:-} +PREVIOUS_TAG=${2:-} + +if [ -z "$VERSION" ]; then + echo "Usage: $0 [previous-tag]" + echo "Example: $0 4.29.0 v4.28.0" + exit 1 +fi + +# Find previous tag if not specified +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) + fi +fi + +echo "Generating release notes for v${VERSION}..." +echo "Analyzing commits since ${PREVIOUS_TAG}..." + +# Get commit log +COMMIT_LOG=$(git log ${PREVIOUS_TAG}..HEAD --pretty=format:"%h %s" --no-merges) + +if [ -z "$COMMIT_LOG" ]; then + echo "No commits found since ${PREVIOUS_TAG}" + exit 1 +fi + +# Count commits +COMMIT_COUNT=$(echo "$COMMIT_LOG" | wc -l) +echo "Found ${COMMIT_COUNT} commits" + +# Generate release notes using LLM API +# Supports both OpenAI and Anthropic Claude +# Set either OPENAI_API_KEY or ANTHROPIC_API_KEY + +if [ -n "${ANTHROPIC_API_KEY:-}" ]; then + LLM_PROVIDER="anthropic" +elif [ -n "${OPENAI_API_KEY:-}" ]; then + LLM_PROVIDER="openai" +else + echo "Error: Either OPENAI_API_KEY or ANTHROPIC_API_KEY environment variable must be set" + exit 1 +fi + +echo "Using LLM provider: ${LLM_PROVIDER}" + +# Prepare prompt for LLM +read -r -d '' PROMPT < "$OUTPUT_FILE" + echo "" + echo "Saved to: $OUTPUT_FILE" +fi