Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 43 additions & 19 deletions .github/workflows/php-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# +-------------------------------------------------------------------------+


name: PHP Unit Tests
name: Pest Tests

on:
push:
Expand All @@ -41,7 +41,7 @@ concurrency:

jobs:
unit-test:
name: PHPUnit on PHP 8.1 (Docker)
name: Pest using Cacti Composer (Docker)
runs-on: ubuntu-latest

steps:
Expand All @@ -51,37 +51,61 @@ jobs:
# patch-coverage.php diffs against the base branch.
fetch-depth: 0

# The image is the same one developers run locally via
# `composer test:docker`, so a green run here is reproducible off-CI.
- name: Build test image
run: docker build --tag cacti-thold-test:php8.1 --file tests/docker/Dockerfile tests/docker
- name: Checkout Cacti 1.2.31 runtime
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/cacti
# Commit behind the annotated release/1.2.31 tag.
ref: 1e8eaca26b84b128c39ce8cc8ece42d7ff76aac1
path: cacti-runtime

- name: Validate composer.json
run: docker run --rm --volume "$PWD":/cacti/plugins/thold cacti-thold-test:php8.1 composer validate --strict --no-check-lock
- name: Checkout Cacti test toolchain
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Cacti/cacti
# Pin Composer, Pest, the lock file, and Cacti's Docker test image.
ref: 298bd51eca843490fb90b27ada6b3fecc9b9a7d8
path: cacti-toolchain

- name: Install dependencies
run: docker run --rm --volume "$PWD":/cacti/plugins/thold cacti-thold-test:php8.1 composer install --no-progress --no-ansi
# Build the same Linux image used by Cacti's tests/tools/docker_pest.sh.
# Composer installs and executes Cacti's locked Pest toolchain in /work;
# Thold contributes no parallel vendor directory or PHPUnit dependency.
- name: Build Cacti test image
run: |
docker build --tag cacti-web --file cacti-toolchain/docker/Dockerfile cacti-toolchain/docker
docker build --tag cacti-thold-test --file cacti-toolchain/docker/Dockerfile.test cacti-toolchain

# Same scripts a developer runs locally, and the same names Cacti core uses.
- name: Lint every PHP source file
run: docker run --rm --volume "$PWD":/cacti/plugins/thold cacti-thold-test:php8.1 composer lint
run: |
docker run --rm --volume "$PWD":/work/plugins/thold \
--env COMPOSER_ROOT_VERSION=1.3.0-dev \
--entrypoint composer cacti-thold-test \
run-script lint /work/plugins/thold

- name: Run unit tests with coverage
- name: Run Pest with coverage
run: |
docker run --rm --volume "$PWD":/cacti/plugins/thold cacti-thold-test:php8.1 \
composer test:coverage
docker run --rm \
--volume "$PWD/cacti-runtime":/cacti \
--volume "$PWD":/cacti/plugins/thold \
--env COMPOSER_ROOT_VERSION=1.3.0-dev \
--env XDEBUG_MODE=coverage \
--user root \
--entrypoint composer cacti-thold-test \
test -- --configuration=/cacti/plugins/thold/phpunit.xml \
--coverage-clover=/cacti/plugins/thold/coverage/clover.xml \
/cacti/plugins/thold/tests/Unit

# Whole-file coverage is meaningless here: most of the plugin only runs
# inside a live Cacti. What is enforceable is that a change covers the
# lines it adds.
- name: Enforce coverage of changed lines
if: github.event_name == 'pull_request'
env:
BASE_REF: origin/${{ github.base_ref }}
BASE_REF: ${{ github.event.pull_request.base.sha }}
run: |
docker run --rm --volume "$PWD":/cacti/plugins/thold --env BASE_REF \
cacti-thold-test:php8.1 \
sh -c 'git config --global --add safe.directory /cacti/plugins/thold && php tests/bin/patch-coverage.php coverage/clover.xml "$BASE_REF" 100'
docker run --rm --volume "$PWD":/plugin --workdir /plugin \
--env BASE_REF --user root --entrypoint sh cacti-thold-test \
-c 'git config --global --add safe.directory /plugin && php tests/bin/patch-coverage.php coverage/clover.xml "$BASE_REF" 100'

- name: Upload coverage report
if: always()
Expand Down
37 changes: 32 additions & 5 deletions .github/workflows/plugin-ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,21 @@ jobs:
integration-test:
runs-on: ${{ matrix.os }}

# A failure against the pinned release is a real failure. The develop entry
# is advisory: it is how a core regression becomes visible here, but it must
# not turn the plugin's own pull requests red.
continue-on-error: ${{ matrix.cacti != 'release/1.2.31' }}

strategy:
fail-fast: false
matrix:
php: ['8.1', '8.2', '8.3', '8.4']
os: [ubuntu-latest]
cacti: ['release/1.2.31']
include:
- php: '8.4'
os: ubuntu-latest
cacti: 'develop'

services:
mariadb:
Expand All @@ -57,13 +67,14 @@ jobs:
--health-timeout=5s
--health-retries=3

name: PHP ${{ matrix.php }} Integration Test on ${{ matrix.os }}
name: PHP ${{ matrix.php }} Integration Test on ${{ matrix.os }} against Cacti ${{ matrix.cacti }}

steps:
- name: Checkout Cacti
uses: actions/checkout@v7
with:
repository: Cacti/cacti
ref: ${{ matrix.cacti }}
path: cacti

- name: Checkout Thold Plugin
Expand Down Expand Up @@ -190,18 +201,34 @@ jobs:
fi

- name: Remove the plugins directory exclusion from the .phpstan.neon
run: sed '/plugins/d' -i .phpstan.neon
run: |
if [ -f .phpstan.neon ]; then
sed -i '/plugins/d' .phpstan.neon
fi
working-directory: ${{ github.workspace }}/cacti

- name: Mark composer scripts executable
run: sudo chmod +x ${{ github.workspace }}/cacti/include/vendor/bin/*
run: |
if [ -d "${{ github.workspace }}/cacti/include/vendor/bin" ]; then
sudo find "${{ github.workspace }}/cacti/include/vendor/bin" -maxdepth 1 -type f -exec chmod +x {} +
fi

- name: Run Linter on base code
run: composer run-script lint ${{ github.workspace }}/cacti/plugins/thold
run: |
if composer --no-ansi run-script --list | grep -qE '^[[:space:]]+lint([[:space:]]|$)'; then
composer run-script lint ${{ github.workspace }}/cacti/plugins/thold
else
echo 'Composer lint script is not defined; skipping.'
fi
working-directory: ${{ github.workspace }}/cacti

- name: Checking coding standards on base code
run: composer run-script phpcsfixer ${{ github.workspace }}/cacti/plugins/thold
run: |
if composer --no-ansi run-script --list | grep -qE '^[[:space:]]+phpcsfixer([[:space:]]|$)'; then
composer run-script phpcsfixer ${{ github.workspace }}/cacti/plugins/thold
else
echo 'Composer phpcsfixer script is not defined; skipping.'
fi
working-directory: ${{ github.workspace }}/cacti

# - name: Run PHPStan at Level 6 on base code outside of Composer due to technical issues
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@

locales/po/*.mo

/vendor/
/composer.lock
/.phpunit.cache/
/coverage/
/coverage/
/.phpunit.result.cache
49 changes: 0 additions & 49 deletions composer.json

This file was deleted.

5 changes: 4 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
xsi:noNamespaceSchemaLocation="/work/include/vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="tests/bootstrap-unit.php"
cacheDirectory=".phpunit.cache"
colors="true"
Expand All @@ -19,6 +19,9 @@
</testsuites>

<!--
Pest reads this PHPUnit-compatible configuration through Cacti's
Composer-managed vendor tree.

thold_functions.php is the only plugin source that loads without a
running Cacti; every other file includes ./include/auth.php and
dispatches on the request at top level.
Expand Down
1 change: 1 addition & 0 deletions tests/.cacti-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.2.31
9 changes: 7 additions & 2 deletions tests/bin/patch-coverage.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,19 @@
*/
function changed_lines($base_ref) {
$command = 'git diff --no-ext-diff --unified=0 --no-color --diff-filter=AM ' . escapeshellarg($base_ref) . '...HEAD -- "*.php"';
$diff = shell_exec($command);
$output = [];
$status = 0;

if ($diff === null) {
$last_line = exec($command, $output, $status);

if ($last_line === false || $status !== 0) {
fwrite(STDERR, "git diff failed\n");

exit(2);
}

$diff = implode("\n", $output);

$changed = [];
$file = null;

Expand Down
40 changes: 37 additions & 3 deletions tests/bootstrap-unit.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,50 @@
* a future integration suite loads real Cacti first.
*/

require_once dirname(__DIR__) . '/vendor/autoload.php';
$cacti_root = dirname(__DIR__, 3);
$autoload = $cacti_root . '/include/vendor/autoload.php';
$version = $cacti_root . '/include/cacti_version';
$expected = __DIR__ . '/.cacti-version';

if (!is_readable($autoload)) {
throw new RuntimeException("Cacti Composer autoloader is not readable: $autoload");
}

if (!is_readable($version)) {
throw new RuntimeException("Cacti version file is not readable: $version");
}

if (!is_readable($expected)) {
throw new RuntimeException("Expected Cacti version file is not readable: $expected");
}

$cacti_version = trim((string) file_get_contents($version));
$expected_version = trim((string) file_get_contents($expected));

if ($cacti_version === '') {
throw new RuntimeException("Cacti version file is empty: $version");
}

if ($expected_version === '') {
throw new RuntimeException("Expected Cacti version file is empty: $expected");
}

if ($cacti_version !== $expected_version) {
throw new RuntimeException("Expected Cacti $expected_version, found $cacti_version in $version");
}

require_once $autoload;
require_once __DIR__ . '/Helpers/CactiStubs.php';
require_once __DIR__ . '/TestCase.php';

/*
* base_path has to point at the Cacti root two levels above this plugin:
* thold_functions.php builds include paths from it at runtime.
*/
$GLOBALS['config'] = [
'base_path' => dirname(dirname(dirname(__DIR__))),
'base_path' => $cacti_root,
'url_path' => '/cacti/',
'cacti_version' => '1.2.31',
'cacti_version' => $cacti_version,
'cacti_server_os' => 'unix',
];

Expand Down
29 changes: 0 additions & 29 deletions tests/docker/Dockerfile

This file was deleted.

15 changes: 0 additions & 15 deletions tests/docker/docker-compose.yml

This file was deleted.

Loading