Files
pdf-extraction-agenda/.github/workflows/add-pipeline-comment.yaml
2025-03-01 01:48:02 +03:00

194 lines
8.4 KiB
YAML

name: Parse New Pipeline Submission
on:
issues:
types: [ opened, edited ] # Runs automatically when an issue is opened or edited
workflow_dispatch: # Allows manual execution on all existing issues
permissions:
issues: write
jobs:
parse_issue:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Extract Issue Data
uses: actions/github-script@v7
with:
script: |
const githubContext = context;
const isManualRun = process.env.GITHUB_EVENT_NAME === "workflow_dispatch";
async function deleteExistingComments(issue_number) {
console.log(`Fetching existing comments for issue #${issue_number}...`);
const comments = await github.paginate(github.rest.issues.listComments, {
owner: githubContext.repo.owner,
repo: githubContext.repo.repo,
issue_number: issue_number,
per_page: 100
});
for (const comment of comments) {
if (comment.user.type === "Bot") {
console.log(`Deleting comment ID: ${comment.id}`);
await github.rest.issues.deleteComment({
owner: githubContext.repo.owner,
repo: githubContext.repo.repo,
comment_id: comment.id
});
}
}
}
async function processIssue(issue) {
if (!issue.body) {
console.log(`Skipping issue #${issue.number} due to empty body.`);
return;
}
if (!issue.labels.some(label => label.name === 'pipeline')) {
console.log(`Skipping issue #${issue.number}, no "pipeline" label.`);
return;
}
const fields = {
'Pipeline Name': 'name',
'URL': 'url',
'GitHub URL': 'github_url',
'License': 'license',
'Custom License': 'custom_license',
'Pipeline Description': 'pipeline_description',
'Primary Language': 'primary_language',
'Demo (if available)': 'demo_link',
'Has the pipeline been benchmarked? If yes, provide benchmark results or a link to evaluation metrics.': 'benchmark_results',
'Does it have an API?': 'api_available',
'API URL (if applicable)': 'api_url',
'API Pricing Page (if applicable)': 'api_pricing',
'API Average Price per 1000 Page (if applicable)': 'api_average_price',
'Additional Notes': 'additional_notes'
};
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escapes special regex characters
}
function extractField(label) {
const escapedLabel = escapeRegExp(label); // Ensure special characters in the label are escaped
const regex = new RegExp(`### ${escapedLabel}\\n\\n(.*?)(?=\\n### |$)`, 's');
const match = issue.body.match(regex);
return match && match[1].trim() !== "_No response_" ? match[1].trim() : '';
}
const extractedData = {};
for (const [label, id] of Object.entries(fields)) {
extractedData[id] = extractField(label);
}
const {
name, url, github_url, license, custom_license,
primary_language, pipeline_description, demo_link,
benchmark_results, api_available, api_url, api_pricing,
api_average_price, additional_notes
} = extractedData;
const licenseColors = {
'Apache-2.0': 'brightgreen',
'MIT': 'brightgreen',
'BSD-3-Clause': 'brightgreen',
'GPL-3.0': 'yellow',
'MPL-2.0': 'yellow',
'AGPL-3.0': 'orange',
'Proprietary': 'red',
'Other (please specify below)': 'red'
};
const licenseDisplay = license === 'Other (please specify below)' && custom_license ? custom_license : license;
const licenseColor = licenseColors[license] || 'lightgrey';
const licenseBadge = `![License](https://img.shields.io/badge/License-${licenseDisplay.replace(/-/g, '--')}-${licenseColor})`;
const githubBadge = github_url ? `[![GitHub last commit](https://img.shields.io/github/last-commit/${github_url.replace('https://github.com/', '')}?label=GitHub&logo=github)](${github_url})` : '';
const demoBadge = demo_link ? `[![Demo](https://img.shields.io/badge/DEMO-black?logo=awwwards)](${demo_link})` : '';
const apiBadge = api_available === "Yes" && api_url
? `[![API](https://img.shields.io/badge/API-Available-blue?logo=swagger&logoColor=85EA2D)](${api_url})`
: '';
const displayURL = url || github_url || '';
const title = displayURL
? `[${name}](${displayURL})\n[✏️](${issue.html_url})`
: `${name}\n[✏️](${issue.html_url})`;
let formattedOutput = `### ${title}`.trim();
if (githubBadge || licenseBadge || demoBadge || apiBadge) {
formattedOutput += `\n${[githubBadge, licenseBadge, demoBadge, apiBadge].filter(Boolean).join("\n")}`;
}
if (primary_language) {
formattedOutput += `\n\n**Primary Language:** ${primary_language}`;
}
if (licenseDisplay) {
formattedOutput += `\n\n**License:** ${licenseDisplay}`;
}
if (pipeline_description) {
formattedOutput += `\n\n**Description:** ${pipeline_description}`;
}
if (benchmark_results) {
formattedOutput += `\n\n**Benchmark Results:** ${benchmark_results}`;
}
if (api_available === "Yes") {
formattedOutput += `\n\n**API Details:**`;
if (api_url) formattedOutput += `\n- **API URL:** ${api_url}`;
if (api_pricing) formattedOutput += `\n- **Pricing:** ${api_pricing}`;
if (api_average_price) formattedOutput += `\n- **Average Price:** ${api_average_price}`;
}
if (additional_notes && additional_notes.trim()) {
const formattedNotes = additional_notes.replace(/```markdown/g, '').replace(/```/g, '').trim();
if (formattedNotes) {
formattedOutput += `\n\n**Additional Notes:**\n${formattedNotes}`;
}
}
formattedOutput = formattedOutput.trim(); // Remove leading/trailing spaces
await deleteExistingComments(issue.number);
console.log(`Updating issue #${issue.number}...`);
await github.rest.issues.createComment({
owner: githubContext.repo.owner,
repo: githubContext.repo.repo,
issue_number: issue.number,
body: formattedOutput
});
}
if (isManualRun) {
console.log("Manual run triggered: Processing all open pipeline issues...");
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner: githubContext.repo.owner,
repo: githubContext.repo.repo,
state: 'open',
per_page: 100
});
for (const issue of issues) {
await processIssue(issue);
}
} else {
const issue = githubContext.payload.issue;
if (!issue) {
console.log("No issue found in context. Exiting.");
return 1;
}
console.log(`Triggered automatically on issue #${issue.number}`);
await processIssue(issue);
}