Restructure repo (#251)
* refactor: restructure src/ into modules/, scripts/, and build/ - src/nag_screen/ and src/node_info/ -> src/modules/ (mods grouped explicitly) - src/Scripts/ -> src/scripts/ (lowercase, consistent) - src/gen-rules.sh -> build/ (build tool separated from source) Update all references: debian/rules, .github/workflows/*, build/gen-rules.sh, src/scripts/test/test-syntax.sh (SRC_DIR now points to src/modules/), src/scripts/test/test-patches.sh, and files.list comments. * refactor: move CI test scripts from src/scripts/test/ to build/test/ Test scripts are not installed — they are CI/dev tooling and belong alongside build/gen-rules.sh. Update workflow references and fix the SRC_DIR path depth in build/test/test-syntax.sh (../ -> ../..). * d --------- Co-authored-by: Meliox <na>
This commit is contained in:
1 parent
3db6a010df
commit
6585849459
44 files changed
+342
-30
No files matched your search
@@ -43,11 +43,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
perl -i -pe 'BEGIN { $v = $ENV{BUILD_VERSION} }
|
perl -i -pe 'BEGIN { $v = $ENV{BUILD_VERSION} }
|
||||||
s/(our \$VERSION\s*=\s*'"'"')[^'"'"']*'"'"';/${1}$v'"'"';/
|
s/(our \$VERSION\s*=\s*'"'"')[^'"'"']*'"'"';/${1}$v'"'"';/
|
||||||
' src/node_info/files/Config.pm
|
' src/modules/node_info/files/Config.pm
|
||||||
|
|
||||||
- name: Generate dynamic debian rules
|
- name: Generate dynamic debian rules
|
||||||
run: |
|
run: |
|
||||||
bash src/gen-rules.sh >> debian/rules
|
bash build/gen-rules.sh >> debian/rules
|
||||||
|
|
||||||
- name: Build deb package
|
- name: Build deb package
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
BUILD_VERSION="${{ steps.version.outputs.build_version }}"
|
BUILD_VERSION="${{ steps.version.outputs.build_version }}"
|
||||||
sed -i -E "s/^our \\\$VERSION\\s*=.*/our \\\$VERSION = '${BUILD_VERSION}';/" \
|
sed -i -E "s/^our \\\$VERSION\\s*=.*/our \\\$VERSION = '${BUILD_VERSION}';/" \
|
||||||
src/node_info/files/Config.pm
|
src/modules/node_info/files/Config.pm
|
||||||
|
|
||||||
- name: Set package version in changelog
|
- name: Set package version in changelog
|
||||||
run: |
|
run: |
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate dynamic debian rules
|
- name: Generate dynamic debian rules
|
||||||
run: |
|
run: |
|
||||||
bash src/gen-rules.sh >> debian/rules
|
bash build/gen-rules.sh >> debian/rules
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: dpkg-buildpackage -us -uc -b
|
run: dpkg-buildpackage -us -uc -b
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ jobs:
|
|||||||
path: deb
|
path: deb
|
||||||
|
|
||||||
- name: Fetch upstream Proxmox files
|
- name: Fetch upstream Proxmox files
|
||||||
run: bash src/Scripts/test/fetch-proxmox-files.sh
|
run: bash build/test/fetch-proxmox-files.sh
|
||||||
|
|
||||||
- name: Install built package
|
- name: Install built package
|
||||||
run: apt-get install -y ./deb/*.deb
|
run: apt-get install -y ./deb/*.deb
|
||||||
|
|
||||||
- name: Test all mods
|
- name: Test all mods
|
||||||
run: bash src/Scripts/test/test-patches.sh all
|
run: bash build/test/test-patches.sh all
|
||||||
|
|
||||||
- name: Validate source syntax
|
- name: Validate source syntax
|
||||||
run: bash src/Scripts/test/test-syntax.sh all
|
run: bash build/test/test-syntax.sh all
|
||||||
@@ -58,19 +58,19 @@ jobs:
|
|||||||
export BUILD_VERSION="${VERSION}-test-${SHORT_SHA}"
|
export BUILD_VERSION="${VERSION}-test-${SHORT_SHA}"
|
||||||
perl -i -pe 'BEGIN { $v = $ENV{BUILD_VERSION} }
|
perl -i -pe 'BEGIN { $v = $ENV{BUILD_VERSION} }
|
||||||
s/(our \$VERSION\s*=\s*'"'"')[^'"'"']*'"'"';/$1'"'"'$v'"'"';/
|
s/(our \$VERSION\s*=\s*'"'"')[^'"'"']*'"'"';/$1'"'"'$v'"'"';/
|
||||||
' src/node_info/files/Config.pm
|
' src/modules/node_info/files/Config.pm
|
||||||
|
|
||||||
- name: Generate dynamic debian rules
|
- name: Generate dynamic debian rules
|
||||||
run: |
|
run: |
|
||||||
bash src/gen-rules.sh >> debian/rules
|
bash build/gen-rules.sh >> debian/rules
|
||||||
bash src/gen-rules.sh conffiles >> debian/pve-mod.conffiles
|
bash build/gen-rules.sh conffiles >> debian/pve-mod.conffiles
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: dpkg-buildpackage -us -uc -b
|
run: dpkg-buildpackage -us -uc -b
|
||||||
|
|
||||||
# ── Test ───────────────────────────────────────────────────────────────
|
# ── Test ───────────────────────────────────────────────────────────────
|
||||||
- name: Fetch upstream Proxmox files
|
- name: Fetch upstream Proxmox files
|
||||||
run: bash src/Scripts/test/fetch-proxmox-files.sh
|
run: bash build/test/fetch-proxmox-files.sh
|
||||||
|
|
||||||
- name: Install built package
|
- name: Install built package
|
||||||
run: sudo apt-get install -y ../pve-mod_*.deb
|
run: sudo apt-get install -y ../pve-mod_*.deb
|
||||||
@@ -78,7 +78,7 @@ jobs:
|
|||||||
- name: Test mod
|
- name: Test mod
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
sudo bash src/Scripts/test/test-patches.sh "${{ matrix.mod }}" 2>&1 | tee test-output.log
|
sudo bash build/test/test-patches.sh "${{ matrix.mod }}" 2>&1 | tee test-output.log
|
||||||
|
|
||||||
- name: Report failure as issue
|
- name: Report failure as issue
|
||||||
if: failure()
|
if: failure()
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# src/gen-rules.sh
|
# build/gen-rules.sh
|
||||||
#
|
#
|
||||||
# Generates the per-module portion of the Debian build configuration from each
|
# Generates the per-module portion of the Debian build configuration from each
|
||||||
# module's metadata, so adding or changing a module never requires touching
|
# module's metadata, so adding or changing a module never requires touching
|
||||||
# debian/rules by hand.
|
# debian/rules by hand.
|
||||||
#
|
#
|
||||||
# A module is any directory under src/ that contains a files/ and/or patches/
|
# A module is any directory under src/modules/ that contains a files/ and/or
|
||||||
# subdirectory (so src/Scripts/, which has neither, is ignored). The module's
|
# patches/ subdirectory. The module's directory name is its canonical mod key
|
||||||
# directory name is its canonical mod key (matches the [modules] keys in
|
# (matches the [modules] keys in pve-mod.conf and the install path
|
||||||
# pve-mod.conf and the install path usr/lib/pve-mod/patches/<mod>/).
|
# usr/lib/pve-mod/patches/<mod>/).
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# gen-rules.sh Emit dpkg install lines (tab-indented, no header).
|
# gen-rules.sh Emit dpkg install lines (tab-indented, no header).
|
||||||
# Append to debian/rules' override_dh_install recipe:
|
# Append to debian/rules' override_dh_install recipe:
|
||||||
# bash src/gen-rules.sh >> debian/rules
|
# bash build/gen-rules.sh >> debian/rules
|
||||||
# Conffiles under etc/ are detected automatically by
|
# Conffiles under etc/ are detected automatically by
|
||||||
# debhelper (compat 13+); no separate conffiles step needed.
|
# debhelper (compat 13+); no separate conffiles step needed.
|
||||||
#
|
#
|
||||||
@@ -37,7 +37,7 @@ set -euo pipefail
|
|||||||
# regardless of the caller's working directory.
|
# regardless of the caller's working directory.
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
SRC_DIR="$REPO_ROOT/src"
|
SRC_DIR="$REPO_ROOT/src/modules"
|
||||||
PKG_DIR="debian/pve-mod"
|
PKG_DIR="debian/pve-mod"
|
||||||
|
|
||||||
# Print the list of module directory names (basenames), sorted, that contain a
|
# Print the list of module directory names (basenames), sorted, that contain a
|
||||||
@@ -62,7 +62,7 @@ emit_install() {
|
|||||||
emit_install_rules() {
|
emit_install_rules() {
|
||||||
local mod="$1"
|
local mod="$1"
|
||||||
local mod_dir="$SRC_DIR/$mod"
|
local mod_dir="$SRC_DIR/$mod"
|
||||||
local rel_mod="src/$mod"
|
local rel_mod="src/modules/$mod"
|
||||||
|
|
||||||
# 1. Mapped files from files/files.list.
|
# 1. Mapped files from files/files.list.
|
||||||
local manifest="$mod_dir/files/files.list"
|
local manifest="$mod_dir/files/files.list"
|
||||||
File renamed without changes.
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# src/Scripts/test/test-mods.sh
|
# build/test/test-patches.sh
|
||||||
#
|
#
|
||||||
# Exercises pve-mod's patch engine against the installed Proxmox files.
|
# Exercises pve-mod's patch engine against the installed Proxmox files.
|
||||||
#
|
#
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# build/test/test-syntax.sh
|
||||||
|
#
|
||||||
|
# Validates source syntax for all mod files without requiring a running system.
|
||||||
|
#
|
||||||
|
# Usage: test-syntax.sh <mod> | all
|
||||||
|
#
|
||||||
|
# Mods are auto-discovered by scanning for subdirectories of src/ that contain
|
||||||
|
# a files/ or patches/ directory. No installed package required.
|
||||||
|
#
|
||||||
|
# For each target mod it:
|
||||||
|
# 1. runs perl -c on every .pm file under <mod>/files/
|
||||||
|
# 2. runs node --check on every .js file under <mod>/files/
|
||||||
|
# 3. runs bash -n on post-apply.sh and post-revert.sh in <mod>/patches/
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SRC_DIR="${PVE_MOD_SRC_DIR:-$(cd "$SCRIPT_DIR/../.." && pwd)/src/modules}"
|
||||||
|
|
||||||
|
info() { echo "[syntax] $*"; }
|
||||||
|
warn() { echo "[syntax] WARNING: $*" >&2; }
|
||||||
|
|
||||||
|
# List mod names by scanning SRC_DIR for subdirs that contain files/ or patches/.
|
||||||
|
list_modules() {
|
||||||
|
local d name
|
||||||
|
for d in "$SRC_DIR"/*/; do
|
||||||
|
[[ -d "$d" ]] || continue
|
||||||
|
name="$(basename "$d")"
|
||||||
|
if [[ -d "$d/files" || -d "$d/patches" ]]; then
|
||||||
|
echo "$name"
|
||||||
|
fi
|
||||||
|
done | sort
|
||||||
|
}
|
||||||
|
|
||||||
|
# check_perl_syntax <mod>: run perl -c on every .pm under <mod>/files/
|
||||||
|
check_perl_syntax() {
|
||||||
|
local mod="$1"
|
||||||
|
local files_dir="$SRC_DIR/$mod/files"
|
||||||
|
[[ -d "$files_dir" ]] || return 0
|
||||||
|
|
||||||
|
local ok=0 f output
|
||||||
|
while IFS= read -r f; do
|
||||||
|
output="$(perl -c "$f" 2>&1)"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
warn "perl -c FAILED: $f"
|
||||||
|
echo "$output"
|
||||||
|
ok=1
|
||||||
|
fi
|
||||||
|
done < <(find "$files_dir" -name "*.pm" -type f | sort)
|
||||||
|
return $ok
|
||||||
|
}
|
||||||
|
|
||||||
|
# check_js_syntax <mod>: run node --check on every .js under <mod>/files/
|
||||||
|
check_js_syntax() {
|
||||||
|
local mod="$1"
|
||||||
|
local files_dir="$SRC_DIR/$mod/files"
|
||||||
|
[[ -d "$files_dir" ]] || return 0
|
||||||
|
|
||||||
|
local ok=0 f output
|
||||||
|
while IFS= read -r f; do
|
||||||
|
output="$(node --check "$f" 2>&1)"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
warn "node --check FAILED: $f"
|
||||||
|
echo "$output"
|
||||||
|
ok=1
|
||||||
|
fi
|
||||||
|
done < <(find "$files_dir" -name "*.js" -type f | sort)
|
||||||
|
return $ok
|
||||||
|
}
|
||||||
|
|
||||||
|
# check_bash_syntax <mod>: run bash -n on post-apply.sh and post-revert.sh
|
||||||
|
check_bash_syntax() {
|
||||||
|
local mod="$1"
|
||||||
|
local patches_src="$SRC_DIR/$mod/patches"
|
||||||
|
[[ -d "$patches_src" ]] || return 0
|
||||||
|
|
||||||
|
local ok=0 script f output
|
||||||
|
for script in post-apply.sh post-revert.sh; do
|
||||||
|
f="$patches_src/$script"
|
||||||
|
[[ -f "$f" ]] || continue
|
||||||
|
output="$(bash -n "$f" 2>&1)"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
warn "bash -n FAILED: $f"
|
||||||
|
echo "$output"
|
||||||
|
ok=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return $ok
|
||||||
|
}
|
||||||
|
|
||||||
|
# test_syntax_one_mod <mod>: run all syntax checks for one mod.
|
||||||
|
# Returns 0 on pass, 1 on any failure.
|
||||||
|
test_syntax_one_mod() {
|
||||||
|
local mod="$1"
|
||||||
|
echo "::group::Syntax check: $mod"
|
||||||
|
local ok=0
|
||||||
|
|
||||||
|
check_perl_syntax "$mod" || ok=1
|
||||||
|
check_js_syntax "$mod" || ok=1
|
||||||
|
check_bash_syntax "$mod" || ok=1
|
||||||
|
|
||||||
|
if [[ $ok -eq 0 ]]; then
|
||||||
|
info "PASS: $mod"
|
||||||
|
else
|
||||||
|
warn "FAIL: $mod"
|
||||||
|
fi
|
||||||
|
echo "::endgroup::"
|
||||||
|
return $ok
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── main ──────────────────────────────────────────────────────────────────────
|
||||||
|
[[ $# -eq 1 ]] || { echo "Usage: $0 <mod>|all" >&2; exit 2; }
|
||||||
|
|
||||||
|
if ! command -v perl >/dev/null 2>&1; then
|
||||||
|
warn "'perl' command not found; install perl."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v node >/dev/null 2>&1; then
|
||||||
|
warn "'node' command not found; install nodejs."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
targets=()
|
||||||
|
if [[ "$1" == "all" ]]; then
|
||||||
|
mapfile -t targets < <(list_modules)
|
||||||
|
[[ ${#targets[@]} -gt 0 ]] || { warn "no mods found in $SRC_DIR"; exit 1; }
|
||||||
|
else
|
||||||
|
targets=("$1")
|
||||||
|
fi
|
||||||
|
|
||||||
|
failed=()
|
||||||
|
for mod in "${targets[@]}"; do
|
||||||
|
test_syntax_one_mod "$mod" || failed+=("$mod")
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [[ ${#failed[@]} -gt 0 ]]; then
|
||||||
|
warn "Failed mods: ${failed[*]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "All tested mods passed: ${targets[*]}"
|
||||||
|
exit 0
|
||||||
Vendored
+5
-5
@@ -6,18 +6,18 @@ override_dh_install:
|
|||||||
# ── Static section ─────────────────────────────────────────────────────
|
# ── Static section ─────────────────────────────────────────────────────
|
||||||
# Generic, mod-independent files that never change when mods are added.
|
# Generic, mod-independent files that never change when mods are added.
|
||||||
# Everything mod-specific (module files, patches, per-mod configs) is
|
# Everything mod-specific (module files, patches, per-mod configs) is
|
||||||
# generated and appended below by src/gen-rules.sh at build time and is
|
# generated and appended below by build/gen-rules.sh at build time and is
|
||||||
# NOT committed to the repository.
|
# NOT committed to the repository.
|
||||||
#
|
#
|
||||||
# Patch helpers (generic, manifest-driven)
|
# Patch helpers (generic, manifest-driven)
|
||||||
install -Dm755 src/Scripts/apply-patches.sh debian/pve-mod/usr/lib/pve-mod/apply-patches.sh
|
install -Dm755 src/scripts/apply-patches.sh debian/pve-mod/usr/lib/pve-mod/apply-patches.sh
|
||||||
install -Dm755 src/Scripts/revert-patches.sh debian/pve-mod/usr/lib/pve-mod/revert-patches.sh
|
install -Dm755 src/scripts/revert-patches.sh debian/pve-mod/usr/lib/pve-mod/revert-patches.sh
|
||||||
# Configure tool
|
# Configure tool
|
||||||
install -Dm755 src/Scripts/pve-mod-configure debian/pve-mod/usr/sbin/pve-mod-configure
|
install -Dm755 src/scripts/pve-mod-configure debian/pve-mod/usr/sbin/pve-mod-configure
|
||||||
# Main config (conffile for user edits)
|
# Main config (conffile for user edits)
|
||||||
install -Dm644 src/pve-mod.conf debian/pve-mod/etc/pve-mod/pve-mod.conf
|
install -Dm644 src/pve-mod.conf debian/pve-mod/etc/pve-mod/pve-mod.conf
|
||||||
# Main config reference copy for upgrade key-diff (not a conffile)
|
# Main config reference copy for upgrade key-diff (not a conffile)
|
||||||
install -Dm644 src/pve-mod.conf debian/pve-mod/usr/share/pve-mod/pve-mod.conf.default
|
install -Dm644 src/pve-mod.conf debian/pve-mod/usr/share/pve-mod/pve-mod.conf.default
|
||||||
# ── Dynamic section ────────────────────────────────────────────────────
|
# ── Dynamic section ────────────────────────────────────────────────────
|
||||||
# `bash src/gen-rules.sh >> debian/rules` appends per-module install lines
|
# `bash build/gen-rules.sh >> debian/rules` appends per-module install lines
|
||||||
# here during CI, just before dpkg-buildpackage. Do not commit them.
|
# here during CI, just before dpkg-buildpackage. Do not commit them.
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
# source - path relative to this files/ directory
|
# source - path relative to this files/ directory
|
||||||
# destination - path relative to the package root (no leading slash)
|
# destination - path relative to the package root (no leading slash)
|
||||||
# permission - octal mode, optional (defaults to 644)
|
# permission - octal mode, optional (defaults to 644)
|
||||||
# Read by src/gen-rules.sh to generate the per-module debian install rules.
|
# Read by build/gen-rules.sh to generate the per-module debian install rules.
|
||||||
#
|
#
|
||||||
# The nag_screen mod ships no new files - it only patches existing Proxmox
|
# The nag_screen mod ships no new files - it only patches existing Proxmox
|
||||||
# files - so this manifest is intentionally empty.
|
# files - so this manifest is intentionally empty.
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -4,7 +4,7 @@
|
|||||||
# source - path relative to this files/ directory
|
# source - path relative to this files/ directory
|
||||||
# destination - path relative to the package root (no leading slash)
|
# destination - path relative to the package root (no leading slash)
|
||||||
# permission - octal mode, optional (defaults to 644)
|
# permission - octal mode, optional (defaults to 644)
|
||||||
# Read by src/gen-rules.sh to generate the per-module debian install rules.
|
# Read by build/gen-rules.sh to generate the per-module debian install rules.
|
||||||
|
|
||||||
# PVE API2 facade
|
# PVE API2 facade
|
||||||
PveMod_SensorInfo.pm usr/share/perl5/PVE/API2/PVEMod_SensorInfo.pm
|
PveMod_SensorInfo.pm usr/share/perl5/PVE/API2/PVEMod_SensorInfo.pm
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,168 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# src/scripts/test/test-patches.sh
|
||||||
|
#
|
||||||
|
# Exercises pve-mod's patch engine against the installed Proxmox files.
|
||||||
|
#
|
||||||
|
# Usage: test-mods.sh <mod> | all
|
||||||
|
#
|
||||||
|
# Mods are auto-discovered from the [modules] section of the main config, so
|
||||||
|
# adding a new mod (a new [modules] key plus a patches/<mod>/ directory) is
|
||||||
|
# picked up automatically - no edits to this script are required.
|
||||||
|
#
|
||||||
|
# For each target mod it:
|
||||||
|
# 1. enables only that mod in the main config
|
||||||
|
# 2. turns on every conditional flag referenced by the mod's patches.list,
|
||||||
|
# so all of the mod's patches are exercised (e.g. node_info's gpu_history)
|
||||||
|
# 3. runs apply-patches.sh and asserts it exits 0
|
||||||
|
# 4. runs revert-patches.sh and asserts it reports no unclean reversions
|
||||||
|
#
|
||||||
|
# Failure detection relies on the apply exit code: the patch engine performs an
|
||||||
|
# atomic preflight dry-run and exits non-zero if any mod cannot apply cleanly.
|
||||||
|
#
|
||||||
|
# Must run as root (it edits /etc/pve-mod and the patched system files).
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
MAIN_CONF="${PVE_MOD_MAIN_CONF:-/etc/pve-mod/pve-mod.conf}"
|
||||||
|
CONFD_DIR="${PVE_MOD_CONFD_DIR:-/etc/pve-mod/conf.d}"
|
||||||
|
PATCHES_DIR="${PVE_MOD_PATCHES_DIR:-/usr/lib/pve-mod/patches}"
|
||||||
|
APPLY="${PVE_MOD_APPLY:-/usr/lib/pve-mod/apply-patches.sh}"
|
||||||
|
REVERT="${PVE_MOD_REVERT:-/usr/lib/pve-mod/revert-patches.sh}"
|
||||||
|
|
||||||
|
info() { echo "[test] $*"; }
|
||||||
|
warn() { echo "[test] WARNING: $*" >&2; }
|
||||||
|
|
||||||
|
# List the keys of the [modules] section in the main config, one per line.
|
||||||
|
list_modules() {
|
||||||
|
[[ -f "$MAIN_CONF" ]] || return 0
|
||||||
|
awk -F= '
|
||||||
|
/^\[/ { in_sec = ($0 == "[modules]") }
|
||||||
|
in_sec && /^[^#=]+=/ {
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1)
|
||||||
|
print $1
|
||||||
|
}
|
||||||
|
' "$MAIN_CONF"
|
||||||
|
}
|
||||||
|
|
||||||
|
# set_conf <file> <section> <key> <value>: set an existing key within a section.
|
||||||
|
set_conf() {
|
||||||
|
local file="$1" section="$2" key="$3" value="$4"
|
||||||
|
[[ -f "$file" ]] || { warn "config not found: $file"; return 1; }
|
||||||
|
awk -v sec="[$section]" -v k="$key" -v v="$value" '
|
||||||
|
/^\[/ { in_sec = ($0 == sec) }
|
||||||
|
{
|
||||||
|
if (in_sec && $0 ~ "^[[:space:]]*"k"[[:space:]]*=") {
|
||||||
|
print k"="v
|
||||||
|
} else {
|
||||||
|
print
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Disable every discovered mod in the main config.
|
||||||
|
disable_all_modules() {
|
||||||
|
local m
|
||||||
|
for m in $(list_modules); do
|
||||||
|
set_conf "$MAIN_CONF" modules "$m" 0
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Turn on every conditional flag a mod's patches.list references, so all of its
|
||||||
|
# patches become active. Conditions look like: <patch-file> section.key=value
|
||||||
|
enable_conditions() {
|
||||||
|
local mod="$1"
|
||||||
|
local manifest="$PATCHES_DIR/$mod/patches.list"
|
||||||
|
local mod_conf="$CONFD_DIR/$mod.conf"
|
||||||
|
[[ -f "$manifest" ]] || return 0
|
||||||
|
local line cond local_key want sect ckey
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line="${line%%#*}"
|
||||||
|
line="$(echo "$line" | sed -E 's/^[[:space:]]+|[[:space:]]+$//g')"
|
||||||
|
[[ -z "$line" ]] && continue
|
||||||
|
# Skip lines without a condition (no whitespace after the patch name).
|
||||||
|
[[ "$line" == *[[:space:]]* ]] || continue
|
||||||
|
cond="$(echo "${line#*[[:space:]]}" | sed -E 's/^[[:space:]]+//')"
|
||||||
|
[[ "$cond" == *=* ]] || continue
|
||||||
|
local_key="${cond%%=*}"
|
||||||
|
want="${cond#*=}"
|
||||||
|
sect="${local_key%%.*}"
|
||||||
|
ckey="${local_key#*.}"
|
||||||
|
set_conf "$mod_conf" "$sect" "$ckey" "$want" \
|
||||||
|
&& info " enabled condition $local_key=$want in $(basename "$mod_conf")"
|
||||||
|
done < "$manifest"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test a single mod end to end. Returns 0 on success, 1 on failure.
|
||||||
|
test_one_mod() {
|
||||||
|
local mod="$1"
|
||||||
|
echo "::group::Testing mod: $mod"
|
||||||
|
local ok=0
|
||||||
|
|
||||||
|
if [[ ! -f "$PATCHES_DIR/$mod/patches.list" ]]; then
|
||||||
|
warn "no patch manifest for mod '$mod' ($PATCHES_DIR/$mod/patches.list)"
|
||||||
|
echo "::endgroup::"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
disable_all_modules
|
||||||
|
set_conf "$MAIN_CONF" modules "$mod" 1
|
||||||
|
enable_conditions "$mod"
|
||||||
|
|
||||||
|
info "Applying patches for '$mod'..."
|
||||||
|
local apply_log apply_rc
|
||||||
|
apply_log="$("$APPLY" 2>&1)"; apply_rc=$?
|
||||||
|
echo "$apply_log"
|
||||||
|
if [[ $apply_rc -ne 0 ]]; then
|
||||||
|
warn "apply-patches.sh failed for mod '$mod' (exit $apply_rc)"
|
||||||
|
ok=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $ok -eq 0 ]]; then
|
||||||
|
info "Reverting patches for '$mod'..."
|
||||||
|
local revert_log
|
||||||
|
revert_log="$("$REVERT" 2>&1)"
|
||||||
|
echo "$revert_log"
|
||||||
|
if echo "$revert_log" | grep -qE "could not be reverted cleanly|reported an error"; then
|
||||||
|
warn "revert-patches.sh reported an unclean revert for mod '$mod'"
|
||||||
|
ok=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $ok -eq 0 ]]; then
|
||||||
|
info "PASS: $mod"
|
||||||
|
else
|
||||||
|
warn "FAIL: $mod"
|
||||||
|
fi
|
||||||
|
echo "::endgroup::"
|
||||||
|
return $ok
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── main ──────────────────────────────────────────────────────────────────────
|
||||||
|
[[ $# -eq 1 ]] || { echo "Usage: $0 <mod>|all" >&2; exit 2; }
|
||||||
|
|
||||||
|
if ! command -v patch >/dev/null 2>&1; then
|
||||||
|
warn "'patch' command not found; install the 'patch' package."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
targets=()
|
||||||
|
if [[ "$1" == "all" ]]; then
|
||||||
|
mapfile -t targets < <(list_modules)
|
||||||
|
[[ ${#targets[@]} -gt 0 ]] || { warn "no mods found in [modules] of $MAIN_CONF"; exit 1; }
|
||||||
|
else
|
||||||
|
targets=("$1")
|
||||||
|
fi
|
||||||
|
|
||||||
|
failed=()
|
||||||
|
for mod in "${targets[@]}"; do
|
||||||
|
test_one_mod "$mod" || failed+=("$mod")
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [[ ${#failed[@]} -gt 0 ]]; then
|
||||||
|
warn "Failed mods: ${failed[*]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "All tested mods passed: ${targets[*]}"
|
||||||
|
exit 0
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# src/Scripts/test/test-syntax.sh
|
# src/scripts/test/test-syntax.sh
|
||||||
#
|
#
|
||||||
# Validates source syntax for all mod files without requiring a running system.
|
# Validates source syntax for all mod files without requiring a running system.
|
||||||
#
|
#
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
set -u
|
set -u
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
SRC_DIR="${PVE_MOD_SRC_DIR:-$(cd "$SCRIPT_DIR/../../.." && pwd)/src}"
|
SRC_DIR="${PVE_MOD_SRC_DIR:-$(cd "$SCRIPT_DIR/../../.." && pwd)/src/modules}"
|
||||||
|
|
||||||
info() { echo "[syntax] $*"; }
|
info() { echo "[syntax] $*"; }
|
||||||
warn() { echo "[syntax] WARNING: $*" >&2; }
|
warn() { echo "[syntax] WARNING: $*" >&2; }
|
||||||
Reference in new issue
Block a user