mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-28 07:37:11 +09:00
* fix(hooks): check staged blobs and fail closed in the changelog tools The pre-commit hooks read working-tree files while claiming to check staged content, check-changelog.py passed when its base diff failed, and fold-changelog.py deleted fragments it had not validated. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(tests): make CI helper scripts fail when they check nothing check_all_pages.sh passed without logging in or crawling, the sink inventory accepted ripgrep errors, install_packages.sh and copyright_year.sh lost their failures, and the LDAP spec asserted before navigation finished. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(i18n): audit only changed .po entries and keep contributor badges separate audit_po.py failed every translation PR on pre-existing errors and matched non-printf text as conversions; update-contributors.py leaked badges between aliased contributors. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs(changelog): add fragment for #8457 Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test(e2e): move the pointer off the Deepness multiselect button Deepness sets a zero body margin, so the unhovered #ms-button sits at the viewport origin and headless Chromium on Linux intermittently applies :hover to it. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: pull pinned integration database from authenticated mirror Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
204 lines
5.3 KiB
Bash
Executable File
204 lines
5.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# +-------------------------------------------------------------------------+
|
|
# | Pre-commit validation wrapper for Cacti |
|
|
# | Checks environment and dev tools before running linters. |
|
|
# +-------------------------------------------------------------------------+
|
|
set -eu
|
|
|
|
VENDOR_BIN="include/vendor/bin"
|
|
REQUIRED_PHP_MAJOR=8
|
|
MAX_PHP_MINOR=4
|
|
|
|
# ---- Environment checks (run before any tool) ----
|
|
|
|
check_php_version() {
|
|
php_ver=$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;' 2>/dev/null || echo "unknown")
|
|
major=$(echo "$php_ver" | cut -d. -f1)
|
|
minor=$(echo "$php_ver" | cut -d. -f2)
|
|
|
|
if [ "$major" != "$REQUIRED_PHP_MAJOR" ]; then
|
|
echo "WARNING: PHP $php_ver detected. Cacti requires PHP 8.x"
|
|
elif [ "$minor" -gt "$MAX_PHP_MINOR" ] 2>/dev/null; then
|
|
echo "WARNING: PHP $php_ver detected. Cacti targets PHP 8.1-8.4."
|
|
echo " Some type features (true|string) are not available on PHP 8.1."
|
|
echo " Consider: export PATH=\"/opt/homebrew/opt/php@8.4/bin:\${PATH}\""
|
|
fi
|
|
}
|
|
|
|
# Staged PHP files, one per line. Paths are read back with `read -r`, so
|
|
# spaces survive; quotePath=false keeps non-ASCII names unescaped.
|
|
staged_php_files() {
|
|
git -c core.quotePath=false diff --cached --name-only --diff-filter=ACMR -- '*.php'
|
|
}
|
|
|
|
check_merge_conflicts() {
|
|
staged=$(staged_php_files)
|
|
|
|
if [ -z "$staged" ]; then
|
|
return 0
|
|
fi
|
|
|
|
# Inspect the staged blob: a marker resolved only in the working tree is
|
|
# still committed.
|
|
conflicts=$(printf '%s\n' "$staged" | while IFS= read -r f; do
|
|
if git show ":$f" | grep -E -q '^(<<<<<<<|=======$|>>>>>>>)'; then
|
|
printf '%s\n' "$f"
|
|
fi
|
|
done)
|
|
|
|
if [ -n "$conflicts" ]; then
|
|
echo ""
|
|
echo "ERROR: Merge conflict markers found in staged files:"
|
|
echo "$conflicts"
|
|
echo " Resolve conflicts before committing."
|
|
echo ""
|
|
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_composer_lock() {
|
|
if git diff --cached --name-only | grep -q '^composer\.lock$'; then
|
|
echo ""
|
|
echo "ERROR: composer.lock is staged for commit."
|
|
echo " Cacti supports multiple PHP versions; composer.lock must not be committed."
|
|
echo " Run: git reset HEAD composer.lock"
|
|
echo ""
|
|
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_vendor_dev_deps() {
|
|
php tests/tools/check_vendor_policy.php
|
|
}
|
|
|
|
check_autoload_freshness() {
|
|
if [ ! -f include/vendor/autoload.php ]; then
|
|
echo "WARNING: your are missing the composer autoload. Please run composer install"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_tool() {
|
|
tool="$1"
|
|
label="$2"
|
|
|
|
if [ ! -x "$VENDOR_BIN/$tool" ]; then
|
|
echo ""
|
|
echo "ERROR: $label not found at $VENDOR_BIN/$tool"
|
|
echo ""
|
|
echo " Run: composer install --ignore-platform-reqs"
|
|
echo ""
|
|
echo " Dev dependencies must be installed for pre-commit hooks."
|
|
echo " This is a one-time setup after cloning or switching branches."
|
|
echo ""
|
|
|
|
exit 1
|
|
fi
|
|
|
|
# Verify the tool can actually load (catches missing Symfony/autoload issues)
|
|
if ! "$VENDOR_BIN/$tool" --version > /dev/null 2>&1; then
|
|
echo ""
|
|
echo "ERROR: $label exists but failed to load. Autoload may be stale."
|
|
echo ""
|
|
echo " Run: composer install --ignore-platform-reqs"
|
|
echo ""
|
|
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ---- Lint / analysis tools ----
|
|
|
|
# Lint the staged blobs with php -l. The previous phplint branch linted the
|
|
# working tree and its guard could never be true, so it never ran.
|
|
run_lint() {
|
|
echo "Running php -l on staged files..."
|
|
|
|
staged=$(staged_php_files)
|
|
|
|
if [ -z "$staged" ]; then
|
|
echo " No staged PHP files to check."
|
|
return 0
|
|
fi
|
|
|
|
failed=$(printf '%s\n' "$staged" | while IFS= read -r f; do
|
|
if ! git show ":$f" | php -l > /dev/null 2>&1; then
|
|
printf '%s\n' "$f"
|
|
fi
|
|
done)
|
|
|
|
if [ -n "$failed" ]; then
|
|
echo "Syntax errors in staged files:"
|
|
printf '%s\n' "$failed" | while IFS= read -r f; do
|
|
printf ' %s\n' "$f"
|
|
git show ":$f" | php -l 2>&1 || true
|
|
done
|
|
exit 1
|
|
fi
|
|
|
|
echo " All staged PHP files pass syntax check."
|
|
}
|
|
|
|
run_phpcsfixer() {
|
|
check_tool "php-cs-fixer" "PHP CS Fixer"
|
|
|
|
echo "Running PHP CS Fixer (dry-run)..."
|
|
|
|
if ! composer run-script php-cs-fixer; then
|
|
echo ""
|
|
echo "TIP: To auto-fix formatting issues, run:"
|
|
echo " composer run-script php-cs-fixit"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
run_phpstan() {
|
|
check_tool "phpstan" "PHPStan"
|
|
echo "Running PHPStan..."
|
|
composer run-script phpstan
|
|
}
|
|
|
|
# ---- Pre-flight checks (always run) ----
|
|
|
|
run_preflight() {
|
|
check_php_version
|
|
check_merge_conflicts
|
|
check_composer_lock
|
|
check_vendor_dev_deps
|
|
check_autoload_freshness
|
|
}
|
|
|
|
# ---- Main ----
|
|
|
|
case "${1:-all}" in
|
|
lint)
|
|
run_preflight
|
|
run_lint
|
|
;;
|
|
phpcsfixer)
|
|
run_preflight
|
|
run_phpcsfixer
|
|
;;
|
|
phpstan)
|
|
run_preflight
|
|
run_phpstan
|
|
;;
|
|
all)
|
|
run_preflight
|
|
run_lint
|
|
run_phpcsfixer
|
|
run_phpstan
|
|
;;
|
|
preflight)
|
|
run_preflight
|
|
echo "Pre-flight checks passed."
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {lint|phpcsfixer|phpstan|all|preflight}"
|
|
exit 1
|
|
;;
|
|
esac
|