# GitHub Actions Workflow for Plugin Release
# 插件发布工作流
#
# This workflow automates the release process for OpenWebUI plugins.
# 此工作流自动化 OpenWebUI 插件的发布流程。
#
# Triggers:
# - Push to main branch when plugins are modified (auto-release)
# - Manual trigger (workflow_dispatch) with custom release notes
# - Push of version tags (v*)
#
# What it does:
# 1. Detects plugin version changes compared to the last release
# 2. Generates release notes with updated plugin information
# 3. Creates a GitHub Release with plugin files as downloadable assets
# 4. Supports multiple plugin updates in a single release

name: Plugin Release / 插件发布

on:
  # Auto-trigger on push to main when plugins are modified
  push:
    branches:
      - main
    paths:
      - 'plugins/**/*.py'
    tags:
      - 'v*'

  # Manual trigger with inputs
  workflow_dispatch:
    inputs:
      version:
        description: 'Release version (e.g., v1.0.0). Leave empty for auto-generated version.'
        required: false
        type: string
      release_title:
        description: 'Release title (optional)'
        required: false
        type: string
      release_notes:
        description: 'Additional release notes (Markdown)'
        required: false
        type: string
      prerelease:
        description: 'Mark as pre-release'
        required: false
        type: boolean
        default: false

permissions:
  contents: write

jobs:
  check-changes:
    runs-on: ubuntu-latest
    env:
      LANG: en_US.UTF-8
      LC_ALL: en_US.UTF-8
    outputs:
      has_changes: ${{ steps.detect.outputs.has_changes }}
      changed_plugins: ${{ steps.detect.outputs.changed_plugins }}
      release_notes: ${{ steps.detect.outputs.release_notes }}
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Configure Git
        run: |
          git config --global core.quotepath false
          git config --global i18n.commitencoding utf-8
          git config --global i18n.logoutputencoding utf-8

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Detect plugin changes
        id: detect
        run: |
          # Get the last release tag
          LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
          
          if [ -z "$LAST_TAG" ]; then
            echo "No previous release found, treating all plugins as new"
            COMPARE_REF="$(git rev-list --max-parents=0 HEAD)"
          else
            echo "Comparing with last release: $LAST_TAG"
            COMPARE_REF="$LAST_TAG"
          fi
          
          # Get current plugin versions
          python scripts/extract_plugin_versions.py --json --output current_versions.json
          
          # Get previous plugin versions by checking out old plugins
          if git worktree add /tmp/old_repo ${COMPARE_REF} 2>/dev/null; then
            if [ -d /tmp/old_repo/plugins ]; then
              python scripts/extract_plugin_versions.py --plugins-dir /tmp/old_repo/plugins --json --output old_versions.json
            else
              echo "[]" > old_versions.json
            fi
            git worktree remove /tmp/old_repo 2>/dev/null || true
          else
            echo "Failed to create worktree, using empty version list"
            echo "[]" > old_versions.json
          fi
          
          # Compare versions and generate release notes
          python scripts/extract_plugin_versions.py --compare old_versions.json --ignore-removed --output changes.md
          python scripts/extract_plugin_versions.py --compare old_versions.json --json --output changes.json
          
          echo "=== Version Changes ==="
          cat changes.md
          
          # Check if there are any changes
          if grep -q "No changes detected" changes.md; then
            echo "has_changes=false" >> $GITHUB_OUTPUT
            echo "changed_plugins=" >> $GITHUB_OUTPUT
          else
            echo "has_changes=true" >> $GITHUB_OUTPUT
            
            # Extract changed plugin file paths using Python
            python3 -c "
          import json
          with open('changes.json', 'r') as f:
              data = json.load(f)
          files = []
          for plugin in data.get('added', []):
              if 'file_path' in plugin:
                  files.append(plugin['file_path'])
          for update in data.get('updated', []):
              if 'current' in update and 'file_path' in update['current']:
                  files.append(update['current']['file_path'])
          print('\n'.join(files))
          " > changed_files.txt
            
            echo "changed_plugins<<EOF" >> $GITHUB_OUTPUT
            cat changed_files.txt >> $GITHUB_OUTPUT
            echo "" >> $GITHUB_OUTPUT
            echo "EOF" >> $GITHUB_OUTPUT
          fi
          
          # Store release notes
          {
            echo 'release_notes<<EOF'
            cat changes.md
            echo ""
            echo 'EOF'
          } >> $GITHUB_OUTPUT

  release:
    needs: check-changes
    if: needs.check-changes.outputs.has_changes == 'true' || github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    env:
      LANG: en_US.UTF-8
      LC_ALL: en_US.UTF-8

    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Configure Git
        run: |
          git config --global core.quotepath false
          git config --global i18n.commitencoding utf-8
          git config --global i18n.logoutputencoding utf-8

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Determine version
        id: version
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ github.event.inputs.version }}" ]; then
            VERSION="${{ github.event.inputs.version }}"
          elif [[ "${{ github.ref }}" == refs/tags/v* ]]; then
            VERSION="${GITHUB_REF#refs/tags/}"
          else
            # Auto-generate version based on date and daily release count
            TODAY=$(date +'%Y.%m.%d')
            TODAY_PREFIX="v${TODAY}-"
            
            # Count existing releases with today's date prefix
            # grep -c returns 1 if count is 0, so we use || true to avoid script failure
            EXISTING_COUNT=$(gh release list --limit 100 2>/dev/null | grep -c "^${TODAY_PREFIX}" || true)
            
            # Clean up output (handle potential newlines or fallback issues)
            EXISTING_COUNT=$(echo "$EXISTING_COUNT" | tr -cd '0-9')
            if [ -z "$EXISTING_COUNT" ]; then EXISTING_COUNT=0; fi
            
            NEXT_NUM=$((EXISTING_COUNT + 1))
            
            VERSION="${TODAY_PREFIX}${NEXT_NUM}"
            
            # Final fallback to ensure VERSION is never empty
            if [ -z "$VERSION" ]; then
              VERSION="v$(date +'%Y.%m.%d-%H%M%S')"
            fi
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Release version: $VERSION"

      - name: Extract plugin versions
        id: plugins
        run: |
          python scripts/extract_plugin_versions.py --json --output plugin_versions.json
          python scripts/extract_plugin_versions.py --json --output plugin_versions.json

      - name: Collect plugin files for release
        id: collect_files
        run: |
          mkdir -p release_plugins
          
          CHANGED_PLUGINS="${{ needs.check-changes.outputs.changed_plugins }}"
          
          if [ -n "$CHANGED_PLUGINS" ]; then
            echo "Collecting changed plugin files..."
            echo "$CHANGED_PLUGINS" | while read -r file; do
              if [ -n "$file" ] && [ -f "$file" ]; then
                dir=$(dirname "$file")
                mkdir -p "release_plugins/$dir"
                cp "$file" "release_plugins/$file"
                echo "Added: $file"
              fi
            done
          else
            echo "No changed plugins detected. Skipping file collection."
          fi
          
          # Create a zip file with error handling
          # cd release_plugins
          # Zip step removed as per user request
          
          echo "=== Collected Files ==="
          find release_plugins -name "*.py" -type f | head -20

      - name: Update plugin icon URLs
        run: |
          echo "Updating icon_url in plugins to use absolute GitHub URLs..."
          # Base URL for raw content using the release tag
          REPO_URL="https://raw.githubusercontent.com/${{ github.repository }}/${{ steps.version.outputs.version }}"
          
          find release_plugins -name "*.py" | while read -r file; do
            # $file is like release_plugins/plugins/actions/infographic/infographic.py
            # Remove release_plugins/ prefix to get the path in the repo
            src_file="${file#release_plugins/}"
            src_dir=$(dirname "$src_file")
            base_name=$(basename "$src_file" .py)
            
            # Check if a corresponding png exists in the source repository
            png_file="${src_dir}/${base_name}.png"
            
            if [ -f "$png_file" ]; then
              echo "Found icon for $src_file: $png_file"
              TARGET_ICON_URL="${REPO_URL}/${png_file}"
              
              # Use python for safe replacement
              python3 -c "
          import sys
          import re
          
          file_path = '$file'
          icon_url = '$TARGET_ICON_URL'
          
          try:
              with open(file_path, 'r', encoding='utf-8') as f:
                  content = f.read()
              
              # Replace icon_url: ... with new url
              # Matches 'icon_url: ...' and replaces it
              new_content = re.sub(r'^icon_url:.*$', f'icon_url: {icon_url}', content, flags=re.MULTILINE)
              
              with open(file_path, 'w', encoding='utf-8') as f:
                  f.write(new_content)
              print(f'Successfully updated icon_url in {file_path}')
          except Exception as e:
              print(f'Error updating {file_path}: {e}', file=sys.stderr)
              sys.exit(1)
          "
            fi
          done

      - name: Debug Filenames
        run: |
          python3 -c "import sys; print(f'Filesystem encoding: {sys.getfilesystemencoding()}')"
          ls -R release_plugins

      - name: Upload Debug Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: debug-plugins
          path: release_plugins/

      - name: Get commit messages
        id: commits
        if: github.event_name == 'push'
        run: |
          LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
          
          if [ -n "$LAST_TAG" ]; then
            COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s" --no-merges -- plugins/ | head -20)
          else
            COMMITS=$(git log --pretty=format:"- %s" --no-merges -10 -- plugins/)
          fi
          
          {
            echo 'commits<<EOF'
            echo "$COMMITS"
            echo ""
            echo 'EOF'
          } >> "$GITHUB_OUTPUT"

      - name: Generate release notes
        id: notes
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          TITLE="${{ github.event.inputs.release_title }}"
          NOTES="${{ github.event.inputs.release_notes }}"
          DETECTED_CHANGES="${{ needs.check-changes.outputs.release_notes }}"
          COMMITS="${{ steps.commits.outputs.commits }}"
          
          echo "# ${VERSION} Release / 发布" > release_notes.md
          echo "" >> release_notes.md
          
          if [ -n "$TITLE" ]; then
            echo "## $TITLE" >> release_notes.md
            echo "" >> release_notes.md
          fi
          
          if [ -n "$DETECTED_CHANGES" ] && ! echo "$DETECTED_CHANGES" | grep -q "No changes detected"; then
            echo "## What's Changed / 更新内容" >> release_notes.md
            echo "" >> release_notes.md
            echo "$DETECTED_CHANGES" >> release_notes.md
            echo "" >> release_notes.md
          fi
          
          if [ -n "$COMMITS" ]; then
            echo "## Commits / 提交记录" >> release_notes.md
            echo "" >> release_notes.md
            echo "$COMMITS" >> release_notes.md
            echo "" >> release_notes.md
          fi
          
          if [ -n "$NOTES" ]; then
            echo "## Additional Notes / 附加说明" >> release_notes.md
            echo "" >> release_notes.md
            echo "$NOTES" >> release_notes.md
            echo "" >> release_notes.md
          fi
          

          
          cat >> release_notes.md << 'EOF'
          
          ## Download / 下载
          
          📦 **Download the updated plugin files below** / 请在下方下载更新的插件文件
          
          ### Installation / 安装
          
          #### From OpenWebUI Community
          1. Open OpenWebUI Admin Panel
          2. Navigate to Functions/Tools
          3. Search for the plugin name
          4. Click Install
          
          #### Manual Installation / 手动安装
          1. Download the plugin file (`.py`) from the assets below
          2. Open OpenWebUI Admin Panel → Functions
          3. Click "Create Function" → Import
          4. Paste the plugin code
          
          ---
          
          📚 [Documentation / 文档](https://fu-jie.github.io/awesome-openwebui/)
          🐛 [Report Issues / 报告问题](https://github.com/Fu-Jie/awesome-openwebui/issues)
          EOF
          
          echo "=== Release Notes ==="
          cat release_notes.md

      - name: Create Git Tag
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          
          if [ -z "$VERSION" ]; then
            echo "Error: Version is empty!"
            exit 1
          fi
          
          if ! git rev-parse "$VERSION" >/dev/null 2>&1; then
            echo "Creating tag $VERSION"
            git tag "$VERSION"
            git push origin "$VERSION"
          else
            echo "Tag $VERSION already exists"
          fi
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ steps.version.outputs.version }}
          target_commitish: ${{ github.sha }}
          name: ${{ github.event.inputs.release_title || steps.version.outputs.version }}
          body_path: release_notes.md
          prerelease: ${{ github.event.inputs.prerelease || false }}
          make_latest: true
          files: |
            plugin_versions.json
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Upload Release Assets
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Check if there are any .py files to upload
          if [ -d release_plugins ] && [ -n "$(find release_plugins -type f -name '*.py' 2>/dev/null)" ]; then
            echo "Uploading plugin files..."
            find release_plugins -type f -name "*.py" -print0 | xargs -0 gh release upload ${{ steps.version.outputs.version }} --clobber
          else
            echo "No plugin files to upload. Skipping asset upload."
          fi

      - name: Summary
        run: |
          echo "## 🚀 Release Created Successfully!" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Version:** ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "### Updated Plugins" >> $GITHUB_STEP_SUMMARY
          echo "${{ needs.check-changes.outputs.release_notes }}" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY

