add: teamspeak #841
Workflow file for this run
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: PR Script Requirements Check | |
| on: | |
| pull_request_target: | |
| types: [opened, edited, synchronize, reopened] | |
| permissions: | |
| pull-requests: write | |
| contents: read | |
| issues: write | |
| jobs: | |
| validate-script-requirements: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Validate new script requirements | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| // Skip entirely if the PR is flagged keep-open. | |
| const prLabels = (context.payload.pull_request.labels || []).map(l => l.name); | |
| if (prLabels.includes("keep-open")) { | |
| console.log("PR has keep-open label — skipping requirement check."); | |
| return; | |
| } | |
| const body = context.payload.pull_request.body || ""; | |
| const lines = body.split("\n"); | |
| function checkboxChecked(line) { | |
| return /\[\s*x\s*\]/i.test(line); | |
| } | |
| function findLine(text) { | |
| return lines.find(l => l.includes(text)); | |
| } | |
| // --- Template presence check (runs FIRST, before anything else) --- | |
| // The "📦 Application Requirements" header is unique to the ProxmoxVED template. | |
| // If it's absent, the contributor used the wrong template OR no template at all. | |
| // Close the PR with a clear message regardless of what else is in the body. | |
| const templateSentinel = findLine("📦 Application Requirements"); | |
| if (!templateSentinel) { | |
| const message = | |
| "❌ **Pull Request Closed – PR Template Not Used**\n\n" + | |
| "The PR description is missing the **📦 Application Requirements** section, which means this PR was not opened with the ProxmoxVED PR template.\n\n" + | |
| "This usually happens in one of two ways:\n" + | |
| "- The **main repo's** PR template was used instead of the ProxmoxVED one, or\n" + | |
| "- The template was cleared or overwritten with a custom description.\n\n" + | |
| "The ProxmoxVED template contains required sections (Type of Change, Code & Security Review, Application Requirements, Source) that the maintainers rely on to review submissions. A custom description — no matter how thorough — cannot replace it.\n\n" + | |
| "### What to do\n" + | |
| "1. Open a **new PR** in this repository.\n" + | |
| "2. When the PR form loads, the ProxmoxVED template should appear automatically in the description. If it doesn't, copy it manually from " + | |
| "[`.github/pull_request_template.md`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/pull_request_template.md).\n" + | |
| "3. Fill out the checkboxes and relevant sections — you can keep your original write-up by pasting it into the Description section of the template.\n\n" + | |
| "---\n\n" + | |
| "⚠ **Maintainer note**\n\n" + | |
| "**Please do not ping or repeatedly contact maintainers to reopen this PR.** Open a fresh PR with the correct template instead."; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: message | |
| }); | |
| await github.rest.pulls.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number, | |
| state: "closed" | |
| }); | |
| core.setFailed("PR opened without the ProxmoxVED template (Application Requirements section missing)."); | |
| return; | |
| } | |
| // --- New script check --- | |
| const newScriptLine = findLine("🆕 **New script**"); | |
| if (!newScriptLine || !checkboxChecked(newScriptLine)) { | |
| console.log("Not a new script PR — skipping requirement check."); | |
| return; | |
| } | |
| // --- Requirement checklist --- | |
| const requirements = [ | |
| "The application is **at least 6 months old**", | |
| "The application is **actively maintained**", | |
| "The application has **600+ GitHub stars**", | |
| "Official **release tarballs** are published", | |
| "I understand that not all scripts will be accepted" | |
| ]; | |
| const missing = []; | |
| for (const req of requirements) { | |
| const line = findLine(req); | |
| if (!line || !checkboxChecked(line)) { | |
| missing.push(req); | |
| } | |
| } | |
| const architectureOptions = [ | |
| "**arm64 supported**", | |
| "**arm64 not tested**", | |
| "**arm64 not supported**" | |
| ]; | |
| const hasArchitectureSelection = architectureOptions.some(req => { | |
| const line = findLine(req); | |
| return line && checkboxChecked(line); | |
| }); | |
| if (!hasArchitectureSelection) { | |
| missing.push("One arm64 support option (`arm64 supported`, `arm64 not tested`, or `arm64 not supported`) must be checked"); | |
| } | |
| // Only enforce template-version-gated checks if the section exists in the PR body. | |
| // This prevents old PRs (opened before the section was added) from being closed on sync. | |
| const aiNoUsedLine = findLine("**No AI used**"); | |
| const aiWasUsedLine = findLine("**AI was used**"); | |
| if (aiNoUsedLine || aiWasUsedLine) { | |
| const hasAISelection = (aiNoUsedLine && checkboxChecked(aiNoUsedLine)) || | |
| (aiWasUsedLine && checkboxChecked(aiWasUsedLine)); | |
| if (!hasAISelection) { | |
| missing.push("One AI assistance option (`No AI used` or `AI was used – confirmed compliance with AGENTS.md and pve-script-creator.agent.md`) must be checked"); | |
| } | |
| } | |
| const noDockerLine = findLine("**No Docker / Docker Compose**"); | |
| if (noDockerLine && !checkboxChecked(noDockerLine)) { | |
| missing.push("`No Docker / Docker Compose` must be confirmed – the application must run bare-metal"); | |
| } | |
| const noGitPullLine = findLine("**No git pull**"); | |
| if (noGitPullLine && !checkboxChecked(noGitPullLine)) { | |
| missing.push("`No git pull` must be confirmed – use `fetch_and_deploy_gh_release` (or the Codeberg/GitLab/URL variants) instead"); | |
| } | |
| if (missing.length > 0) { | |
| let list = ""; | |
| for (const m of missing) { | |
| list += "- " + m + "\n"; | |
| } | |
| const message = | |
| "❌ **Pull Request Closed – Application Requirements Not Met**\n\n" + | |
| "This pull request is marked as **🆕 New script**, but the required application criteria were not confirmed.\n\n" + | |
| "The following requirement confirmations are missing:\n\n" + | |
| list + | |
| "\nNew application submissions must meet the project requirements before being considered.\n" + | |
| "Please wait until the application satisfies the criteria before submitting a new PR.\n\n" + | |
| "---\n\n" + | |
| "⚠ **Maintainer note**\n\n" + | |
| "The team periodically reviews closed submissions. If a project is still considered valuable to the ecosystem, maintainers may reopen the PR even if it does not fully meet the thresholds.\n\n" + | |
| "**Please do not ping or repeatedly contact maintainers to reopen PRs.**"; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: message | |
| }); | |
| await github.rest.pulls.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number, | |
| state: "closed" | |
| }); | |
| core.setFailed("Application requirements checklist incomplete."); | |
| } |