Reset to Upstream and Merge PRs #385
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Reset to Upstream and Merge PRs | |
| on: | |
| schedule: | |
| - cron: '0 8 * * *' # Runs at midnight EST sunday | |
| workflow_dispatch: | |
| inputs: | |
| pr_numbers: | |
| description: 'Comma-separated list of PR numbers to merge' | |
| required: false | |
| default: '' | |
| auto_resolve_conflicts: | |
| description: 'Auto-resolve conflicts in favor of our version (HEAD)' | |
| required: false | |
| type: boolean | |
| default: true | |
| conflict_resolution_strategy: | |
| description: 'How to resolve conflicts: auto-head (our version), auto-pr (PR version), or skip (skip conflicted PRs)' | |
| required: false | |
| type: choice | |
| options: | |
| - auto-head | |
| - auto-pr | |
| - skip | |
| default: 'auto-head' | |
| pr_specific_strategies: | |
| description: 'Per-PR conflict strategies (format: "5011:auto-pr,7077:auto-head") - overrides global strategy' | |
| required: false | |
| default: '' | |
| permissions: | |
| contents: write | |
| pull-requests: read | |
| env: | |
| # PR list is stored in .github/pr-list.txt (one number per line) | |
| # The workflow reads from and auto-updates that file - no need to edit here | |
| # | |
| # Token for authentication | |
| GH_TOKEN: ${{ secrets.PAT_TOKEN || github.token }} | |
| jobs: | |
| reset-and-merge: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ env.GH_TOKEN }} | |
| persist-credentials: true | |
| - name: Verify authentication | |
| run: | | |
| # Check if PAT_TOKEN is available | |
| if [ -n "${{ secrets.PAT_TOKEN }}" ]; then | |
| echo "✅ PAT_TOKEN is configured" | |
| else | |
| echo "✅ Using default GITHUB_TOKEN" | |
| echo "Note: For workflow self-updating, set up PAT_TOKEN secret" | |
| fi | |
| - name: Configure Git | |
| run: | | |
| git config --global user.name "GitHub Action" | |
| git config --global user.email "action@github.com" | |
| # Set merge strategy to avoid merge commit messages prompts | |
| git config pull.rebase false | |
| - name: Generate patches from custom modifications | |
| run: | | |
| echo "=== Generating Patches from Custom Modifications ===" | |
| # Make the script executable | |
| if [ -f ".github/scripts/generate-patches.sh" ]; then | |
| chmod +x .github/scripts/generate-patches.sh | |
| .github/scripts/generate-patches.sh | |
| else | |
| echo "⚠️ Patch generation script not found, skipping automatic patch generation" | |
| fi | |
| echo "Current patches in .github/patches:" | |
| ls -lh .github/patches/ || echo "No patches directory found" | |
| - name: Backup workflow files | |
| run: | | |
| # Backup workflows | |
| mkdir -p /tmp/workflows-backup | |
| if [ -d ".github/workflows" ]; then | |
| cp ".github/workflows/Reset to Upstream and Merge PRs.yml" "/tmp/workflows-backup/Reset to Upstream and Merge PRs.yml" || true | |
| # Backup any other custom workflow files | |
| cp ".github/workflows/Build and Release.yml" "/tmp/workflows-backup/Build and Release.yml" || true | |
| fi | |
| # Backup PR list file | |
| if [ -f ".github/pr-list.txt" ]; then | |
| cp ".github/pr-list.txt" "/tmp/pr-list.txt" || true | |
| fi | |
| # Backup patch definitions file | |
| if [ -f ".github/patch-definitions.txt" ]; then | |
| cp ".github/patch-definitions.txt" "/tmp/patch-definitions.txt" || true | |
| fi | |
| # Backup patch generation script | |
| mkdir -p /tmp/scripts-backup | |
| if [ -f ".github/scripts/generate-patches.sh" ]; then | |
| cp ".github/scripts/generate-patches.sh" "/tmp/scripts-backup/generate-patches.sh" || true | |
| fi | |
| # Backup custom patches directory | |
| mkdir -p /tmp/patches-backup | |
| if [ -d ".github/patches" ]; then | |
| cp -r .github/patches/* /tmp/patches-backup/ || true | |
| fi | |
| - name: Add upstream remote | |
| run: | | |
| # Add upstream without authentication (public repo) | |
| git remote add upstream https://github.com/jellyfin/jellyfin-web.git || \ | |
| git remote set-url upstream https://github.com/jellyfin/jellyfin-web.git | |
| # Fix origin URL to include authentication token | |
| git remote set-url origin https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git | |
| - name: Fetch all remotes | |
| run: | | |
| echo "Current remotes:" | |
| git remote -v | |
| echo "Fetching from origin..." | |
| git fetch origin | |
| echo "Fetching from upstream..." | |
| git fetch upstream --prune | |
| echo "Fetched latest changes from all remotes" | |
| - name: Reset to upstream | |
| id: reset_upstream | |
| run: | | |
| echo "Current branch: $(git branch --show-current)" | |
| echo "Current commit: $(git rev-parse HEAD)" | |
| # Reset to upstream/master and clean up workflow files | |
| git checkout master | |
| git reset --hard upstream/master | |
| # Remove all upstream workflow files | |
| if [ -d ".github/workflows" ]; then | |
| git rm -rf .github/workflows || true | |
| git commit -m "Remove all upstream workflow files" || true | |
| fi | |
| echo "Successfully reset to upstream" | |
| echo "reset_success=true" >> $GITHUB_OUTPUT | |
| - name: Restore workflow files | |
| run: | | |
| # Restore workflow files | |
| mkdir -p .github/workflows | |
| if [ -f "/tmp/workflows-backup/Reset to Upstream and Merge PRs.yml" ]; then | |
| cp "/tmp/workflows-backup/Reset to Upstream and Merge PRs.yml" ".github/workflows/" | |
| git add ".github/workflows/Reset to Upstream and Merge PRs.yml" | |
| fi | |
| if [ -f "/tmp/workflows-backup/Build and Release.yml" ]; then | |
| cp "/tmp/workflows-backup/Build and Release.yml" ".github/workflows/" | |
| git add ".github/workflows/Build and Release.yml" | |
| fi | |
| # Restore PR list file | |
| if [ -f "/tmp/pr-list.txt" ]; then | |
| cp "/tmp/pr-list.txt" ".github/pr-list.txt" | |
| git add ".github/pr-list.txt" | |
| fi | |
| # Restore patch-related files | |
| if [ -f "/tmp/patch-definitions.txt" ]; then | |
| cp "/tmp/patch-definitions.txt" ".github/patch-definitions.txt" | |
| git add ".github/patch-definitions.txt" | |
| fi | |
| mkdir -p .github/scripts | |
| if [ -f "/tmp/scripts-backup/generate-patches.sh" ]; then | |
| cp "/tmp/scripts-backup/generate-patches.sh" ".github/scripts/generate-patches.sh" | |
| git add ".github/scripts/generate-patches.sh" | |
| fi | |
| # Restore the patches directory so it persists | |
| mkdir -p .github/patches | |
| if [ -d "/tmp/patches-backup" ]; then | |
| cp -r /tmp/patches-backup/* .github/patches/ || true | |
| git add .github/patches/ | |
| fi | |
| # Commit restored files if there are changes | |
| if ! git diff --cached --quiet; then | |
| git commit -m "Restore our workflow files and custom patches after reset" | |
| fi | |
| - name: Check PR status (merged, closed, or open) | |
| if: steps.reset_upstream.outputs.reset_success == 'true' | |
| id: check_pr_status | |
| run: | | |
| # Use the input PR numbers if provided, otherwise read from .github/pr-list.txt | |
| PR_NUMBERS="${{ github.event.inputs.pr_numbers }}" | |
| if [ -z "$PR_NUMBERS" ]; then | |
| if [ -f ".github/pr-list.txt" ]; then | |
| PR_NUMBERS=$(grep -v '^#' .github/pr-list.txt | grep -v '^$' | tr '\n' ',' | sed 's/,$//') | |
| fi | |
| fi | |
| if [ -z "$PR_NUMBERS" ]; then | |
| echo "No PRs to process" | |
| echo "merged_upstream_prs=" >> $GITHUB_OUTPUT | |
| echo "closed_prs=" >> $GITHUB_OUTPUT | |
| echo "draft_prs=" >> $GITHUB_OUTPUT | |
| echo "stable_backport_prs=" >> $GITHUB_OUTPUT | |
| echo "unmerged_prs=" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| IFS=',' read -ra PR_ARRAY <<< "$PR_NUMBERS" | |
| echo "## PR Status Check" > pr_status.txt | |
| echo "" >> pr_status.txt | |
| MERGED_UPSTREAM_PRS="" | |
| CLOSED_PRS="" | |
| DRAFT_PRS="" | |
| STABLE_BACKPORT_PRS="" | |
| UNMERGED_PRS="" | |
| for PR_NUMBER in "${PR_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo $PR_NUMBER | xargs) # Trim whitespace | |
| # Check if PR is already merged upstream | |
| if git log upstream/master --grep="Merge pull request #$PR_NUMBER" --oneline | grep -q "$PR_NUMBER"; then | |
| echo "✅ PR $PR_NUMBER is already merged upstream" >> pr_status.txt | |
| if [ -z "$MERGED_UPSTREAM_PRS" ]; then | |
| MERGED_UPSTREAM_PRS="$PR_NUMBER" | |
| else | |
| MERGED_UPSTREAM_PRS="$MERGED_UPSTREAM_PRS,$PR_NUMBER" | |
| fi | |
| else | |
| # Check if PR is closed (but not merged) using GitHub CLI | |
| echo "Checking PR $PR_NUMBER status via GitHub API..." | |
| # Use GitHub CLI to check PR status, draft status, and labels | |
| PR_DATA=$(gh pr view $PR_NUMBER --repo jellyfin/jellyfin-web --json state,merged,isDraft,labels -q '.state + ":" + (.merged|tostring) + ":" + (.isDraft|tostring) + ":" + ([.labels[].name] | join(","))' 2>/dev/null || echo "UNKNOWN:false:false:") | |
| STATE=$(echo "$PR_DATA" | cut -d':' -f1) | |
| IS_MERGED=$(echo "$PR_DATA" | cut -d':' -f2) | |
| IS_DRAFT=$(echo "$PR_DATA" | cut -d':' -f3) | |
| LABELS=$(echo "$PR_DATA" | cut -d':' -f4-) | |
| if [ "$STATE" = "CLOSED" ] && [ "$IS_MERGED" = "false" ]; then | |
| echo "❌ PR $PR_NUMBER is closed (not merged)" >> pr_status.txt | |
| if [ -z "$CLOSED_PRS" ]; then | |
| CLOSED_PRS="$PR_NUMBER" | |
| else | |
| CLOSED_PRS="$CLOSED_PRS,$PR_NUMBER" | |
| fi | |
| elif [ "$IS_DRAFT" = "true" ]; then | |
| echo "📝 PR $PR_NUMBER is a draft" >> pr_status.txt | |
| if [ -z "$DRAFT_PRS" ]; then | |
| DRAFT_PRS="$PR_NUMBER" | |
| else | |
| DRAFT_PRS="$DRAFT_PRS,$PR_NUMBER" | |
| fi | |
| elif echo "$LABELS" | grep -qi "stable backport"; then | |
| echo "🏷️ PR $PR_NUMBER is tagged with 'stable backport'" >> pr_status.txt | |
| if [ -z "$STABLE_BACKPORT_PRS" ]; then | |
| STABLE_BACKPORT_PRS="$PR_NUMBER" | |
| else | |
| STABLE_BACKPORT_PRS="$STABLE_BACKPORT_PRS,$PR_NUMBER" | |
| fi | |
| elif [ "$STATE" = "OPEN" ] || [ "$STATE" = "UNKNOWN" ]; then | |
| echo "⭕ PR $PR_NUMBER needs to be merged" >> pr_status.txt | |
| echo "$PR_NUMBER" >> prs_to_merge.txt | |
| if [ -z "$UNMERGED_PRS" ]; then | |
| UNMERGED_PRS="$PR_NUMBER" | |
| else | |
| UNMERGED_PRS="$UNMERGED_PRS,$PR_NUMBER" | |
| fi | |
| fi | |
| fi | |
| done | |
| echo "PR Status:" | |
| cat pr_status.txt || true | |
| # Set outputs for README update | |
| echo "merged_upstream_prs=$MERGED_UPSTREAM_PRS" >> $GITHUB_OUTPUT | |
| echo "closed_prs=$CLOSED_PRS" >> $GITHUB_OUTPUT | |
| echo "draft_prs=$DRAFT_PRS" >> $GITHUB_OUTPUT | |
| echo "stable_backport_prs=$STABLE_BACKPORT_PRS" >> $GITHUB_OUTPUT | |
| echo "unmerged_prs=$UNMERGED_PRS" >> $GITHUB_OUTPUT | |
| - name: Merge PRs | |
| if: steps.reset_upstream.outputs.reset_success == 'true' | |
| id: merge_prs | |
| run: | | |
| if [ ! -f "prs_to_merge.txt" ]; then | |
| echo "All PRs are either merged upstream or closed!" | |
| echo "newly_merged_prs=" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "## Merge Results" > merge_results.txt | |
| echo "" >> merge_results.txt | |
| NEWLY_MERGED_PRS="" | |
| # Parse per-PR strategies if provided | |
| declare -A PR_STRATEGIES | |
| if [ -n "${{ github.event.inputs.pr_specific_strategies }}" ]; then | |
| echo "Parsing per-PR conflict strategies..." | |
| IFS=',' read -ra STRATEGY_PAIRS <<< "${{ github.event.inputs.pr_specific_strategies }}" | |
| for pair in "${STRATEGY_PAIRS[@]}"; do | |
| if [[ $pair == *":"* ]]; then | |
| PR=$(echo "$pair" | cut -d':' -f1 | xargs) | |
| STRATEGY=$(echo "$pair" | cut -d':' -f2 | xargs) | |
| PR_STRATEGIES[$PR]=$STRATEGY | |
| echo " PR $PR: $STRATEGY" | |
| fi | |
| done | |
| fi | |
| while IFS= read -r PR_NUMBER; do | |
| echo "Processing PR $PR_NUMBER" | |
| # Fetch the PR branch | |
| if git fetch upstream pull/$PR_NUMBER/head:pr-$PR_NUMBER; then | |
| echo "Fetched PR $PR_NUMBER successfully" | |
| # Check if this PR can be merged cleanly | |
| MERGE_BASE=$(git merge-base HEAD pr-$PR_NUMBER) | |
| if git merge-tree $MERGE_BASE HEAD pr-$PR_NUMBER | grep -q '^<<<<<<<'; then | |
| # Determine conflict resolution strategy for this PR | |
| STRATEGY="${PR_STRATEGIES[$PR_NUMBER]:-${{ github.event.inputs.conflict_resolution_strategy || 'auto-head' }}}" | |
| echo "⚠️ PR $PR_NUMBER has conflicts - using strategy: $STRATEGY" >> merge_results.txt | |
| case $STRATEGY in | |
| "auto-head") | |
| echo "Attempting merge with auto-resolution (favoring HEAD/our version)..." | |
| if git merge pr-$PR_NUMBER --no-ff -m "Merge upstream changes from PR-$PR_NUMBER"; then | |
| echo "✅ Merged PR $PR_NUMBER successfully (auto-resolved conflicts)" >> merge_results.txt | |
| if [ -z "$NEWLY_MERGED_PRS" ]; then | |
| NEWLY_MERGED_PRS="$PR_NUMBER" | |
| else | |
| NEWLY_MERGED_PRS="$NEWLY_MERGED_PRS,$PR_NUMBER" | |
| fi | |
| git branch -D pr-$PR_NUMBER | |
| else | |
| # Merge failed, try manual conflict resolution | |
| echo "Auto-merge failed, resolving conflicts manually (HEAD wins)..." | |
| git checkout --ours . | |
| git add . | |
| git commit -m "Merge upstream changes from PR-$PR_NUMBER (resolved conflicts favoring HEAD)" | |
| echo "✅ Merged PR $PR_NUMBER with manual conflict resolution (HEAD wins)" >> merge_results.txt | |
| if [ -z "$NEWLY_MERGED_PRS" ]; then | |
| NEWLY_MERGED_PRS="$PR_NUMBER" | |
| else | |
| NEWLY_MERGED_PRS="$NEWLY_MERGED_PRS,$PR_NUMBER" | |
| fi | |
| git branch -D pr-$PR_NUMBER | |
| fi | |
| ;; | |
| "auto-pr") | |
| echo "Attempting merge with auto-resolution (favoring PR version)..." | |
| if git merge pr-$PR_NUMBER --no-ff -m "Merge upstream changes from PR-$PR_NUMBER (auto-resolved conflicts favoring PR)"; then | |
| echo "✅ Merged PR $PR_NUMBER successfully (auto-resolved conflicts)" >> merge_results.txt | |
| if [ -z "$NEWLY_MERGED_PRS" ]; then | |
| NEWLY_MERGED_PRS="$PR_NUMBER" | |
| else | |
| NEWLY_MERGED_PRS="$NEWLY_MERGED_PRS,$PR_NUMBER" | |
| fi | |
| git branch -D pr-$PR_NUMBER | |
| else | |
| # Merge failed, try manual conflict resolution | |
| echo "Auto-merge failed, resolving conflicts manually (PR wins)..." | |
| git checkout --theirs . | |
| git add . | |
| git commit -m "Merge upstream changes from PR-$PR_NUMBER (resolved conflicts favoring PR)" | |
| echo "✅ Merged PR $PR_NUMBER with manual conflict resolution (PR wins)" >> merge_results.txt | |
| if [ -z "$NEWLY_MERGED_PRS" ]; then | |
| NEWLY_MERGED_PRS="$PR_NUMBER" | |
| else | |
| NEWLY_MERGED_PRS="$NEWLY_MERGED_PRS,$PR_NUMBER" | |
| fi | |
| git branch -D pr-$PR_NUMBER | |
| fi | |
| ;; | |
| "skip") | |
| echo "⏭️ Skipping PR $PR_NUMBER due to conflicts (strategy: skip)" >> merge_results.txt | |
| git branch -D pr-$PR_NUMBER || true | |
| ;; | |
| *) | |
| echo "❌ Unknown conflict resolution strategy: $STRATEGY for PR $PR_NUMBER" >> merge_results.txt | |
| git branch -D pr-$PR_NUMBER || true | |
| ;; | |
| esac | |
| else | |
| # No conflicts, merge normally | |
| if git merge pr-$PR_NUMBER --no-ff -m "Merge upstream changes from PR-$PR_NUMBER"; then | |
| echo "✅ Merged PR $PR_NUMBER successfully" >> merge_results.txt | |
| if [ -z "$NEWLY_MERGED_PRS" ]; then | |
| NEWLY_MERGED_PRS="$PR_NUMBER" | |
| else | |
| NEWLY_MERGED_PRS="$NEWLY_MERGED_PRS,$PR_NUMBER" | |
| fi | |
| # Clean up the PR branch | |
| git branch -D pr-$PR_NUMBER | |
| else | |
| echo "❌ Failed to merge PR $PR_NUMBER (unexpected error)" >> merge_results.txt | |
| git merge --abort | |
| git branch -D pr-$PR_NUMBER || true | |
| fi | |
| fi | |
| else | |
| echo "❌ Failed to fetch PR $PR_NUMBER (PR may not exist or is closed)" >> merge_results.txt | |
| fi | |
| done < prs_to_merge.txt | |
| echo "" | |
| echo "Merge Summary:" | |
| cat merge_results.txt | |
| # Set output for README update | |
| echo "newly_merged_prs=$NEWLY_MERGED_PRS" >> $GITHUB_OUTPUT | |
| - name: Update README with current PR list | |
| if: steps.reset_upstream.outputs.reset_success == 'true' | |
| run: | | |
| # Get PR status information | |
| MERGED_UPSTREAM_PRS="${{ steps.check_pr_status.outputs.merged_upstream_prs }}" | |
| CLOSED_PRS="${{ steps.check_pr_status.outputs.closed_prs }}" | |
| DRAFT_PRS="${{ steps.check_pr_status.outputs.draft_prs }}" | |
| STABLE_BACKPORT_PRS="${{ steps.check_pr_status.outputs.stable_backport_prs }}" | |
| UNMERGED_PRS="${{ steps.check_pr_status.outputs.unmerged_prs }}" | |
| NEWLY_MERGED_PRS="${{ steps.merge_prs.outputs.newly_merged_prs }}" | |
| echo "Updating README with current PR status..." | |
| echo "Merged upstream: $MERGED_UPSTREAM_PRS" | |
| echo "Closed without merge: $CLOSED_PRS" | |
| echo "Draft PRs: $DRAFT_PRS" | |
| echo "Stable backport PRs: $STABLE_BACKPORT_PRS" | |
| echo "Still unmerged: $UNMERGED_PRS" | |
| echo "Newly merged: $NEWLY_MERGED_PRS" | |
| # Load or create timestamp files | |
| MERGED_PRS_FILE=".github/merged_prs_timestamps.json" | |
| CLOSED_PRS_FILE=".github/closed_prs_timestamps.json" | |
| DRAFT_PRS_FILE=".github/draft_prs_timestamps.json" | |
| STABLE_BACKPORT_PRS_FILE=".github/stable_backport_prs_timestamps.json" | |
| # Initialize files if they don't exist | |
| [ ! -f "$MERGED_PRS_FILE" ] && echo "{}" > "$MERGED_PRS_FILE" | |
| [ ! -f "$CLOSED_PRS_FILE" ] && echo "{}" > "$CLOSED_PRS_FILE" | |
| [ ! -f "$DRAFT_PRS_FILE" ] && echo "{}" > "$DRAFT_PRS_FILE" | |
| [ ! -f "$STABLE_BACKPORT_PRS_FILE" ] && echo "{}" > "$STABLE_BACKPORT_PRS_FILE" | |
| # Add current timestamp for newly merged/closed PRs | |
| CURRENT_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") | |
| # Record merged PRs | |
| if [ -n "$MERGED_UPSTREAM_PRS" ]; then | |
| echo "Recording merge timestamps for upstream PRs: $MERGED_UPSTREAM_PRS" | |
| IFS=',' read -ra MERGED_ARRAY <<< "$MERGED_UPSTREAM_PRS" | |
| for PR_NUMBER in "${MERGED_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| cat "$MERGED_PRS_FILE" | jq --arg pr "$PR_NUMBER" --arg ts "$CURRENT_TIMESTAMP" '. + {($pr): $ts}' > "${MERGED_PRS_FILE}.tmp" | |
| mv "${MERGED_PRS_FILE}.tmp" "$MERGED_PRS_FILE" | |
| done | |
| fi | |
| # Record closed PRs | |
| if [ -n "$CLOSED_PRS" ]; then | |
| echo "Recording close timestamps for closed PRs: $CLOSED_PRS" | |
| IFS=',' read -ra CLOSED_ARRAY <<< "$CLOSED_PRS" | |
| for PR_NUMBER in "${CLOSED_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| cat "$CLOSED_PRS_FILE" | jq --arg pr "$PR_NUMBER" --arg ts "$CURRENT_TIMESTAMP" '. + {($pr): $ts}' > "${CLOSED_PRS_FILE}.tmp" | |
| mv "${CLOSED_PRS_FILE}.tmp" "$CLOSED_PRS_FILE" | |
| done | |
| fi | |
| # Record draft PRs | |
| if [ -n "$DRAFT_PRS" ]; then | |
| echo "Recording draft timestamps for draft PRs: $DRAFT_PRS" | |
| IFS=',' read -ra DRAFT_ARRAY <<< "$DRAFT_PRS" | |
| for PR_NUMBER in "${DRAFT_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| cat "$DRAFT_PRS_FILE" | jq --arg pr "$PR_NUMBER" --arg ts "$CURRENT_TIMESTAMP" '. + {($pr): $ts}' > "${DRAFT_PRS_FILE}.tmp" | |
| mv "${DRAFT_PRS_FILE}.tmp" "$DRAFT_PRS_FILE" | |
| done | |
| fi | |
| # Record stable backport PRs | |
| if [ -n "$STABLE_BACKPORT_PRS" ]; then | |
| echo "Recording stable backport timestamps for stable backport PRs: $STABLE_BACKPORT_PRS" | |
| IFS=',' read -ra STABLE_BACKPORT_ARRAY <<< "$STABLE_BACKPORT_PRS" | |
| for PR_NUMBER in "${STABLE_BACKPORT_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| cat "$STABLE_BACKPORT_PRS_FILE" | jq --arg pr "$PR_NUMBER" --arg ts "$CURRENT_TIMESTAMP" '. + {($pr): $ts}' > "${STABLE_BACKPORT_PRS_FILE}.tmp" | |
| mv "${STABLE_BACKPORT_PRS_FILE}.tmp" "$STABLE_BACKPORT_PRS_FILE" | |
| done | |
| fi | |
| # Filter to show recent changes (last 7 days) | |
| SEVEN_DAYS_AGO=$(date -u -d '7 days ago' +"%Y-%m-%dT%H:%M:%SZ") | |
| # Get recently merged PRs | |
| RECENT_MERGED_PRS="" | |
| if [ -f "$MERGED_PRS_FILE" ]; then | |
| RECENT_PRS=$(cat "$MERGED_PRS_FILE" | jq -r --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | map(.key) | join(",")') | |
| [ "$RECENT_PRS" != "" ] && [ "$RECENT_PRS" != "null" ] && RECENT_MERGED_PRS="$RECENT_PRS" | |
| # Clean up old entries | |
| cat "$MERGED_PRS_FILE" | jq --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | from_entries' > "${MERGED_PRS_FILE}.tmp" | |
| mv "${MERGED_PRS_FILE}.tmp" "$MERGED_PRS_FILE" | |
| fi | |
| # Get recently closed PRs | |
| RECENT_CLOSED_PRS="" | |
| if [ -f "$CLOSED_PRS_FILE" ]; then | |
| RECENT_PRS=$(cat "$CLOSED_PRS_FILE" | jq -r --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | map(.key) | join(",")') | |
| [ "$RECENT_PRS" != "" ] && [ "$RECENT_PRS" != "null" ] && RECENT_CLOSED_PRS="$RECENT_PRS" | |
| # Clean up old entries | |
| cat "$CLOSED_PRS_FILE" | jq --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | from_entries' > "${CLOSED_PRS_FILE}.tmp" | |
| mv "${CLOSED_PRS_FILE}.tmp" "$CLOSED_PRS_FILE" | |
| fi | |
| # Get recently draft PRs | |
| RECENT_DRAFT_PRS="" | |
| if [ -f "$DRAFT_PRS_FILE" ]; then | |
| RECENT_PRS=$(cat "$DRAFT_PRS_FILE" | jq -r --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | map(.key) | join(",")') | |
| [ "$RECENT_PRS" != "" ] && [ "$RECENT_PRS" != "null" ] && RECENT_DRAFT_PRS="$RECENT_PRS" | |
| # Clean up old entries | |
| cat "$DRAFT_PRS_FILE" | jq --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | from_entries' > "${DRAFT_PRS_FILE}.tmp" | |
| mv "${DRAFT_PRS_FILE}.tmp" "$DRAFT_PRS_FILE" | |
| fi | |
| # Get recently stable backport PRs | |
| RECENT_STABLE_BACKPORT_PRS="" | |
| if [ -f "$STABLE_BACKPORT_PRS_FILE" ]; then | |
| RECENT_PRS=$(cat "$STABLE_BACKPORT_PRS_FILE" | jq -r --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | map(.key) | join(",")') | |
| [ "$RECENT_PRS" != "" ] && [ "$RECENT_PRS" != "null" ] && RECENT_STABLE_BACKPORT_PRS="$RECENT_PRS" | |
| # Clean up old entries | |
| cat "$STABLE_BACKPORT_PRS_FILE" | jq --arg cutoff "$SEVEN_DAYS_AGO" 'to_entries | map(select(.value > $cutoff)) | from_entries' > "${STABLE_BACKPORT_PRS_FILE}.tmp" | |
| mv "${STABLE_BACKPORT_PRS_FILE}.tmp" "$STABLE_BACKPORT_PRS_FILE" | |
| fi | |
| echo "Recent merged PRs (last 7 days): $RECENT_MERGED_PRS" | |
| echo "Recent closed PRs (last 7 days): $RECENT_CLOSED_PRS" | |
| echo "Recent draft PRs (last 7 days): $RECENT_DRAFT_PRS" | |
| echo "Recent stable backport PRs (last 7 days): $RECENT_STABLE_BACKPORT_PRS" | |
| # Create the PR section for README | |
| echo "## Currently Installed PRs" > /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| if [ -n "$UNMERGED_PRS" ]; then | |
| echo "The following PRs are automatically merged into this fork:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra PR_ARRAY <<< "$UNMERGED_PRS" | |
| for PR_NUMBER in "${PR_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| echo "- [Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)" >> /tmp/pr_section.md | |
| done | |
| # Add recently removed section | |
| if [ -n "$RECENT_MERGED_PRS" ] || [ -n "$RECENT_CLOSED_PRS" ] || [ -n "$RECENT_DRAFT_PRS" ] || [ -n "$RECENT_STABLE_BACKPORT_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "### Recently Removed PRs (Last 7 Days)" >> /tmp/pr_section.md | |
| fi | |
| if [ -n "$RECENT_MERGED_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### ✅ Merged Upstream" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they have been merged into upstream Jellyfin Web:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra MERGED_ARRAY <<< "$RECENT_MERGED_PRS" | |
| for PR_NUMBER in "${MERGED_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| MERGE_DATE=$(cat "$MERGED_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (merged on $MERGE_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| if [ -n "$RECENT_CLOSED_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### ❌ Closed Without Merging" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they were closed without being merged:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra CLOSED_ARRAY <<< "$RECENT_CLOSED_PRS" | |
| for PR_NUMBER in "${CLOSED_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| CLOSE_DATE=$(cat "$CLOSED_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (closed on $CLOSE_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| if [ -n "$RECENT_DRAFT_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### 📝 Moved to Draft" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they were moved to draft status:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra DRAFT_ARRAY <<< "$RECENT_DRAFT_PRS" | |
| for PR_NUMBER in "${DRAFT_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| DRAFT_DATE=$(cat "$DRAFT_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (became draft on $DRAFT_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| if [ -n "$RECENT_STABLE_BACKPORT_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### 🏷️ Tagged as Stable Backport" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they were tagged with 'stable backport':" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra STABLE_BACKPORT_ARRAY <<< "$RECENT_STABLE_BACKPORT_PRS" | |
| for PR_NUMBER in "${STABLE_BACKPORT_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| BACKPORT_DATE=$(cat "$STABLE_BACKPORT_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (tagged on $BACKPORT_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| else | |
| echo "🎉 All PRs have been merged upstream or closed! This fork is now clean and matches the upstream Jellyfin Web repository." >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| # Add recently removed section if there are any | |
| if [ -n "$RECENT_MERGED_PRS" ] || [ -n "$RECENT_CLOSED_PRS" ] || [ -n "$RECENT_DRAFT_PRS" ] || [ -n "$RECENT_STABLE_BACKPORT_PRS" ]; then | |
| echo "### Recently Removed PRs (Last 7 Days)" >> /tmp/pr_section.md | |
| fi | |
| if [ -n "$RECENT_MERGED_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### ✅ Merged Upstream" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they have been merged into upstream Jellyfin Web:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra MERGED_ARRAY <<< "$RECENT_MERGED_PRS" | |
| for PR_NUMBER in "${MERGED_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| MERGE_DATE=$(cat "$MERGED_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (merged on $MERGE_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| if [ -n "$RECENT_CLOSED_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### ❌ Closed Without Merging" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they were closed without being merged:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra CLOSED_ARRAY <<< "$RECENT_CLOSED_PRS" | |
| for PR_NUMBER in "${CLOSED_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| CLOSE_DATE=$(cat "$CLOSED_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (closed on $CLOSE_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| if [ -n "$RECENT_DRAFT_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### 📝 Moved to Draft" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they were moved to draft status:" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra DRAFT_ARRAY <<< "$RECENT_DRAFT_PRS" | |
| for PR_NUMBER in "${DRAFT_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| DRAFT_DATE=$(cat "$DRAFT_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (became draft on $DRAFT_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| if [ -n "$RECENT_STABLE_BACKPORT_PRS" ]; then | |
| echo "" >> /tmp/pr_section.md | |
| echo "#### 🏷️ Tagged as Stable Backport" >> /tmp/pr_section.md | |
| echo "The following PRs were automatically removed as they were tagged with 'stable backport':" >> /tmp/pr_section.md | |
| echo "" >> /tmp/pr_section.md | |
| IFS=',' read -ra STABLE_BACKPORT_ARRAY <<< "$RECENT_STABLE_BACKPORT_PRS" | |
| for PR_NUMBER in "${STABLE_BACKPORT_ARRAY[@]}"; do | |
| PR_NUMBER=$(echo "$PR_NUMBER" | xargs) | |
| BACKPORT_DATE=$(cat "$STABLE_BACKPORT_PRS_FILE" | jq -r --arg pr "$PR_NUMBER" '.[$pr] // empty' | cut -d'T' -f1) | |
| echo "- ~~[Upstream PR #$PR_NUMBER](https://github.com/jellyfin/jellyfin-web/pull/$PR_NUMBER)~~ (tagged on $BACKPORT_DATE)" >> /tmp/pr_section.md | |
| done | |
| fi | |
| fi | |
| echo "" >> /tmp/pr_section.md | |
| echo "---" >> /tmp/pr_section.md | |
| # Read the PR section content | |
| PR_SECTION=$(cat /tmp/pr_section.md) | |
| # Read the current README | |
| README_CONTENT=$(cat README.md) | |
| # Check if the PR section already exists | |
| if echo "$README_CONTENT" | grep -q "## Currently Installed PRs"; then | |
| # Replace existing section | |
| # Extract content before the PR section | |
| BEFORE_SECTION=$(echo "$README_CONTENT" | sed '/## Currently Installed PRs/,$d') | |
| # Extract content after the PR section (after the next ---) | |
| AFTER_SECTION=$(echo "$README_CONTENT" | sed -n '/## Currently Installed PRs/,/^---$/p' | sed '1,/^---$/d' | sed -n '/^---$/,$p' | tail -n +2) | |
| # If no --- found after PR section, take everything after the next ## | |
| if [ -z "$AFTER_SECTION" ]; then | |
| AFTER_SECTION=$(echo "$README_CONTENT" | sed -n '/## Currently Installed PRs/,$p' | sed -n '/^## /,$p' | tail -n +2) | |
| fi | |
| # Combine the sections | |
| echo "$BEFORE_SECTION" > README.md | |
| echo "$PR_SECTION" >> README.md | |
| echo "$AFTER_SECTION" >> README.md | |
| else | |
| # Add section after the main header | |
| # Extract the header section (first 3 lines) | |
| HEAD_SECTION=$(head -n 3 README.md) | |
| # Extract the rest | |
| REST_SECTION=$(tail -n +4 README.md) | |
| # Combine sections | |
| echo "$HEAD_SECTION" > README.md | |
| echo "" >> README.md | |
| echo "$PR_SECTION" >> README.md | |
| echo "$REST_SECTION" >> README.md | |
| fi | |
| # Create commit message | |
| COMMIT_MSG="Update README with current PR list" | |
| CHANGES="" | |
| [ -n "$RECENT_MERGED_PRS" ] && CHANGES="${CHANGES}merged: $RECENT_MERGED_PRS, " | |
| [ -n "$RECENT_CLOSED_PRS" ] && CHANGES="${CHANGES}closed: $RECENT_CLOSED_PRS, " | |
| [ -n "$RECENT_DRAFT_PRS" ] && CHANGES="${CHANGES}draft: $RECENT_DRAFT_PRS, " | |
| [ -n "$RECENT_STABLE_BACKPORT_PRS" ] && CHANGES="${CHANGES}stable-backport: $RECENT_STABLE_BACKPORT_PRS, " | |
| if [ -n "$CHANGES" ]; then | |
| # Remove trailing comma and space | |
| CHANGES="${CHANGES%, }" | |
| COMMIT_MSG="$COMMIT_MSG ($CHANGES)" | |
| fi | |
| # Commit the updated README and timestamps files | |
| git add README.md "$MERGED_PRS_FILE" "$CLOSED_PRS_FILE" "$DRAFT_PRS_FILE" "$STABLE_BACKPORT_PRS_FILE" | |
| git commit -m "$COMMIT_MSG" || echo "No changes to commit" | |
| - name: Update PR list file | |
| if: steps.reset_upstream.outputs.reset_success == 'true' | |
| run: | | |
| PR_LIST_FILE=".github/pr-list.txt" | |
| echo "Starting PR list update process..." | |
| # Read current PR list from file (or from manual input) | |
| CURRENT_PR_NUMBERS="${{ github.event.inputs.pr_numbers }}" | |
| if [ -z "$CURRENT_PR_NUMBERS" ]; then | |
| if [ -f "$PR_LIST_FILE" ]; then | |
| CURRENT_PR_NUMBERS=$(grep -v '^#' "$PR_LIST_FILE" | grep -v '^$' | tr '\n' ',' | sed 's/,$//') | |
| fi | |
| fi | |
| echo "Current PR list: $CURRENT_PR_NUMBERS" | |
| # Get all PRs that should be removed | |
| MERGED_UPSTREAM_PRS="${{ steps.check_pr_status.outputs.merged_upstream_prs }}" | |
| CLOSED_PRS="${{ steps.check_pr_status.outputs.closed_prs }}" | |
| DRAFT_PRS="${{ steps.check_pr_status.outputs.draft_prs }}" | |
| STABLE_BACKPORT_PRS="${{ steps.check_pr_status.outputs.stable_backport_prs }}" | |
| # Combine all PRs that should be removed | |
| PRS_TO_REMOVE="" | |
| for pr_list in "$MERGED_UPSTREAM_PRS" "$CLOSED_PRS" "$DRAFT_PRS" "$STABLE_BACKPORT_PRS"; do | |
| if [ -n "$pr_list" ]; then | |
| if [ -z "$PRS_TO_REMOVE" ]; then | |
| PRS_TO_REMOVE="$pr_list" | |
| else | |
| PRS_TO_REMOVE="$PRS_TO_REMOVE,$pr_list" | |
| fi | |
| fi | |
| done | |
| if [ -n "$PRS_TO_REMOVE" ]; then | |
| echo "PRs to be removed (merged, closed, draft, or stable backport): $PRS_TO_REMOVE" | |
| IFS=',' read -ra CURRENT_ARRAY <<< "$CURRENT_PR_NUMBERS" | |
| IFS=',' read -ra REMOVE_ARRAY <<< "$PRS_TO_REMOVE" | |
| NEW_PR_LIST="" | |
| REMOVED_COUNT=0 | |
| for PR in "${CURRENT_ARRAY[@]}"; do | |
| PR=$(echo $PR | xargs) # Trim whitespace | |
| SHOULD_REMOVE=false | |
| for REMOVE_PR in "${REMOVE_ARRAY[@]}"; do | |
| REMOVE_PR=$(echo $REMOVE_PR | xargs) | |
| if [ "$PR" == "$REMOVE_PR" ]; then | |
| SHOULD_REMOVE=true | |
| ((REMOVED_COUNT++)) | |
| echo " Removing PR $PR from list" | |
| break | |
| fi | |
| done | |
| if [ "$SHOULD_REMOVE" == "false" ]; then | |
| if [ -z "$NEW_PR_LIST" ]; then | |
| NEW_PR_LIST="$PR" | |
| else | |
| NEW_PR_LIST="$NEW_PR_LIST,$PR" | |
| fi | |
| fi | |
| done | |
| # Update pr-list.txt if PRs were removed | |
| if [ "$NEW_PR_LIST" != "$CURRENT_PR_NUMBERS" ]; then | |
| echo "Updating $PR_LIST_FILE..." | |
| echo "Old list: $CURRENT_PR_NUMBERS" | |
| echo "New list: $NEW_PR_LIST" | |
| echo "Removed $REMOVED_COUNT PR(s)" | |
| # Rewrite the file (preserve comment header, one PR per line) | |
| printf '# PR numbers to merge into this fork from jellyfin/jellyfin-web\n# Add/remove PR numbers here - workflow will read and update this file automatically\n' > "$PR_LIST_FILE" | |
| echo "$NEW_PR_LIST" | tr ',' '\n' | grep -v '^$' | xargs -I{} echo {} >> "$PR_LIST_FILE" | |
| git add "$PR_LIST_FILE" | |
| echo "PR_LIST_UPDATED=true" >> $GITHUB_ENV | |
| echo "Successfully updated $PR_LIST_FILE" | |
| else | |
| echo "No PRs to remove from the list" | |
| fi | |
| else | |
| echo "No PRs were merged upstream or closed - keeping current list intact" | |
| fi | |
| - name: Apply custom patches | |
| run: | | |
| # Restore patches directory first | |
| mkdir -p .github/patches | |
| if [ -d "/tmp/patches-backup" ]; then | |
| cp -r /tmp/patches-backup/* .github/patches/ || true | |
| fi | |
| # Apply subtitle defaults patch if it exists | |
| if [ -f ".github/patches/subtitle-defaults.patch" ]; then | |
| echo "Applying subtitle defaults patch..." | |
| if git apply --check .github/patches/subtitle-defaults.patch 2>/dev/null; then | |
| git apply .github/patches/subtitle-defaults.patch | |
| echo "✅ Subtitle defaults patch applied successfully" | |
| else | |
| echo "⚠️ Subtitle defaults patch failed to apply - may need updating" | |
| echo "This is not critical, continuing..." | |
| fi | |
| else | |
| echo "No subtitle defaults patch found at .github/patches/subtitle-defaults.patch" | |
| fi | |
| # Apply any other patches in the patches directory | |
| if [ -d ".github/patches" ]; then | |
| for patch_file in .github/patches/*.patch; do | |
| if [ -f "$patch_file" ] && [ "$patch_file" != ".github/patches/subtitle-defaults.patch" ]; then | |
| echo "Applying $(basename $patch_file)..." | |
| if git apply --check "$patch_file" 2>/dev/null; then | |
| git apply "$patch_file" | |
| echo "✅ $(basename $patch_file) applied successfully" | |
| else | |
| echo "⚠️ $(basename $patch_file) failed to apply" | |
| fi | |
| fi | |
| done | |
| fi | |
| # Commit patch changes if any were applied | |
| if ! git diff --quiet; then | |
| git add -A | |
| git commit -m "Apply custom patches after upstream reset" || true | |
| fi | |
| - name: Push changes | |
| if: steps.reset_upstream.outputs.reset_success == 'true' | |
| run: | | |
| # Clean up temporary files | |
| rm -f pr_status.txt merge_results.txt prs_to_merge.txt | |
| # Check if we have any uncommitted changes (workflow file update) | |
| if ! git diff --cached --quiet; then | |
| git commit -m "Auto-update PR list: removed merged/closed PRs" | |
| fi | |
| # Push all changes | |
| git push origin master --force | |
| - name: Generate summary | |
| if: always() | |
| run: | | |
| echo "## Workflow Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ steps.reset_upstream.outputs.reset_success }}" == "true" ]; then | |
| echo "✅ Successfully reset to upstream" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "❌ Failed to reset to upstream" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ -f "pr_status.txt" ]; then | |
| cat pr_status.txt >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ -f "merge_results.txt" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| cat merge_results.txt >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # Add info about PR list updates | |
| if [ -n "${{ env.PR_LIST_UPDATED }}" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "## PR List Update" >> $GITHUB_STEP_SUMMARY | |
| echo "Automatically removed merged/closed PRs from the workflow file" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Send Discord notification on failure | |
| uses: Ilshidur/action-discord@master | |
| if: failure() | |
| env: | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} | |
| with: | |
| args: | | |
| ❌ Reset to upstream failed! | |
| PRs attempted: ${{ github.event.inputs.pr_numbers || 'see .github/pr-list.txt' }} | |
| See workflow logs: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| - name: Send Discord notification on success | |
| uses: Ilshidur/action-discord@master | |
| if: success() | |
| env: | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} | |
| with: | |
| args: | | |
| ✅ Successfully reset to upstream jellyfin-web! | |
| ${{ env.PR_LIST_UPDATED && '📝 PR list auto-updated - merged/closed PRs removed' || '' }} | |
| 📋 README updated with current PR status | |
| 🔧 Conflict resolution: ${{ github.event.inputs.conflict_resolution_strategy || 'auto-head' }} | |
| Check the summary: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |