[Bug] Transfer Error Hypervisor Migration XCP-NG -> PVE over local LAN #297
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Issue Validator | |
| on: | |
| issues: | |
| types: [opened, edited] | |
| # NS Apr 2026 — CodeQL alert: pin GITHUB_TOKEN scope. We only need to read the | |
| # issue body and potentially comment/label — no code, no packages, no PRs. | |
| permissions: | |
| issues: write | |
| contents: read | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check issue body | |
| # NS 2026-05-30 — pinned to commit SHA so a moving-tag compromise can't | |
| # smuggle malicious script into the issue-validator step. | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const issue = context.payload.issue; | |
| const body = issue.body || ''; | |
| const labels = issue.labels.map(l => l.name.toLowerCase()); | |
| const title = issue.title.toLowerCase(); | |
| let isInvalid = false; | |
| let message = ''; | |
| // === BUG REPORT === | |
| if (labels.includes('bug') || title.includes('[bug]')) { | |
| const requiredFields = [ | |
| { name: 'Describe the bug', check: /describe the bug\s*\n+\s*\S+/i }, | |
| { name: 'Steps to Reproduce', check: /steps to reproduce\s*\n+\s*\S+/i }, | |
| { name: 'PegaProx Version', check: /pegaprox version:\s*\S+/i } | |
| ]; | |
| const missing = requiredFields.filter(f => !f.check.test(body)); | |
| if (missing.length > 0 || body.length < 100) { | |
| isInvalid = true; | |
| const missingList = missing.map(f => '- [ ] ' + f.name).join('\n'); | |
| const shortNote = body.length < 100 ? '\n- [ ] More details (current description is too short)' : ''; | |
| message = '👋 Thanks for reporting a bug!\n\n' + | |
| 'Unfortunately, it looks like some required information is missing.\n\n' + | |
| '**Please provide:**\n' + missingList + shortNote + '\n\n' + | |
| '**Why?**\nWe are volunteers maintaining PegaProx in our free time. ' + | |
| 'Complete bug reports help us fix issues faster. 🐾\n\n' + | |
| 'Closing for now — please reopen with the required details or open a new issue.\n\n' + | |
| '*This is an automated message.*'; | |
| } | |
| } | |
| // === FEATURE REQUEST === | |
| if (labels.includes('enhancement') || labels.includes('feature') || title.includes('[feature]')) { | |
| const hasDescription = body.length > 50; | |
| if (!hasDescription) { | |
| isInvalid = true; | |
| message = '👋 Thanks for the feature request!\n\n' + | |
| 'Unfortunately, we need a bit more detail to understand your idea.\n\n' + | |
| '**Please describe:**\n' + | |
| '- [ ] What feature would you like?\n' + | |
| '- [ ] Why? What problem does it solve?\n' + | |
| '- [ ] Any ideas how it could work?\n\n' + | |
| 'Closing for now — please reopen with more details. 🐾\n\n' + | |
| '*This is an automated message.*'; | |
| } | |
| } | |
| // === CLOSE IF INVALID === | |
| if (isInvalid) { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: message | |
| }); | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| labels: ['incomplete'] | |
| }); | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| state: 'closed' | |
| }); | |
| console.log('Issue closed: incomplete template'); | |
| } else { | |
| console.log('Issue valid'); | |
| } |