diff --git a/.github/workflows/update-studio-docs.yml b/.github/workflows/update-studio-docs.yml index 6e4de38b14..541ceeaf30 100644 --- a/.github/workflows/update-studio-docs.yml +++ b/.github/workflows/update-studio-docs.yml @@ -43,16 +43,24 @@ jobs: echo "url=${{ github.event.client_payload.url }}" >> $GITHUB_OUTPUT echo "target_branch=${{ github.event.client_payload.target_branch || 'dev' }}" >> $GITHUB_OUTPUT - mkdir -p .tmp - jq -r '.client_payload.notes' "$GITHUB_EVENT_PATH" > .tmp/raw-notes.txt + # Save notes to environment variable (multiline) + { + echo "RAW_NOTES<> $GITHUB_ENV else echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT echo "name=${{ github.event.inputs.name }}" >> $GITHUB_OUTPUT echo "url=${{ github.event.inputs.url }}" >> $GITHUB_OUTPUT echo "target_branch=${{ github.event.inputs.target_branch || 'dev' }}" >> $GITHUB_OUTPUT - mkdir -p .tmp - echo "${{ github.event.inputs.notes }}" > .tmp/raw-notes.txt + # Save notes to environment variable (multiline) + { + echo "RAW_NOTES<> $GITHUB_ENV fi - name: Validate payload @@ -74,7 +82,7 @@ jobs: echo "❌ Missing: url" exit 1 fi - if [ ! -s .tmp/raw-notes.txt ]; then + if [ -z "$RAW_NOTES" ]; then echo "❌ Missing: release notes" exit 1 fi @@ -158,7 +166,7 @@ jobs: Version: ${{ steps.payload.outputs.version }} Name: ${{ steps.payload.outputs.name }} Raw notes: - $(cat .tmp/raw-notes.txt) + ${{ env.RAW_NOTES }} CRITICAL RULES: 1. Extract ONLY essential, user-facing changes @@ -181,28 +189,64 @@ jobs: # ------------------------------------------------- - name: Prepare final release notes run: | + mkdir -p .tmp + AI_RESPONSE="${{ steps.ai.outputs.response }}" if [ -n "$AI_RESPONSE" ] && [ "$AI_RESPONSE" != "null" ]; then echo "✅ Using AI-formatted release notes" echo "$AI_RESPONSE" > .tmp/final-notes.txt else - echo "⚠️ AI unavailable - using raw release notes with basic formatting" + echo "⚠️ AI unavailable - using aggressive cleaning on raw release notes" - # Basic fallback: ensure each line starts with "- " - while IFS= read -r line; do + # Clean and format raw notes with aggressive filtering + echo "$RAW_NOTES" | while IFS= read -r line; do # Skip empty lines - if [ -z "$line" ]; then - continue - fi + [ -z "$line" ] && continue + + # Skip section headers + [[ "$line" =~ ^#+.*What.*Changed ]] && continue + [[ "$line" =~ ^##[[:space:]] ]] && continue + + # Skip full changelog links + [[ "$line" =~ ^\*\*Full\ Changelog ]] && continue + [[ "$line" =~ ^Full\ Changelog ]] && continue + + # Remove leading bullet/asterisk + line=$(echo "$line" | sed 's/^[[:space:]]*[*-][[:space:]]*//') + + # Aggressive cleaning: remove entire " by @user in https://..." suffix + line=$(echo "$line" | sed 's/[[:space:]]*by @[a-zA-Z0-9_-]*[[:space:]]*in https:\/\/github\.com\/[^[:space:]]*//g') + + # Remove remaining "by @username" or "by username" + line=$(echo "$line" | sed 's/[[:space:]]*by @[a-zA-Z0-9_-]*[[:space:]]*$//g') + line=$(echo "$line" | sed 's/[[:space:]]*by [a-zA-Z0-9_-]*[[:space:]]*$//g') - # Add bullet if not present - if [[ ! "$line" =~ ^[[:space:]]*- ]]; then - echo "- $line" - else - echo "$line" - fi - done < .tmp/raw-notes.txt > .tmp/final-notes.txt + # Remove standalone @mentions + line=$(echo "$line" | sed 's/@[a-zA-Z0-9_-]*//g') + + # Clean trailing periods if orphaned + line=$(echo "$line" | sed 's/\.[[:space:]]*$//') + + # Trim all whitespace + line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + # Skip if line is empty or too short + [ -z "$line" ] && continue + [ ${#line} -lt 5 ] && continue + + # Capitalize first letter if lowercase + line="$(echo ${line:0:1} | tr '[:lower:]' '[:upper:]')${line:1}" + + # Add clean bullet and output + echo "- $line" + done > .tmp/final-notes.txt + fi + + # Safety check: verify we have content + if [ ! -s .tmp/final-notes.txt ]; then + echo "⚠️ No valid release notes extracted, using minimal fallback" + echo "- Release ${{ steps.payload.outputs.version }}" > .tmp/final-notes.txt fi echo "=== Final release notes ===" @@ -358,18 +402,27 @@ jobs: # Find table start (skip SEO and headers) table_start = 0 + table_end = 0 for i, line in enumerate(lines): if line.strip().startswith('|') and '**ABP Studio Version**' in line: table_start = i + elif table_start > 0 and line.strip() and not line.strip().startswith('|'): + table_end = i break if table_start == 0: print("❌ Could not find version mapping table") exit(1) - # Extract header + separator + data rows - header_lines = lines[:table_start+2] # Keep everything before data rows - data_rows = [l for l in lines[table_start+2:] if l.strip().startswith('|')] + # If no end found, table goes to end of file + if table_end == 0: + table_end = len(lines) + + # Extract sections + before_table = lines[:table_start] # Everything before table + table_header = lines[table_start:table_start+2] # Header + separator + data_rows = [l for l in lines[table_start+2:table_end] if l.strip().startswith('|')] # Data rows + after_table = lines[table_end:] # Everything after table new_rows = [] handled = False @@ -449,9 +502,12 @@ jobs: new_rows.insert(0, new_row) print(f"✅ Added new mapping: {studio_ver} -> {abp_ver}") - # Write updated file + # Write updated file - preserve ALL content with open(file_path, 'w') as f: - f.writelines(header_lines + new_rows) + f.writelines(before_table) # SEO, title, intro text + f.writelines(table_header) # Table header + f.writelines(new_rows) # Updated data rows + f.writelines(after_table) # Content after table (preview section, etc.) print("MAPPING_UPDATED=true") PYTHON_EOF