|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# GitHub Actions script to generate AI-powered PR descriptions using Amazon Bedrock |
| 4 | +# This script analyzes commit history and generates formatted PR descriptions matching LISA's changelog format |
| 5 | + |
| 6 | +set -e # Exit on any error |
| 7 | + |
| 8 | +RELEASE_TAG="$1" |
| 9 | + |
| 10 | +if [ -z "$RELEASE_TAG" ]; then |
| 11 | + echo "Error: Release tag is required as first argument" |
| 12 | + exit 1 |
| 13 | +fi |
| 14 | + |
| 15 | +echo "🔍 Fetching commit history and PR details for release branch (comparing against main)..." |
| 16 | + |
| 17 | +# Function to check if GitHub CLI is properly authenticated |
| 18 | +check_gh_auth() { |
| 19 | + if ! command -v gh >/dev/null 2>&1; then |
| 20 | + return 1 |
| 21 | + fi |
| 22 | + |
| 23 | + # Check authentication status with timeout |
| 24 | + if timeout 10s gh auth status >/dev/null 2>&1; then |
| 25 | + return 0 |
| 26 | + else |
| 27 | + return 1 |
| 28 | + fi |
| 29 | +} |
| 30 | + |
| 31 | +# Function to get PR info for a commit |
| 32 | +get_commit_pr_info() { |
| 33 | + local commit_hash="$1" |
| 34 | + local commit_subject="$2" |
| 35 | + local commit_author="$3" |
| 36 | + |
| 37 | + # Try to find associated PRs using GitHub CLI (only if authenticated) |
| 38 | + if [[ "$GH_AUTHENTICATED" == "true" ]]; then |
| 39 | + # Use timeout to prevent hanging and suppress errors |
| 40 | + local pr_info=$(timeout 15s gh pr list --search "$commit_hash" --state merged --json number,title,body --limit 1 2>/dev/null || echo "[]") |
| 41 | + |
| 42 | + if [[ "$pr_info" != "[]" ]] && [[ -n "$pr_info" ]] && [[ "$pr_info" != *"error"* ]]; then |
| 43 | + local pr_number=$(echo "$pr_info" | jq -r '.[0].number // empty' 2>/dev/null) |
| 44 | + local pr_title=$(echo "$pr_info" | jq -r '.[0].title // empty' 2>/dev/null) |
| 45 | + local pr_body=$(echo "$pr_info" | jq -r '.[0].body // empty' 2>/dev/null) |
| 46 | + |
| 47 | + if [[ -n "$pr_number" && -n "$pr_title" && "$pr_number" != "null" ]]; then |
| 48 | + echo "- $commit_subject ($commit_author)" |
| 49 | + echo " PR #$pr_number: $pr_title" |
| 50 | + |
| 51 | + if [[ -n "$pr_body" && "$pr_body" != "null" ]]; then |
| 52 | + # Truncate very long PR descriptions and clean up formatting |
| 53 | + local cleaned_body=$(echo "$pr_body" | head -c 500 | tr '\n' ' ' | tr -s ' ') |
| 54 | + echo " $cleaned_body" |
| 55 | + fi |
| 56 | + return 0 |
| 57 | + fi |
| 58 | + fi |
| 59 | + fi |
| 60 | + |
| 61 | + # Fallback to commit message only |
| 62 | + echo "- $commit_subject ($commit_author)" |
| 63 | + return 1 |
| 64 | +} |
| 65 | + |
| 66 | +# Check GitHub CLI authentication status |
| 67 | +if check_gh_auth; then |
| 68 | + echo "✅ GitHub CLI authenticated - will attempt PR lookups" |
| 69 | + GH_AUTHENTICATED="true" |
| 70 | +else |
| 71 | + echo "⚠️ GitHub CLI not available or not authenticated - using commit messages only" |
| 72 | + echo " To enable PR lookups, run: gh auth login" |
| 73 | + GH_AUTHENTICATED="false" |
| 74 | +fi |
| 75 | + |
| 76 | +# Get commits with PR information |
| 77 | +COMMITS="" |
| 78 | +commit_count=0 |
| 79 | +pr_found_count=0 |
| 80 | +echo "📡 Looking up commit information..." |
| 81 | + |
| 82 | +while IFS='|' read -r hash subject author; do |
| 83 | + if [[ -n "$hash" ]]; then |
| 84 | + # Get commit info and handle return code properly with set -e |
| 85 | + commit_info=$(get_commit_pr_info "$hash" "$subject" "$author") || commit_return_code=$? |
| 86 | + |
| 87 | + # Check if PR info was found (return code 0 means PR found) |
| 88 | + if [[ -z "$commit_return_code" ]]; then |
| 89 | + pr_found_count=$((pr_found_count + 1)) |
| 90 | + fi |
| 91 | + |
| 92 | + if [[ -n "$COMMITS" ]]; then |
| 93 | + COMMITS="$COMMITS"$'\n'"$commit_info" |
| 94 | + else |
| 95 | + COMMITS="$commit_info" |
| 96 | + fi |
| 97 | + commit_count=$((commit_count + 1)) |
| 98 | + |
| 99 | + # Show progress for long-running operations |
| 100 | + if [[ $((commit_count % 3)) -eq 0 ]]; then |
| 101 | + echo " ... processed $commit_count commits" |
| 102 | + fi |
| 103 | + |
| 104 | + # Reset the return code variable for next iteration |
| 105 | + unset commit_return_code |
| 106 | + fi |
| 107 | +done < <(git log main..HEAD --pretty=format:"%H|%s|%an" --no-merges) |
| 108 | + |
| 109 | +echo "✅ Processed $commit_count commits" |
| 110 | +if [[ "$GH_AUTHENTICATED" == "true" ]]; then |
| 111 | + echo "📊 Found PR information for $pr_found_count commits" |
| 112 | +fi |
| 113 | + |
| 114 | +# Get unique contributors from commits for acknowledgements (use email to extract GitHub username) |
| 115 | +CONTRIBUTORS=$(git log main..HEAD --pretty=format:"%ae" --no-merges | sort -u | sed 's/@.*$//' | sed 's/^/* @/' | tr '\n' '\n') |
| 116 | + |
| 117 | +# If no commits, use a default message |
| 118 | +if [ -z "$COMMITS" ]; then |
| 119 | + COMMITS="- Version update to $RELEASE_TAG" |
| 120 | + CONTRIBUTORS="* @github_actions_lisa" |
| 121 | +fi |
| 122 | + |
| 123 | +echo "📝 Found commits:" |
| 124 | +echo -e "$COMMITS" |
| 125 | +echo "" |
| 126 | +echo "👥 Contributors: $CONTRIBUTORS" |
| 127 | +echo "" |
| 128 | + |
| 129 | +# Create a prompt for Bedrock to generate PR description matching LISA's changelog format |
| 130 | +PROMPT="Please create a professional pull request description for the LISA software release that follows this EXACT format template: |
| 131 | +
|
| 132 | +# $RELEASE_TAG |
| 133 | +
|
| 134 | +## Key Features |
| 135 | +
|
| 136 | +### [Feature Name 1] |
| 137 | +[Description of the feature and its capabilities] |
| 138 | +**[Subcategory if needed]:** |
| 139 | +- **[Component]**: [Description of enhancement] |
| 140 | +- **[Component]**: [Description of enhancement] |
| 141 | +
|
| 142 | +### [Feature Name 2] |
| 143 | +[Description of the feature] |
| 144 | +
|
| 145 | +## Key Changes |
| 146 | +- **[Category]**: [Description of change] |
| 147 | +- **[Category]**: [Description of change] |
| 148 | +- **[Category]**: [Description of change] |
| 149 | +
|
| 150 | +## Acknowledgements |
| 151 | +$CONTRIBUTORS |
| 152 | +
|
| 153 | +**Full Changelog**: https://github.com/awslabs/LISA/compare/[previous-version]..$RELEASE_TAG |
| 154 | +
|
| 155 | +--- |
| 156 | +
|
| 157 | +Based on these commits from the release: |
| 158 | +$COMMITS |
| 159 | +
|
| 160 | +Requirements: |
| 161 | +1. Use the EXACT format template above with # for version header |
| 162 | +2. Group related commits into logical Key Features sections with descriptive subsection names |
| 163 | +3. List implementation details in Key Changes as bullet points with bold category labels |
| 164 | +4. Use professional, concise language appropriate for a software release |
| 165 | +5. Focus on user-facing improvements and system enhancements |
| 166 | +6. Include the contributors list and changelog link as shown |
| 167 | +7. If there are only version/build commits, create a simple 'System Updates' feature section |
| 168 | +
|
| 169 | +Generate the description now:" |
| 170 | + |
| 171 | +# Call Bedrock to generate description |
| 172 | +echo "🤖 Generating PR description with Bedrock Claude 3 Haiku..." |
| 173 | + |
| 174 | +# Use jq to properly construct the JSON payload to avoid escaping issues |
| 175 | +BEDROCK_PAYLOAD=$(jq -n \ |
| 176 | + --arg prompt "$PROMPT" \ |
| 177 | + '{ |
| 178 | + "anthropic_version": "bedrock-2023-05-31", |
| 179 | + "max_tokens": 1500, |
| 180 | + "messages": [ |
| 181 | + { |
| 182 | + "role": "user", |
| 183 | + "content": $prompt |
| 184 | + } |
| 185 | + ] |
| 186 | + }') |
| 187 | + |
| 188 | +RESPONSE=$(aws bedrock-runtime invoke-model \ |
| 189 | + --model-id "anthropic.claude-3-haiku-20240307-v1:0" \ |
| 190 | + --body "$BEDROCK_PAYLOAD" \ |
| 191 | + --cli-binary-format raw-in-base64-out \ |
| 192 | + /tmp/bedrock_response.json) |
| 193 | + |
| 194 | +# Extract the generated description from the response |
| 195 | +DESCRIPTION=$(jq -r '.content[0].text' /tmp/bedrock_response.json) |
| 196 | + |
| 197 | +# Fallback description if Bedrock fails - use LISA changelog format |
| 198 | +if [ -z "$DESCRIPTION" ] || [ "$DESCRIPTION" = "null" ]; then |
| 199 | + echo "⚠️ Bedrock response failed, using fallback description" |
| 200 | + DESCRIPTION="# $RELEASE_TAG |
| 201 | +
|
| 202 | +## Key Features |
| 203 | +
|
| 204 | +### System Updates |
| 205 | +This release includes version updates and system improvements to enhance LISA's stability and performance. |
| 206 | +
|
| 207 | +## Key Changes |
| 208 | +- **Version Management**: Updated version numbers across all package files |
| 209 | +- **Release Process**: Automated release branch creation and versioning |
| 210 | +- **System Maintenance**: General system updates and improvements |
| 211 | +
|
| 212 | +## Acknowledgements |
| 213 | +$CONTRIBUTORS |
| 214 | +
|
| 215 | +**Full Changelog**: https://github.com/awslabs/LISA/compare/[previous-version]..$RELEASE_TAG" |
| 216 | +else |
| 217 | + echo "✅ Successfully generated PR description with Bedrock" |
| 218 | +fi |
| 219 | + |
| 220 | +echo "" |
| 221 | +echo "📋 Generated PR description:" |
| 222 | +echo "----------------------------------------" |
| 223 | +echo "$DESCRIPTION" |
| 224 | +echo "----------------------------------------" |
| 225 | + |
| 226 | +# Save description to GitHub Actions output |
| 227 | +{ |
| 228 | + echo 'DESCRIPTION<<EOF' |
| 229 | + echo "$DESCRIPTION" |
| 230 | + echo 'EOF' |
| 231 | +} >> $GITHUB_OUTPUT |
0 commit comments