refactor: migrate artifact comment system from repository_dispatch to workflow_run
Some checks failed
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
🕒 Handle Stale Issues / 🗑️ Cleanup Stale Issues (push) Has been cancelled
🤖 Android APK Build (Phone + TV) / 🏗️ Build Android APK (phone) (push) Has been cancelled
🤖 Android APK Build (Phone + TV) / 🏗️ Build Android APK (tv) (push) Has been cancelled
🤖 iOS IPA Build (Phone + TV) / 🏗️ Build iOS IPA (phone) (push) Has been cancelled

Replaces the repository_dispatch event system with workflow_run triggers to improve reliability and reduce complexity. The new approach automatically detects PR associations through commit SHA lookups rather than requiring manual payload construction.

Removes redundant notification steps from build workflows and simplifies the concurrency group logic. Enhances manual testing support with improved PR discovery fallbacks.
This commit is contained in:
Uruk
2025-09-30 00:58:25 +02:00
parent 2b761f15c8
commit 788f420ce5
3 changed files with 61 additions and 203 deletions

View File

@@ -1,29 +1,29 @@
name: 📝 Artifact Comment on PR
concurrency:
group: artifact-comment-${{ github.sha }}
group: artifact-comment-${{ github.event.workflow_run.head_sha || 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]
repository_dispatch: # Triggered by build workflows when they start/complete
workflow_run: # Triggered when build workflows complete
workflows:
- "🤖 Android APK Build (Phone + TV)"
- "🤖 iOS IPA Build (Phone + TV)"
types:
- build-started
- build-completed
- build-failed
- completed
jobs:
comment-artifacts:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || github.event_name == 'repository_dispatch'
if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'pull_request')
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
@@ -34,23 +34,23 @@ jobs:
let pr;
let targetCommitSha;
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 (context.eventName === 'workflow_run') {
// Find PR associated with this workflow run commit
console.log('Workflow run event:', context.payload.workflow_run.name);
if (!payload || !payload.pr_number) {
console.log('No PR information in repository_dispatch payload');
const { data: pullRequests } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
owner: context.repo.owner,
repo: context.repo.repo,
commit_sha: context.payload.workflow_run.head_sha
});
if (pullRequests.length === 0) {
console.log('No pull request found for commit:', context.payload.workflow_run.head_sha);
return;
}
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;
pr = pullRequests[0];
targetCommitSha = context.payload.workflow_run.head_sha;
} else if (context.eventName === 'pull_request') {
// Direct PR event
@@ -58,15 +58,45 @@ jobs:
targetCommitSha = pr.head.sha;
} else if (context.eventName === 'workflow_dispatch') {
// Get current PR for manual testing
const prNumber = context.payload.pull_request?.number || 1101;
const { data: prData } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
pr = prData;
targetCommitSha = pr.head.sha;
// For manual testing, try to find PR for current branch/commit
console.log('Manual workflow dispatch triggered');
// First, try to find PRs associated with current commit
try {
const { data: pullRequests } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
owner: context.repo.owner,
repo: context.repo.repo,
commit_sha: context.sha
});
if (pullRequests.length > 0) {
pr = pullRequests[0];
targetCommitSha = pr.head.sha;
console.log(`Found PR #${pr.number} for commit ${context.sha.substring(0, 7)}`);
} else {
// Fallback: get latest open PR
const { data: openPRs } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
sort: 'updated',
direction: 'desc',
per_page: 1
});
if (openPRs.length > 0) {
pr = openPRs[0];
targetCommitSha = pr.head.sha;
console.log(`Using latest open PR #${pr.number} for manual testing`);
} else {
console.log('No open PRs found for manual testing');
return;
}
}
} catch (error) {
console.log('Error finding PR for manual testing:', error.message);
return;
}
} else {
console.log('Unsupported event type:', context.eventName);
@@ -157,52 +187,11 @@ 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**: [\`${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 += `🔗 **Commit**: [\`${targetCommitSha.substring(0, 7)}\`](https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${targetCommitSha})\n\n`; // Progressive build status and downloads table
commentBody += `### 📦 Build Artifacts\n\n`;
commentBody += `| Platform | Device | Status | Download |\n`;
commentBody += `|----------|--------|--------|---------|\n`;
@@ -217,16 +206,7 @@ jobs:
for (const target of buildTargets) {
// 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;
}
}
const matchingStatus = buildStatuses[target.workflowType];
// Find matching artifact
const matchingArtifact = allArtifacts.find(artifact =>

View File

@@ -18,7 +18,6 @@ jobs:
name: 🏗️ Build Android APK
permissions:
contents: read
repository-projects: write
strategy:
fail-fast: false
@@ -26,26 +25,6 @@ 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:
@@ -112,43 +91,3 @@ 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 }}'
}
});

View File

@@ -22,7 +22,6 @@ jobs:
name: 🏗️ Build iOS IPA
permissions:
contents: read
repository-projects: write
strategy:
fail-fast: false
@@ -31,26 +30,6 @@ 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: '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:
@@ -114,43 +93,3 @@ 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 }}'
}
});