From 7756cad12ac9d0cdeb815b2b241081534a43a7ec Mon Sep 17 00:00:00 2001 From: "CanbiZ (MickLesk)" <47820557+MickLesk@users.noreply.github.com> Date: Tue, 29 Sep 2026 15:23:48 +0200 Subject: [PATCH] Post a test command for vm/, tools/ and turnkey/ changes too (#17587) A fix to tools/addon/all-templates.sh got no comment because only ct/ and install/ were recognised. Each script now also says where it runs, read from what it calls: the Proxmox VE host, inside a guest, or PBS/PMG/PDM. --- .github/workflows/pr-test-command.yml | 63 +++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-test-command.yml b/.github/workflows/pr-test-command.yml index 0007e2d3e..5cbeeb4c5 100644 --- a/.github/workflows/pr-test-command.yml +++ b/.github/workflows/pr-test-command.yml @@ -2,7 +2,8 @@ name: PR test command # Posts a ready-to-run test command for reviewers. # It uses this PR’s script branch with the production engine, since both resolve -# independently. Only scripts using community-scripts/core are supported. +# independently. ct/ scripts need community-scripts/core; vm/, tools/ and +# turnkey/ scripts run straight from the branch. # # pull_request_target allows comments on fork PRs. No PR code is checked out or # executed; API inputs are validated and the comment is assembled in JavaScript. @@ -14,6 +15,9 @@ on: paths: - "ct/**" - "install/**" + - "vm/**" + - "tools/**" + - "turnkey/**" jobs: comment: @@ -50,14 +54,43 @@ jobs: // ct/foo.sh and install/foo-install.sh are the same app. A removed // file has nothing left to run. const apps = new Map(); // slug -> {ct, install} + const others = []; for (const f of files) { if (f.status === 'removed') continue; let m = f.filename.match(/^ct\/([a-z0-9][a-z0-9._-]*)\.sh$/); if (m) { apps.set(m[1], { ...apps.get(m[1]), ct: true }); continue; } m = f.filename.match(/^install\/([a-z0-9][a-z0-9._-]*)-install\.sh$/); - if (m) apps.set(m[1], { ...apps.get(m[1]), install: true }); + if (m) { apps.set(m[1], { ...apps.get(m[1]), install: true }); continue; } + if (/^(vm|tools|turnkey)\/[A-Za-z0-9._\/-]+\.sh$/.test(f.filename)) others.push(f.filename); } - if (apps.size === 0) return; + if (apps.size === 0 && others.length === 0) return; + others.sort(); + + // Where a tool runs is read from the script itself; it is never run. + const HOST = /(^|[\s;&|(`$])(pct|qm|pveam|pvesm|pvesh|pveversion)\s/m; + async function runsOn(path) { + if (path.startsWith('vm/')) return 'pve'; + const appliance = (path.split('/').pop().match(/(?:^|-)(pbs|pmg|pdm)(?=[0-9-]|\.sh$)/) || [])[1]; + if (path.startsWith('tools/pve/')) return appliance || 'pve'; + let text = ''; + try { + const res = await github.rest.repos.getContent({ + owner: head.owner.login, repo: head.name, path, ref: pr.head.sha, + }); + text = Buffer.from(res.data.content || '', 'base64').toString('utf8'); + } catch (e) {} + if (HOST.test(text.replace(/^\s*#.*$/gm, '').replace(/command -v \S+/g, ''))) return 'pve'; + if (appliance) return appliance; + return path.startsWith('tools/addon/') ? 'guest' : 'unknown'; + } + const WHERE = { + pve: 'in the Proxmox VE shell', + guest: 'inside the LXC or VM that should get it', + pbs: 'in the Proxmox Backup Server shell', + pmg: 'in the Proxmox Mail Gateway shell', + pdm: 'in the Proxmox Datacenter Manager shell', + unknown: 'wherever the script is meant to run', + }; // Read the ct script at the PR head to see which engine it loads. // Read only -- it is never sourced or run. @@ -132,6 +165,30 @@ jobs: ); } + if (others.length > 0) { + const shown = others.slice(0, MAX_APPS); + lines.push(...(ready.length > 0 ? ['', '---', ''] : ['### Try this branch', ''])); + for (const path of shown) { + lines.push( + `\`${path}\`, run ${WHERE[await runsOn(path)]}:`, + '```bash', + `bash -c "$(curl -fsSL "${base}/${path}")"`, + '```', + '', + ); + } + if (others.length > shown.length) { + lines.push( + `${others.length - shown.length} more script(s) changed; same command, different path.`, + '', + ); + } + lines.push( + 'Only the script itself comes from this branch. Whatever it loads, the engine', + 'or the `misc/` helpers, still comes from `main`.', + ); + } + if (legacy.length > 0) { lines.push( '',