diff --git a/.github/workflows/template-label.js b/.github/workflows/template-label.js index 51a2028a3..6a23dbc85 100644 --- a/.github/workflows/template-label.js +++ b/.github/workflows/template-label.js @@ -1,3 +1,4 @@ +const yaml = require('js-yaml'); /* * Script for commenting on issues/PRs when the template is missing or ignored */ @@ -8,19 +9,29 @@ module.exports = async ({github, context}) => { const isPR = !!context.payload.pull_request; const number = isPR ? context.payload.pull_request.number : context.payload.issue.number; + let templateInfo; + if (isPR) { + templateInfo = await fetchTemplateAndGenerateComment('Raw template', 'https://raw.githubusercontent.com/TeamNewPipe/NewPipe/refs/heads/dev/.github/PULL_REQUEST_TEMPLATE.md', false); + } else { + const templates = { + 'bug report': 'https://raw.githubusercontent.com/TeamNewPipe/NewPipe/refs/heads/dev/.github/ISSUE_TEMPLATE/bug_report.yml', + 'feature request': 'https://raw.githubusercontent.com/TeamNewPipe/NewPipe/refs/heads/dev/.github/ISSUE_TEMPLATE/feature_request.yml' + }; + + const templateParts = await Promise.all(Object.entries(templates).map(async ([templateName, url]) => { + return await fetchTemplateAndGenerateComment(templateName, url, true); + })); + + templateInfo = templateParts.join('\n\n'); + } + let body = ''; if (label === 'template-ignored') { - body = 'Please fill in the template completely or at least as much as possible. The team needs more detailed information.'; + body = 'Please fill in the template completely or at least as much as possible. The team needs more detailed information. Here is the template, in case you deleted parts of it:\n\n' + templateInfo; } else if (label === 'template-missing') { - const kind = isPR ? 'PR' : 'issue'; - let template; - if (isPR) { - template = '
Raw template\n```\n' + process.env.PR_TEMPLATE + '\n```\n
'; - } else { - template = '[Bug report template](https://raw.githubusercontent.com/TeamNewPipe/NewPipe/refs/heads/dev/.github/ISSUE_TEMPLATE/bug_report.yml), [Feature request template](https://raw.githubusercontent.com/TeamNewPipe/NewPipe/refs/heads/dev/.github/ISSUE_TEMPLATE/feature_request.yml)'; - } - body = `Thank you for creating this ${kind}. Please edit your description and add the template with the information: ${template}`; + body = `Thank you for creating this ${isPR ? 'PR' : 'issue'}. Please edit your description and fill in the correct template with the required information:\n\n${templateInfo}`; } else { + // should never happen, but just in case return; } @@ -31,4 +42,76 @@ module.exports = async ({github, context}) => { body }); -} \ No newline at end of file +} + +async function fetchTemplateAndGenerateComment(templateName, url, extractBody) { + const response = await fetch(url); + if (!response.ok) { + console.log(`Failed to fetch ${url}: ${response.status} ${response.statusText}`); + return `
${templateName}\nView template
`; + } + let template = await response.text(); + + if (extractBody) { + const issueTemplate = yaml.load(template); + template = renderIssueForm(issueTemplate.body || []); + } + + const codeFence = '\n```\n'; + return `
${templateName}\n${codeFence}${template}${codeFence}
`; +} + +/** + * Renders the body of a YAML issue template into a Markdown string. + * @see https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms.md + * @param body + * @returns string the Markdown representation of the issue form body + */ +function renderIssueForm(body) { + return body.map(renderFormElement).filter(Boolean).join('\n\n').trim(); +} + +function renderFormElement(element) { + const attributes = element.attributes || {}; + switch (element.type) { + case 'markdown': + return attributes.value || ''; + case 'input': + case 'textarea': + case 'upload': + return renderTextElement(attributes); + case 'dropdown': + return renderDropdown(attributes); + case 'checkboxes': + return renderCheckboxes(attributes); + default: + return ''; + } +} + +function renderTextElement(attributes) { + const heading = attributes.label ? `### ${attributes.label}` : ''; + const description = attributes.description ? `` : ''; + const value = attributes.value || attributes.placeholder || ''; + return [heading, description, value].filter(Boolean).join('\n\n'); +} + +function renderDropdown(attributes) { + const options = (attributes.options || []).map(option => `- ${option}`).join('\n'); + return [ + attributes.label && `### ${attributes.label}`, + attributes.description && ``, + options + ].filter(Boolean).join('\n\n'); +} + +function renderCheckboxes(attributes) { + const options = (attributes.options || []) + .map(option => `- [ ] ${option.label || option}`) + .join('\n'); + return [ + attributes.label && `### ${attributes.label}`, + attributes.description && ``, + options + ].filter(Boolean).join('\n\n'); +} diff --git a/.github/workflows/template-label.yml b/.github/workflows/template-label.yml index ee3f4c646..55c15e00c 100644 --- a/.github/workflows/template-label.yml +++ b/.github/workflows/template-label.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - + - name: Get PR template if: ${{ github.event.pull_request && github.event.label.name == 'template-missing' }} run: | @@ -28,6 +28,9 @@ jobs: echo EOF } >> $GITHUB_ENV + - name: Install js-yaml + run: npm install --no-save --ignore-scripts js-yaml@4.1.0 + - name: Post comment uses: actions/github-script@v8 timeout-minutes: 2