diff --git a/.github/workflows/artifact-comment.yml b/.github/workflows/artifact-comment.yml index 1aa981f1..0bfb99af 100644 --- a/.github/workflows/artifact-comment.yml +++ b/.github/workflows/artifact-comment.yml @@ -1,56 +1,61 @@ name: 📝 Artifact Comment on PR concurrency: - group: artifact-comment-${{ github.event.workflow_run.head_sha || github.sha }} + group: artifact-comment-${{ github.sha }} cancel-in-progress: true on: workflow_dispatch: # Allow manual testing pull_request: # Show in PR checks and provide status updates types: [opened, synchronize, reopened] - workflow_run: - workflows: - - "🤖 Android APK Build (Phone + TV)" - - "🤖 iOS IPA Build (Phone + TV)" + repository_dispatch: # Triggered by build workflows when they start/complete types: - - completed - - requested # Trigger when build starts + - build-started + - build-completed + - build-failed jobs: comment-artifacts: - if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'pull_request') + if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || github.event_name == 'repository_dispatch' name: 📦 Post Build Artifacts runs-on: ubuntu-latest permissions: contents: read pull-requests: write actions: read + repository-projects: read steps: - name: 🔍 Get PR and Artifacts uses: actions/github-script@v8 with: script: | - // Handle workflow_run, pull_request, and manual dispatch events + // Handle repository_dispatch, pull_request, and manual dispatch events let pr; + let targetCommitSha; - if (context.eventName === 'workflow_run') { - // Find PR associated with this commit - const { data: pullRequests } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ - owner: context.repo.owner, - repo: context.repo.repo, - commit_sha: github.event.workflow_run.head_sha - }); + if (context.eventName === 'repository_dispatch') { + // Triggered by build workflows - get PR info from payload + const payload = context.payload.client_payload; + console.log('Repository dispatch payload:', JSON.stringify(payload, null, 2)); - if (pullRequests.length === 0) { - console.log('No pull request found for commit:', github.event.workflow_run.head_sha); + if (!payload || !payload.pr_number) { + console.log('No PR information in repository_dispatch payload'); return; } - pr = pullRequests[0]; + + const { data: prData } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: payload.pr_number + }); + pr = prData; + targetCommitSha = payload.commit_sha || pr.head.sha; } else if (context.eventName === 'pull_request') { // Direct PR event pr = context.payload.pull_request; + targetCommitSha = pr.head.sha; } else if (context.eventName === 'workflow_dispatch') { // Get current PR for manual testing @@ -61,19 +66,20 @@ jobs: pull_number: prNumber }); pr = prData; + targetCommitSha = pr.head.sha; } else { console.log('Unsupported event type:', context.eventName); return; } - console.log(`Processing PR #${pr.number} for commit ${pr.head.sha.substring(0, 7)}`); + console.log(`Processing PR #${pr.number} for commit ${targetCommitSha.substring(0, 7)}`); // Get all recent workflow runs for this PR to collect artifacts from multiple builds const { data: workflowRuns } = await github.rest.actions.listWorkflowRunsForRepo({ owner: context.repo.owner, repo: context.repo.repo, - head_sha: pr.head.sha, + head_sha: targetCommitSha, per_page: 30 }); @@ -151,11 +157,50 @@ jobs: } } + // Override with real-time data from repository_dispatch if available + if (context.eventName === 'repository_dispatch') { + const payload = context.payload.client_payload; + const workflowType = payload.workflow_name.includes('Android') ? 'Android' : 'iOS'; + + if (buildStatuses[workflowType]) { + // Update the existing status with real-time data + buildStatuses[workflowType].status = payload.status === 'in_progress' ? 'in_progress' : + payload.status === 'success' ? 'completed' : + payload.status === 'failure' ? 'completed' : + buildStatuses[workflowType].status; + buildStatuses[workflowType].conclusion = payload.status === 'success' ? 'success' : + payload.status === 'failure' ? 'failure' : + buildStatuses[workflowType].conclusion; + buildStatuses[workflowType].url = payload.run_url; + buildStatuses[workflowType].target = payload.target; + } else { + // Create new status entry for real-time updates + buildStatuses[workflowType] = { + name: payload.workflow_name, + status: payload.status === 'in_progress' ? 'in_progress' : + payload.status === 'success' ? 'completed' : + payload.status === 'failure' ? 'completed' : 'queued', + conclusion: payload.status === 'success' ? 'success' : + payload.status === 'failure' ? 'failure' : null, + url: payload.run_url, + runId: payload.run_id, + target: payload.target, + created_at: new Date().toISOString() + }; + } + } + console.log(`Collected ${allArtifacts.length} total artifacts from all builds`); // Build comment body with progressive status for individual builds let commentBody = `## 🔧 Build Status for PR #${pr.number}\n\n`; - commentBody += `🔗 **Commit**: [\`${pr.head.sha.substring(0, 7)}\`](https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${pr.head.sha})\n\n`; + commentBody += `🔗 **Commit**: [\`${targetCommitSha.substring(0, 7)}\`](https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${targetCommitSha})\n\n`; + + // Show event context for debugging (only for repository_dispatch) + if (context.eventName === 'repository_dispatch') { + const payload = context.payload.client_payload; + commentBody += `🔔 **Real-time Update**: ${payload.workflow_name} (${payload.target}) - ${payload.status}\n\n`; + } // Progressive build status and downloads table commentBody += `### 📦 Build Artifacts\n\n`; @@ -164,15 +209,24 @@ jobs: // Process each expected build target individually const buildTargets = [ - { name: 'Android Phone', platform: '🤖', device: '📱', pattern: /android.*phone/i }, - { name: 'Android TV', platform: '🤖', device: '📺', pattern: /android.*tv/i }, - { name: 'iOS Phone', platform: '🍎', device: '📱', pattern: /ios.*phone/i }, - { name: 'iOS TV', platform: '🍎', device: '📺', pattern: /ios.*tv/i } + { name: 'Android Phone', platform: '🤖', device: '📱', workflowType: 'Android', target: 'phone' }, + { name: 'Android TV', platform: '🤖', device: '📺', workflowType: 'Android', target: 'tv' }, + { name: 'iOS Phone', platform: '🍎', device: '📱', workflowType: 'iOS', target: 'phone' }, + { name: 'iOS TV', platform: '🍎', device: '📺', workflowType: 'iOS', target: 'tv' } ]; for (const target of buildTargets) { - // Find matching workflow status (using our simplified structure) - const matchingStatus = target.name.includes('Android') ? buildStatuses['Android'] : buildStatuses['iOS']; + // Find matching workflow status + let matchingStatus = buildStatuses[target.workflowType]; + + // For repository_dispatch events, check if this specific target matches + if (context.eventName === 'repository_dispatch' && matchingStatus) { + const payload = context.payload.client_payload; + if (payload.target !== target.target) { + // This update is for a different target, show default status + matchingStatus = null; + } + } // Find matching artifact const matchingArtifact = allArtifacts.find(artifact => diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index bc9b9ea1..d273f616 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -18,6 +18,7 @@ jobs: name: 🏗️ Build Android APK permissions: contents: read + repository-projects: write strategy: fail-fast: false @@ -25,6 +26,26 @@ jobs: target: [phone, tv] steps: + - name: 📢 Notify artifact comment workflow (started) + if: github.event_name == 'pull_request' + uses: actions/github-script@v8 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: 'build-started', + client_payload: { + workflow_name: 'Android APK Build', + target: '${{ matrix.target }}', + status: 'in_progress', + pr_number: ${{ github.event.pull_request.number }}, + commit_sha: '${{ github.event.pull_request.head.sha }}', + run_id: ${{ github.run_id }}, + run_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' + } + }); + - name: 📥 Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: @@ -91,3 +112,43 @@ jobs: path: | android/app/build/outputs/apk/release/*.apk retention-days: 7 + + - name: 🔔 Notify artifact comment workflow (success) + if: success() && github.event_name == 'pull_request' + uses: actions/github-script@v8 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: 'build-completed', + client_payload: { + workflow_name: 'Android APK Build', + target: '${{ matrix.target }}', + status: 'success', + pr_number: ${{ github.event.pull_request.number }}, + commit_sha: '${{ github.event.pull_request.head.sha }}', + run_id: ${{ github.run_id }}, + run_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' + } + }); + + - name: 🔔 Notify artifact comment workflow (failure) + if: failure() && github.event_name == 'pull_request' + uses: actions/github-script@v8 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: 'build-failed', + client_payload: { + workflow_name: 'Android APK Build', + target: '${{ matrix.target }}', + status: 'failure', + pr_number: ${{ github.event.pull_request.number }}, + commit_sha: '${{ github.event.pull_request.head.sha }}', + run_id: ${{ github.run_id }}, + run_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' + } + }); diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml index 98b587b3..27c5be6c 100644 --- a/.github/workflows/build-ios.yml +++ b/.github/workflows/build-ios.yml @@ -9,11 +9,11 @@ on: pull_request: branches: [develop, master] paths-ignore: - - '*.md' + - "*.md" push: branches: [develop, master] paths-ignore: - - '*.md' + - "*.md" jobs: build-ios: @@ -22,14 +22,35 @@ jobs: name: 🏗️ Build iOS IPA permissions: contents: read + repository-projects: write strategy: fail-fast: false matrix: target: [phone] -# target: [phone, tv] + # target: [phone, tv] steps: + - name: 📢 Notify artifact comment workflow (started) + if: github.event_name == 'pull_request' + uses: actions/github-script@v8 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: 'build-started', + client_payload: { + workflow_name: 'iOS IPA Build', + target: '${{ matrix.target }}', + status: 'in_progress', + pr_number: ${{ github.event.pull_request.number }}, + commit_sha: '${{ github.event.pull_request.head.sha }}', + run_id: ${{ github.run_id }}, + run_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' + } + }); + - name: 📥 Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: @@ -93,3 +114,43 @@ jobs: name: streamyfin-ios-${{ matrix.target }}-ipa-${{ env.DATE_TAG }} path: build-*.ipa retention-days: 7 + + - name: 🔔 Notify artifact comment workflow (success) + if: success() && github.event_name == 'pull_request' + uses: actions/github-script@v8 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: 'build-completed', + client_payload: { + workflow_name: 'iOS IPA Build', + target: '${{ matrix.target }}', + status: 'success', + pr_number: ${{ github.event.pull_request.number }}, + commit_sha: '${{ github.event.pull_request.head.sha }}', + run_id: ${{ github.run_id }}, + run_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' + } + }); + + - name: 🔔 Notify artifact comment workflow (failure) + if: failure() && github.event_name == 'pull_request' + uses: actions/github-script@v8 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: 'build-failed', + client_payload: { + workflow_name: 'iOS IPA Build', + target: '${{ matrix.target }}', + status: 'failure', + pr_number: ${{ github.event.pull_request.number }}, + commit_sha: '${{ github.event.pull_request.head.sha }}', + run_id: ${{ github.run_id }}, + run_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' + } + });