mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-24 12:08:05 +00:00
Fixes workflow trigger condition by explicitly checking for workflow_run event type to prevent unintended executions. Improves artifact collection reliability by switching to the correct API method and increasing page size to capture more artifacts from multiple builds. Removes redundant artifact fetching logic that was duplicating collection efforts.
210 lines
9.2 KiB
YAML
210 lines
9.2 KiB
YAML
name: 📝 Artifact Comment on PR
|
|
|
|
concurrency:
|
|
group: artifact-comment-${{ github.event.workflow_run.head_sha || github.sha }}
|
|
cancel-in-progress: true
|
|
|
|
on:
|
|
workflow_dispatch: # Allow manual testing
|
|
workflow_run:
|
|
workflows:
|
|
- "🤖 Android APK Build (Phone + TV)"
|
|
- "🤖 iOS IPA Build (Phone + TV)"
|
|
types:
|
|
- completed
|
|
- requested # Trigger when build starts
|
|
|
|
jobs:
|
|
comment-artifacts:
|
|
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'pull_request')
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
actions: read
|
|
|
|
steps:
|
|
- name: 🔍 Get PR and Artifacts
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
// Handle both workflow_run and manual dispatch events
|
|
let pr;
|
|
|
|
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 (pullRequests.length === 0) {
|
|
console.log('No pull request found for commit:', github.event.workflow_run.head_sha);
|
|
return;
|
|
}
|
|
pr = pullRequests[0];
|
|
|
|
} 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;
|
|
|
|
} else {
|
|
console.log('Unsupported event type:', context.eventName);
|
|
return;
|
|
}
|
|
|
|
console.log(`Processing PR #${pr.number} for commit ${pr.head.sha.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,
|
|
per_page: 20
|
|
});
|
|
|
|
// Filter for build workflows only
|
|
const buildRuns = workflowRuns.workflow_runs.filter(run =>
|
|
run.name.includes('Android APK Build') ||
|
|
run.name.includes('iOS IPA Build')
|
|
);
|
|
|
|
console.log(`Found ${buildRuns.length} build workflow runs for this commit`);
|
|
|
|
// Collect artifacts from all completed successful builds
|
|
let allArtifacts = [];
|
|
let buildStatuses = {};
|
|
|
|
for (const run of buildRuns) {
|
|
buildStatuses[run.name] = {
|
|
status: run.status,
|
|
conclusion: run.conclusion,
|
|
url: run.html_url,
|
|
runId: run.id
|
|
};
|
|
|
|
if (run.conclusion === 'success') {
|
|
try {
|
|
const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
run_id: run.id
|
|
});
|
|
allArtifacts.push(...artifacts.artifacts);
|
|
} catch (error) {
|
|
console.log(`Failed to get artifacts for run ${run.id}:`, error.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log(`Collected ${allArtifacts.length} total artifacts from all builds`);
|
|
|
|
// Sort and categorize all collected artifacts
|
|
const androidArtifacts = allArtifacts
|
|
.filter(a => a.name.includes('android'))
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
const iosArtifacts = allArtifacts
|
|
.filter(a => a.name.includes('ios'))
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
|
|
// Build comment body with progressive status
|
|
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`;
|
|
|
|
// Add build status table
|
|
commentBody += `### 🔧 Build Status\n\n`;
|
|
commentBody += `| Workflow | Status | Artifacts |\n`;
|
|
commentBody += `|----------|--------|-----------|\n`;
|
|
|
|
for (const [name, status] of Object.entries(buildStatuses)) {
|
|
const emoji = status.conclusion === 'success' ? '✅' :
|
|
status.conclusion === 'failure' ? '❌' :
|
|
status.status === 'in_progress' ? '🔄' : '⏳';
|
|
const statusText = status.conclusion || status.status || 'pending';
|
|
const artifactCount = allArtifacts.filter(a => {
|
|
// Match artifacts to workflows based on naming patterns
|
|
if (name.includes('Android')) return a.name.includes('android');
|
|
if (name.includes('iOS')) return a.name.includes('ios');
|
|
return false;
|
|
}).length;
|
|
|
|
commentBody += `| [${name}](${status.url}) | ${emoji} ${statusText} | ${artifactCount} |\n`;
|
|
}
|
|
|
|
commentBody += `\n`;
|
|
|
|
// Only show download table if there are artifacts
|
|
if (allArtifacts.length > 0) {
|
|
commentBody += `### 📦 Available Downloads (${allArtifacts.length} artifacts)\n\n`;
|
|
|
|
// Create table for better organization
|
|
commentBody += `| Platform | Device Type | Download Link |\n`;
|
|
commentBody += `|----------|-------------|---------------|\n`;
|
|
|
|
// Add Android artifacts
|
|
androidArtifacts.forEach(artifact => {
|
|
const isTV = artifact.name.includes('tv');
|
|
const deviceType = isTV ? '📺 Android TV' : '📱 Android Phone';
|
|
const nightlyLink = `https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/runs/${artifact.workflow_run.id}/${artifact.name}.zip`;
|
|
commentBody += `| 🤖 Android | ${deviceType} | [📥 Download APK](${nightlyLink}) |\n`;
|
|
});
|
|
|
|
// Add iOS artifacts
|
|
iosArtifacts.forEach(artifact => {
|
|
const isTV = artifact.name.includes('tv');
|
|
const deviceType = isTV ? '📺 Apple TV' : '📱 iPhone/iPad';
|
|
const nightlyLink = `https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/runs/${artifact.workflow_run.id}/${artifact.name}.zip`;
|
|
commentBody += `| 🍎 iOS | ${deviceType} | [📥 Download IPA](${nightlyLink}) |\n`;
|
|
});
|
|
|
|
commentBody += `\n`;
|
|
commentBody += `### 🔧 Installation Instructions\n\n`;
|
|
commentBody += `- **Android APK**: Download and install directly on your device (enable "Install from unknown sources")\n`;
|
|
commentBody += `- **iOS IPA**: Install using [AltStore](https://altstore.io/), [Sideloadly](https://sideloadly.io/), or Xcode\n\n`;
|
|
commentBody += `> ⚠️ **Note**: Artifacts expire in 7 days from build date\n\n`;
|
|
} else {
|
|
commentBody += `⏳ **No artifacts available yet** - builds are still in progress or haven't completed successfully.\n\n`;
|
|
}
|
|
|
|
commentBody += `<sub>*Auto-generated by [GitHub Actions](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId})*</sub>`;
|
|
commentBody += `\n<!-- streamyfin-artifact-comment -->`;
|
|
|
|
// Find existing bot comment to update
|
|
const { data: comments } = await github.rest.issues.listComments({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr.number
|
|
});
|
|
|
|
const botComment = comments.find(comment =>
|
|
comment.user.type === 'Bot' &&
|
|
comment.body.includes('<!-- streamyfin-artifact-comment -->')
|
|
);
|
|
|
|
if (botComment) {
|
|
// Update existing comment
|
|
await github.rest.issues.updateComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: botComment.id,
|
|
body: commentBody
|
|
});
|
|
console.log(`✅ Updated comment ${botComment.id} on PR #${pr.number}`);
|
|
} else {
|
|
// Create new comment
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr.number,
|
|
body: commentBody
|
|
});
|
|
console.log(`✅ Created new comment on PR #${pr.number}`);
|
|
}
|