Files
cacti/.github/workflows/syntax.yml
Thomas Vincent 79a9ae0351 build: raise the 1.3 floor to PHP 8.3 (#7939)
* build: raise the 1.3 floor to PHP 8.3

RHEL 10 ships 8.3 in AppStream and dropped modularity, so an 8.4 floor would
put every RHEL, Alma and Rocky 10 install on Remi. Ubuntu 24.04 is 8.3 as
well, which makes it the lowest common denominator of the current LTS fleet.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs: raise the documented PHP floor to 8.3

The 1.2.x column keeps 8.1, which still matches that branch's composer constraint.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* ci: run process lock coverage on PHP 8.3

* fix: finish PHP 8.3 floor cleanup

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
2026-09-06 08:44:40 -07:00

541 lines
19 KiB
YAML

# +-------------------------------------------------------------------------+
# | Copyright (C) 2004-2026 The Cacti Group |
# | |
# | This program is free software; you can redistribute it and/or |
# | modify it under the terms of the GNU General Public License |
# | as published by the Free Software Foundation; either version 2 |
# | of the License, or (at your option) any later version. |
# | |
# | This program is distributed in the hope that it will be useful, |
# | but WITHOUT ANY WARRANTY; without even the implied warranty of |
# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# | GNU General Public License for more details. |
# +-------------------------------------------------------------------------+
# | Cacti: The Complete RRDtool-based Graphing Solution |
# +-------------------------------------------------------------------------+
# | This code is designed, written, and maintained by the Cacti Group. See |
# | about.php and/or the AUTHORS file for specific developer information. |
# +-------------------------------------------------------------------------+
# | http://www.cacti.net/ |
# +-------------------------------------------------------------------------+
name: Cacti Commit Audit
on:
push:
branches: [develop, '1.2.x']
pull_request:
branches: [develop, '1.2.x']
merge_group:
permissions:
contents: read
concurrency:
group: build-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
"COMPOSER_ALLOW_SUPERUSER": 1
jobs:
javascript-contracts:
name: JavaScript contracts
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Install Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: '22'
- name: Install managed JavaScript and test contracts
run: |
set -euo pipefail
npm ci
npm test
npm run test:coverage
# spelling:
# name: Spell Check
# runs-on: ubuntu-latest
# steps:
# - name: Checkout
# uses: actions/checkout@v7.0.0
# - name: Install codespell
# run: pip install codespell==2.4.1
# - name: Run codespell
# run: codespell --config .codespell.cfg
runtime-compatibility:
name: PHP ${{ matrix.php }} locked runtime
runs-on: ubuntu-24.04
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
php: ['8.3', '8.4', '8.5']
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Setup locked PHP dependencies
uses: ./.github/actions/setup-php-composer
with:
php-version: ${{ matrix.php }}
extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring
coverage: none
dependency-mode: locked-runtime
install-args: --no-dev --prefer-dist --no-progress --no-interaction
- name: Verify actual platform requirements
run: composer check-platform-reqs --no-dev
- name: Smoke-test the production autoloader
run: php -r "require 'include/vendor/autoload.php';"
native-dependencies:
name: PHP ${{ matrix.php }} native dependencies
runs-on: ubuntu-24.04
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
php: ['8.3', '8.4', '8.5']
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: '22'
cache: npm
- name: Build managed JavaScript
run: npm ci
- name: Setup native PHP dependencies
uses: ./.github/actions/setup-php-composer
with:
php-version: ${{ matrix.php }}
extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring
coverage: none
dependency-mode: native
cache-dependency-path: composer.json
- name: Create native compatibility definition
run: |
set -euo pipefail
cp composer.json composer.compat.json
COMPOSER=composer.compat.json composer config platform.php "${{ matrix.php }}"
- name: Resolve native dependencies
env:
COMPOSER: composer.compat.json
run: composer update --prefer-dist --no-progress --no-interaction
- name: Run unit tests
run: include/vendor/bin/pest --display-warnings --testsuite=Unit
check:
runs-on: ubuntu-24.04
timeout-minutes: 60
services:
mysql:
image: mariadb:10.6@sha256:2fdc84794931c0abde9ba6a8c9cb5a4635a02d851a103f0301a8b606dfc5cd98
env:
MYSQL_DATABASE: cacti
MYSQL_HOST: 127.0.0.1
MYSQL_USER: cactiuser
MYSQL_PASSWORD: cactiuser
MYSQL_ROOT_PASSWORD: cactiroot
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
name: PHP 8.3 locked integration
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: '22'
cache: npm
- name: Build managed JavaScript
run: npm ci
- name: Setup locked PHP 8.3 dependencies
uses: ./.github/actions/setup-php-composer
with:
php-version: '8.3'
extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring
ini-values: post_max_size=256M, max_execution_time=60, date.timezone=America/New_York
coverage: none
dependency-mode: locked-quality
install-args: --prefer-dist --no-progress --no-interaction
- name: Check PHP version
run: php -v
- name: Prime fontconfig's cache
run: sudo fc-cache
- name: Validate composer.json and composer.lock
run: composer validate --strict
- name: Verify actual platform requirements
run: composer check-platform-reqs
- name: Run Linter on base code
run: composer run-script lint
working-directory: .
- name: Run hardening pattern guard
if: github.event_name == 'pull_request'
run: composer run-script hardening-patterns -- --base="${{ github.event.pull_request.base.sha }}" --head=HEAD
working-directory: .
- name: Reject committed Composer dependencies
run: composer run-script vendor-policy
working-directory: .
- name: Checking coding standards on base code
run: composer run-script phpcsfixer
working-directory: .
- name: Run PHPStan at Level 6 on base code
run: composer run-script phpstan
working-directory: .
- name: Run Pest Unit Tests
run: composer run-script test
working-directory: .
- name: Checkout Thold Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_thold
ref: 34c4a69b752b8eb0d73e90f1cd1c2a9b317a9d1b
path: plugins/thold
persist-credentials: false
- name: Checkout Monitor Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_monitor
ref: 11c7b6c6422d7ffaba9c2dcac25b729d9cb6ff12
path: plugins/monitor
persist-credentials: false
- name: Checkout MacTrack Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_mactrack
ref: 408adb447cbb7b4ef4360bade646b8d926f7b293
path: plugins/mactrack
persist-credentials: false
- name: Checkout Intropage Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_intropage
ref: f3a00ff7fb4a7f0c26b8910cd32c5c98e45da1e9
path: plugins/intropage
persist-credentials: false
- name: Checkout FlowView Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_flowview
ref: ee37c8938c99bc49f6a2933f373865c65f51fba0
path: plugins/flowview
persist-credentials: false
- name: Checkout Audit Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_audit
ref: 1d7be4f422a3831dcaa150747ad7314168b60605
path: plugins/audit
persist-credentials: false
- name: Checkout Syslog Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/plugin_syslog
ref: 82df21ba2acf38ec4052aa862d2b53c67287f311
path: plugins/syslog
persist-credentials: false
- name: Enable Syslog batch installation
run: |
set -euo pipefail
# With syslog we have to enable batch installs using the lines below
cd ${{ github.workspace }}/plugins/syslog
cp -p config.php.dist config.php
# shellcheck disable=SC2016
sed -i 's/\/\/\$syslog_install_options/\$syslog_install_options/g' config.php
- name: Move plugin config files
run: |
set -euo pipefail
cp -p ${{ github.workspace }}/plugins/flowview/config.php.dist ${{ github.workspace }}/plugins/flowview/config.php
cp -p ${{ github.workspace }}/plugins/syslog/config.php.dist ${{ github.workspace }}/plugins/syslog/config.php
sed -i 's/\/\/\$/\$/g' ${{ github.workspace }}/plugins/syslog/config.php
- name: Run apt-get update
run: sudo apt-get -y update
- name: Install Apache and Tools
run: sudo apt-get install apache2 snmp snmpd rrdtool fping libapache2-mod-php
- name: Start SNMPD Agent and Test Agent
run: |
set -euo pipefail
sudo systemctl start snmpd
sudo snmpwalk -c public -v2c -On localhost .1.3.6.1.2.1.1
- name: Link Web Root and Grant the Web Group Access
run: |
set -euo pipefail
sudo ln -s /home/runner/work/cacti/cacti /var/www/html
sudo chgrp -R www-data "${{ github.workspace }}"
sudo find "${{ github.workspace }}" -type d -exec chmod g+rwx {} +
sudo find "${{ github.workspace }}" -type f -exec chmod g+rw {} +
sudo chmod o+x /home
sudo chmod o+x /home/runner
sudo chmod o+x /home/runner/work
sudo chmod o+x /home/runner/work/cacti
sudo chmod o+x /home/runner/work/cacti/cacti
- name: Configure Apache Site
run: |
set -euo pipefail
cp ${{ github.workspace }}/tests/tools/cacti.conf /tmp/cacti.conf
sed -i "s#GITHUB_WORKSPACE#${{ github.workspace }}#g" /tmp/cacti.conf
sudo cp /tmp/cacti.conf /etc/apache2/sites-available/000-default.conf
- name: Restart Apache2
run: sudo systemctl restart apache2
- name: Create and Initialize Database
run: |
set -euo pipefail
mysql_config="$RUNNER_TEMP/mysql-client.cnf"
install -m 0600 /dev/null "$mysql_config"
printf '%s\n' \
'[client]' \
'user = root' \
'password = cactiroot' \
'host = 127.0.0.1' \
'max_allowed_packet = 500000000' > "$mysql_config"
mysql_args=(--defaults-extra-file="$mysql_config")
mysql "${mysql_args[@]}" -e "CREATE DATABASE IF NOT EXISTS cacti;"
mysql "${mysql_args[@]}" -e "CREATE USER 'cactiuser'@'localhost' IDENTIFIED BY 'cactiuser';"
mysql "${mysql_args[@]}" -e "GRANT ALL PRIVILEGES ON cacti.* TO 'cactiuser'@'localhost';"
mysql "${mysql_args[@]}" -e "FLUSH PRIVILEGES;"
mysql "${mysql_args[@]}" -e "SET GLOBAL max_allowed_packet=500000000;"
mysql "${mysql_args[@]}" cacti < "${{ github.workspace }}/cacti.sql"
mysql "${mysql_args[@]}" -e "INSERT INTO settings (name, value) VALUES ('path_php_binary', '/bin/php')" cacti
- name: Prime Cacti config.php File
run: |
set -euo pipefail
sudo install -o runner -g www-data -m 0660 \
${{ github.workspace }}/include/config.php.dist \
${{ github.workspace }}/include/config.php
sudo sed -i "s/localhost/127.0.0.1/g" ${{ github.workspace }}/include/config.php
- name: Setup Cacti Daemon
run: |
set -euo pipefail
sudo cp ${{ github.workspace }}/tests/tools/cactid.service /etc/systemd/system/cactid.service
sudo sed -i 's/apache/www-data/g' /etc/systemd/system/cactid.service
sudo systemctl enable cactid
sudo systemctl start cactid
for _ in {1..15}; do
if systemctl is-active --quiet cactid; then
break
fi
sleep 1
done
if ! systemctl is-active --quiet cactid; then
sudo systemctl status --no-pager cactid || true
sudo journalctl --no-pager -xeu cactid.service || true
echo "Cacti daemon failed to become active"
exit 1
fi
- name: Check install code for validity
run: php -q tests/tools/check_install_code.php
- name: Check All Resource XML File Syntax
run: php tests/tools/check_xml_syntax.php
- name: Check Poller Script Syntax after Package Import
run: find scripts -name '*.php' -print0 | xargs -0 -n1 php -l
- name: Check that all CLI scripts have a valid --version flag
run: sudo -u www-data -- bash tests/tools/check_cli_version.sh
- name: Install Cacti through the CLI
run: sudo -u www-data -- php cli/install_cacti.php --accept-eula --install --force
- name: Verify Installer Postconditions
run: |
set -euo pipefail
cd ${{ github.workspace }}
mysql_config="$RUNNER_TEMP/mysql-client.cnf"
mysql_args=(--defaults-extra-file="$mysql_config")
expected_tables=$(grep -c '^CREATE TABLE' cacti.sql)
actual_tables=$(mysql "${mysql_args[@]}" cacti --batch --skip-column-names -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()")
installed_version=$(mysql "${mysql_args[@]}" cacti --batch --skip-column-names -e "SELECT cacti FROM version")
host_templates=$(mysql "${mysql_args[@]}" cacti --batch --skip-column-names -e "SELECT COUNT(*) FROM host_template")
test "$actual_tables" -eq "$expected_tables"
test "$installed_version" != "new_install"
test "$host_templates" -gt 0
- name: Install Cacti Packages through CLI
run: sudo -u www-data -- bash tests/tools/install_packages.sh
- name: Check All Resource XML File Syntax Post Package Install
run: php tests/tools/check_xml_syntax.php
- name: Check all perl scripts for syntax errors
run: find scripts -name '*.pl' -print0 | xargs -0 -n1 perl -c
- name: Audit the Installation Schema
run: sudo -u www-data -- php cli/audit_database.php --report
- name: Install and Enable Plugins
run: sudo -u www-data -- php cli/plugin_manage.php --plugin=thold --plugin=intropage --plugin=monitor --plugin=mactrack --plugin=audit --plugin=flowview --plugin=syslog --install --enable --allperms
- name: Add Device for Moc Test, Check CLI scripts for Errors
run: |
set -euo pipefail
sudo -u www-data -- php cli/add_device.php --description=test_device --ip=127.0.0.1 --template=25
sudo -u www-data -- php cli/rebuild_poller_cache.php --debug
sudo -u www-data -- php cli/poller_reindex_hosts.php --id=all --debug
- name: Run Cacti poller
run: |
set -euo pipefail
sudo -u www-data -- php poller.php --poller=1 --force --debug
grep -q "SYSTEM STATS" log/cacti.log
# The recursive crawl walks the whole authenticated UI one request at a
# time and is the single most expensive step in CI. Nothing it exercises can
# change unless server-rendered code, assets or the schema changed, so skip
# it when a pull request touches only tests, workflows or documentation.
- name: Decide whether the page crawl can affect this change
id: crawl_scope
run: |
set -euo pipefail
if [[ "${{ github.event_name }}" != 'pull_request' ]]; then
echo 'required=true' >> "$GITHUB_OUTPUT"
exit 0
fi
base='${{ github.event.pull_request.base.sha }}'
# Fail open: if the diff cannot be read, run the crawl.
if ! changed=$(git diff --name-only "$base" HEAD 2>/dev/null); then
echo 'required=true' >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ -z "$changed" ]]; then
echo 'required=true' >> "$GITHUB_OUTPUT"
exit 0
fi
if printf '%s\n' "$changed" | grep -qvE '^(tests/|\.github/|docs/|locales/|CHANGELOG|changelog\.d/|.*\.md$)'; then
echo 'required=true' >> "$GITHUB_OUTPUT"
else
echo 'required=false' >> "$GITHUB_OUTPUT"
echo "Only tests, workflows or documentation changed; skipping the page crawl."
fi
- name: Check All Pages Using Recursive wget
if: steps.crawl_scope.outputs.required == 'true'
run: |
set -euo pipefail
install -m 0600 /dev/null .my.cnf
printf '%s\n' \
'[client]' \
'user = root' \
'password = cactiroot' \
'host = 127.0.0.1' > .my.cnf
sudo tests/tools/check_all_pages.sh -vmstat 10 -ps 10
- name: View Cacti log on failure
if: failure()
run: |
set -euo pipefail
log_file=${{ github.workspace }}/log/cacti.log
if [[ -f "$log_file" ]]; then
cat "$log_file"
else
echo "Cacti log was not created"
fi
changelog:
name: CHANGELOG format
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Validate CHANGELOG ordering and entry format
run: python3 .github/scripts/check-changelog.py
required:
name: CI / required
if: always()
needs: [runtime-compatibility, native-dependencies, check, changelog]
runs-on: ubuntu-slim
timeout-minutes: 5
steps:
- name: Verify required jobs
env:
RUNTIME_RESULT: ${{ needs.runtime-compatibility.result }}
NATIVE_RESULT: ${{ needs.native-dependencies.result }}
INTEGRATION_RESULT: ${{ needs.check.result }}
CHANGELOG_RESULT: ${{ needs.changelog.result }}
run: |
set -euo pipefail
for result in \
"$RUNTIME_RESULT" \
"$NATIVE_RESULT" \
"$INTEGRATION_RESULT" \
"$CHANGELOG_RESULT"; do
test "$result" = success
done