ci: pin the database image and install locked shared test dependencies (#857)

* ci: pin fixtures and install locked shared test dependencies

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

* ci: fetch shared tooling through a pinned sparse checkout

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

* docs(changelog): list CI hardening as a dev entry

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

* ci: check out the Cacti branch head instead of a pinned commit

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

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
This commit is contained in:
Thomas Vincent authored and GitHub committed 2026-10-19 09:49:52 -04:00
1 parent 755004394d
commit d4917d36c0
2 files changed
+33 -25

No files matched your search

+32 -25
View File
@@ -31,12 +31,19 @@ on:
- main - main
- develop - develop
permissions:
contents: read
env: env:
CACTI: 1.2.x CACTI: 1.2.x
COMPOSER_ALLOW_SUPERUSER: 1
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs: jobs:
integration-test: integration-test:
timeout-minutes: 45
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
@@ -47,7 +54,7 @@ jobs:
services: services:
mariadb: mariadb:
image: mariadb:11.8 image: mariadb:11.8@sha256:6422478cb8e159f080fb1d8ccf65101e26fe51385787fde7d16c3b165a331f15
env: env:
MYSQL_ROOT_PASSWORD: cactiroot MYSQL_ROOT_PASSWORD: cactiroot
MYSQL_DATABASE: cacti MYSQL_DATABASE: cacti
@@ -67,6 +74,7 @@ jobs:
- name: Checkout Cacti - name: Checkout Cacti
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: with:
persist-credentials: false
repository: Cacti/cacti repository: Cacti/cacti
ref: ${{ env.CACTI }} ref: ${{ env.CACTI }}
path: cacti path: cacti
@@ -74,6 +82,7 @@ jobs:
- name: Checkout Thold Plugin - name: Checkout Thold Plugin
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: with:
persist-credentials: false
path: cacti/plugins/thold path: cacti/plugins/thold
# patch-coverage.php diffs against the base branch below. # patch-coverage.php diffs against the base branch below.
fetch-depth: 0 fetch-depth: 0
@@ -82,6 +91,7 @@ jobs:
uses: shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962 # 2.40.0 uses: shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962 # 2.40.0
with: with:
php-version: ${{ matrix.php }} php-version: ${{ matrix.php }}
tools: composer:2.10.3
extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring, snmp extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring, snmp
ini-values: "post_max_size=256M, max_execution_time=60, date.timezone=America/New_York" ini-values: "post_max_size=256M, max_execution_time=60, date.timezone=America/New_York"
coverage: xdebug coverage: xdebug
@@ -131,27 +141,24 @@ jobs:
mysql "$MYSQL_AUTH_USR" cacti < ${{ github.workspace }}/cacti/cacti.sql mysql "$MYSQL_AUTH_USR" cacti < ${{ github.workspace }}/cacti/cacti.sql
mysql "$MYSQL_AUTH_USR" -e "INSERT INTO settings (name, value) VALUES ('path_php_binary', '/usr/bin/php')" cacti mysql "$MYSQL_AUTH_USR" -e "INSERT INTO settings (name, value) VALUES ('path_php_binary', '/usr/bin/php')" cacti
- name: Validate composer files # Core's release archives exclude .github and tests. Fetch these paths
run: | # through Git at the immutable helper revision instead of an Action archive.
cd ${{ github.workspace }}/cacti - name: Checkout shared CI tooling
if [ -f composer.json ]; then uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
sudo composer validate --strict || true with:
fi repository: Cacti/cacti
ref: f3ff777992875740e4665fedfe2eff8335f5b894
persist-credentials: false
path: ci-tools
sparse-checkout: |
.github/actions/setup-plugin-dependencies
tests/tools/plugin-harness
- name: Install Composer Dependencies - name: Install locked Cacti and plugin test dependencies
run: | uses: ./ci-tools/.github/actions/setup-plugin-dependencies
cd ${{ github.workspace }}/cacti with:
if [ -f composer.json ]; then cacti-directory: cacti
sudo composer config --no-plugins allow-plugins.pestphp/pest-plugin true install-core-dev: 'false'
sudo composer require --no-progress --no-interaction "pestphp/pest: ^3" "pestphp/pest-plugin-drift: ^3.0"
sudo rm -f composer.lock
sudo composer install --dev --no-progress
fi
- name: Restore vendor ownership for Pest
run: |
cd ${{ github.workspace }}/cacti
sudo chown -R runner:runner include/vendor composer.lock
- name: Create Cacti config.php - name: Create Cacti config.php
run: | run: |
@@ -192,7 +199,7 @@ jobs:
- name: Run Pest Unit Tests - name: Run Pest Unit Tests
run: | run: |
cd ${{ github.workspace }}/cacti cd ${{ github.workspace }}/cacti
include/vendor/bin/pest --configuration=plugins/thold/phpunit.xml \ "$CACTI_PEST_BIN" --configuration=plugins/thold/phpunit.xml \
--coverage-clover=plugins/thold/coverage/clover.xml --coverage-clover=plugins/thold/coverage/clover.xml
# Whole-file coverage is meaningless here: most of the plugin only runs # Whole-file coverage is meaningless here: most of the plugin only runs
@@ -226,12 +233,12 @@ jobs:
- name: Run Linter on base code - name: Run Linter on base code
if: ${{ env.CACTI != '1.2.x' }} if: ${{ env.CACTI != '1.2.x' }}
run: sudo composer run-script lint ${{ github.workspace }}/cacti/plugins/thold run: composer run-script lint ${{ github.workspace }}/cacti/plugins/thold
working-directory: ${{ github.workspace }}/cacti working-directory: ${{ github.workspace }}/cacti
- name: Checking coding standards on base code - name: Checking coding standards on base code
if: ${{ env.CACTI != '1.2.x' }} if: ${{ env.CACTI != '1.2.x' }}
run: sudo composer run-script phpcsfixer ${{ github.workspace }}/cacti/plugins/thold run: composer run-script phpcsfixer ${{ github.workspace }}/cacti/plugins/thold
working-directory: ${{ github.workspace }}/cacti working-directory: ${{ github.workspace }}/cacti
- name: Run PHPStan at Level 6 on base code outside of Composer due to technical issues - name: Run PHPStan at Level 6 on base code outside of Composer due to technical issues
+1
View File
@@ -13,6 +13,7 @@
* dev: Remove the inert COMPOSER_ROOT_VERSION env from the Pest CI step * dev: Remove the inert COMPOSER_ROOT_VERSION env from the Pest CI step
* feature: Restyle the Thold, Host status and Log status legends as rounded, evenly-spaced solid-colour chips for a clearer, more readable status key across every theme * feature: Restyle the Thold, Host status and Log status legends as rounded, evenly-spaced solid-colour chips for a clearer, more readable status key across every theme
* dev: Keep the status-legend chips equal width (sized to the longest label) as the legend wraps responsively * dev: Keep the status-legend chips equal width (sized to the longest label) as the legend wraps responsively
* dev: Pin the CI database image and shared test dependencies, disable persisted checkout credentials, and limit workflow permissions and runtime
* security: Add a version-safe CSP nonce (`plugin_thold_csp_nonce()`) to every inline `<script>` tag so pages stay compatible with Cacti's Content-Security-Policy nonce enforcement, while falling back cleanly on older Cacti releases that lack the `CactiSecureHeaders` class * security: Add a version-safe CSP nonce (`plugin_thold_csp_nonce()`) to every inline `<script>` tag so pages stay compatible with Cacti's Content-Security-Policy nonce enforcement, while falling back cleanly on older Cacti releases that lack the `CactiSecureHeaders` class
* issue: Center-align the "Not Monitored" status cell on the Device Status page (thold_graph.php) so it matches the other status values instead of rendering right-aligned * issue: Center-align the "Not Monitored" status cell on the Device Status page (thold_graph.php) so it matches the other status values instead of rendering right-aligned
* issue: Define `plugin_thold_csp_nonce()` in thold_functions.php instead of setup.php so it is always available on plugin pages, fixing a fatal "Call to undefined function plugin_thold_csp_nonce()" that disabled the plugin when a page loaded without setup.php * issue: Define `plugin_thold_csp_nonce()` in thold_functions.php instead of setup.php so it is always available on plugin pages, fixing a fatal "Call to undefined function plugin_thold_csp_nonce()" that disabled the plugin when a page loaded without setup.php