|
| 1 | +import test from 'node:test'; |
| 2 | +import assert from 'node:assert/strict'; |
| 3 | +import fs from 'node:fs'; |
| 4 | +import os from 'node:os'; |
| 5 | +import path from 'node:path'; |
| 6 | +import { execFileSync } from 'node:child_process'; |
| 7 | + |
| 8 | +const repoRoot = path.resolve(process.cwd()); |
| 9 | + |
| 10 | +function writeFile(targetPath, contents) { |
| 11 | + fs.mkdirSync(path.dirname(targetPath), { recursive: true }); |
| 12 | + fs.writeFileSync(targetPath, contents); |
| 13 | +} |
| 14 | + |
| 15 | +function cleanupTempDir(targetPath) { |
| 16 | + try { |
| 17 | + fs.chmodSync(targetPath, 0o755); |
| 18 | + } catch {} |
| 19 | + for (const entry of fs.readdirSync(targetPath, { withFileTypes: true })) { |
| 20 | + const entryPath = path.join(targetPath, entry.name); |
| 21 | + if (entry.isDirectory()) { |
| 22 | + cleanupTempDir(entryPath); |
| 23 | + continue; |
| 24 | + } |
| 25 | + try { |
| 26 | + fs.chmodSync(entryPath, 0o644); |
| 27 | + } catch {} |
| 28 | + } |
| 29 | + fs.rmSync(targetPath, { recursive: true, force: true }); |
| 30 | +} |
| 31 | + |
| 32 | +function copyFileIntoTemp(tempRoot, relativePath) { |
| 33 | + const sourcePath = path.join(repoRoot, relativePath); |
| 34 | + const targetPath = path.join(tempRoot, relativePath); |
| 35 | + writeFile(targetPath, fs.readFileSync(sourcePath, 'utf8')); |
| 36 | +} |
| 37 | + |
| 38 | +function createBrokenGitBin(tempRoot) { |
| 39 | + const binDir = path.join(tempRoot, 'fake-bin'); |
| 40 | + const gitPath = path.join(binDir, 'git'); |
| 41 | + fs.mkdirSync(binDir, { recursive: true }); |
| 42 | + fs.writeFileSync(gitPath, '#!/usr/bin/env bash\nexit 128\n'); |
| 43 | + fs.chmodSync(gitPath, 0o755); |
| 44 | + return binDir; |
| 45 | +} |
| 46 | + |
| 47 | +function runBash(args, cwd, extraEnv = {}) { |
| 48 | + return execFileSync('bash', args, { |
| 49 | + cwd, |
| 50 | + encoding: 'utf8', |
| 51 | + env: { |
| 52 | + ...process.env, |
| 53 | + ...extraEnv |
| 54 | + }, |
| 55 | + stdio: ['ignore', 'pipe', 'pipe'] |
| 56 | + }); |
| 57 | +} |
| 58 | + |
| 59 | +test('ensure_plg_changes_entry tolerates unavailable git metadata when curated notes exist', (t) => { |
| 60 | + const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'fvplus-ensure-changes-')); |
| 61 | + t.after(() => { |
| 62 | + cleanupTempDir(tempRoot); |
| 63 | + }); |
| 64 | + |
| 65 | + copyFileIntoTemp(tempRoot, 'scripts/ensure_plg_changes_entry.sh'); |
| 66 | + copyFileIntoTemp(tempRoot, 'scripts/lib.sh'); |
| 67 | + |
| 68 | + writeFile(path.join(tempRoot, 'folderview.plus.plg'), `<?xml version="1.0" standalone="yes"?> |
| 69 | +<!DOCTYPE PLUGIN [ |
| 70 | +<!ENTITY name "folderview.plus"> |
| 71 | +<!ENTITY author "alexphillips-dev"> |
| 72 | +<!ENTITY github "alexphillips-dev/FolderView-Plus"> |
| 73 | +<!ENTITY launch "Settings/FolderViewPlus"> |
| 74 | +<!ENTITY plugdir "/usr/local/emhttp/plugins/&name;"> |
| 75 | +<!ENTITY pluginURL "https://raw.githubusercontent.com/&github;/dev/folderview.plus.plg"> |
| 76 | +<!ENTITY version "2026.04.15.02"> |
| 77 | +<!ENTITY md5 "placeholder"> |
| 78 | +]> |
| 79 | +<PLUGIN name="&name;" author="&author;" version="&version;" launch="&launch;" pluginURL="&pluginURL;" icon="folder-icon.png" support="https://forums.unraid.net/topic/197631-plugin-folderview-plus/" min="7.0.0"> |
| 80 | + <CHANGES> |
| 81 | +
|
| 82 | +###2026.04.15.01 |
| 83 | +- Fix: Previous release. |
| 84 | + </CHANGES> |
| 85 | +</PLUGIN> |
| 86 | +`); |
| 87 | + writeFile(path.join(tempRoot, 'docs', 'releases', '2026.04.15.02.md'), `- Fix: Prevent release-note insertion from failing when git metadata is unavailable. |
| 88 | +- Quality: Allow curated notes to seed the new release block even when git probes fail. |
| 89 | +`); |
| 90 | + |
| 91 | + const brokenGitBin = createBrokenGitBin(tempRoot); |
| 92 | + runBash(['scripts/ensure_plg_changes_entry.sh', '--version', '2026.04.15.02'], tempRoot, { |
| 93 | + PATH: `${brokenGitBin}${path.delimiter}${process.env.PATH ?? ''}` |
| 94 | + }); |
| 95 | + |
| 96 | + const updatedPlg = fs.readFileSync(path.join(tempRoot, 'folderview.plus.plg'), 'utf8'); |
| 97 | + assert.match(updatedPlg, /###2026\.04\.15\.02/); |
| 98 | + assert.match(updatedPlg, /Prevent release-note insertion from failing when git metadata is unavailable/); |
| 99 | +}); |
| 100 | + |
| 101 | +test('pkg_build dry-run falls back to manifest branch when git branch detection is unavailable', (t) => { |
| 102 | + const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'fvplus-pkg-build-')); |
| 103 | + t.after(() => { |
| 104 | + cleanupTempDir(tempRoot); |
| 105 | + }); |
| 106 | + |
| 107 | + copyFileIntoTemp(tempRoot, 'pkg_build.sh'); |
| 108 | + writeFile(path.join(tempRoot, 'folderview.plus.plg'), `<?xml version="1.0" standalone="yes"?> |
| 109 | +<!DOCTYPE PLUGIN [ |
| 110 | +<!ENTITY name "folderview.plus"> |
| 111 | +<!ENTITY author "alexphillips-dev"> |
| 112 | +<!ENTITY github "alexphillips-dev/FolderView-Plus"> |
| 113 | +<!ENTITY launch "Settings/FolderViewPlus"> |
| 114 | +<!ENTITY plugdir "/usr/local/emhttp/plugins/&name;"> |
| 115 | +<!ENTITY pluginURL "https://raw.githubusercontent.com/&github;/dev/folderview.plus.plg"> |
| 116 | +<!ENTITY version "2026.04.15.01"> |
| 117 | +<!ENTITY md5 "placeholder"> |
| 118 | +]> |
| 119 | +<PLUGIN name="&name;" author="&author;" version="&version;" launch="&launch;" pluginURL="&pluginURL;" icon="folder-icon.png" support="https://forums.unraid.net/topic/197631-plugin-folderview-plus/" min="7.0.0"> |
| 120 | + <FILE Name="/tmp/folderview.plus.txz"> |
| 121 | + <URL>https://raw.githubusercontent.com/&github;/dev/archive/&name;-&version;.txz</URL> |
| 122 | + </FILE> |
| 123 | +</PLUGIN> |
| 124 | +`); |
| 125 | + writeFile(path.join(tempRoot, 'folderview.plus.xml'), `<FILE Name="folderview.plus.plg"><Date>2026-04-15</Date><PluginURL>https://raw.githubusercontent.com/alexphillips-dev/FolderView-Plus/dev/folderview.plus.plg</PluginURL><Icon>https://raw.githubusercontent.com/alexphillips-dev/FolderView-Plus/dev/src/folderview.plus/usr/local/emhttp/plugins/folderview.plus/images/folder-icon.png</Icon><Beta>False</Beta><Name>FolderView Plus</Name></FILE>`); |
| 126 | + writeFile(path.join(tempRoot, 'scripts', 'release_guard.sh'), '#!/usr/bin/env bash\nexit 0\n'); |
| 127 | + writeFile(path.join(tempRoot, 'scripts', 'ensure_plg_changes_entry.sh'), '#!/usr/bin/env bash\nexit 0\n'); |
| 128 | + fs.chmodSync(path.join(tempRoot, 'scripts', 'release_guard.sh'), 0o755); |
| 129 | + fs.chmodSync(path.join(tempRoot, 'scripts', 'ensure_plg_changes_entry.sh'), 0o755); |
| 130 | + writeFile(path.join(tempRoot, 'src', 'folderview.plus', 'usr', 'local', 'emhttp', 'plugins', 'folderview.plus', 'README.md'), 'placeholder\n'); |
| 131 | + |
| 132 | + const brokenGitBin = createBrokenGitBin(tempRoot); |
| 133 | + const output = runBash(['pkg_build.sh', '--dry-run'], tempRoot, { |
| 134 | + PATH: `${brokenGitBin}${path.delimiter}${process.env.PATH ?? ''}` |
| 135 | + }); |
| 136 | + |
| 137 | + assert.match(output, /Branch: dev/); |
| 138 | +}); |
0 commit comments