Skip to content
Open
Changes from 4 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
164 changes: 164 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,167 @@ jobs:
}
PHPEOF
php /tmp/check-uninstall.php ${{ inputs.plugin-key }}

detect-e2e-tests:
name: "Detect E2E tests"
runs-on: "ubuntu-latest"
permissions:
contents: "read"
outputs:
has-e2e-tests: "${{ steps.detect.outputs.has-e2e-tests }}"
steps:
- name: "Checkout plugin"
uses: "actions/checkout@v6"
with:
# Only fetch the `tests/e2e` tree (shallow, cone mode): we just need to
# know whether E2E specs exist, not the whole plugin source. If the
# directory is absent, the checkout still succeeds (it is simply empty)
# and the detection below reports `false`.
sparse-checkout: "tests/e2e"
- name: "Detect E2E specs"
id: "detect"
shell: "bash"
run: |
# Mirror the glob used by GLPI core's playwright.config.ts
# (`plugins/*/tests/e2e/**/*.spec.ts`): the `plugin:<key>` project only
# exists when the plugin ships E2E spec files under `tests/e2e/`.
if [[ -n "$(find tests/e2e -name '*.spec.ts' 2>/dev/null | head -n 1)" ]]; then
echo "has-e2e-tests=true" >> "$GITHUB_OUTPUT"
echo "✅ E2E specs found, Playwright tests will run."
else
echo "has-e2e-tests=false" >> "$GITHUB_OUTPUT"
echo "ℹ️ No E2E specs found, Playwright tests will be skipped."
fi

playwright:
needs: "detect-e2e-tests"
if: ${{ needs.detect-e2e-tests.outputs.has-e2e-tests == 'true' }}
permissions:
contents: "read"
name: "Playwright tests"
runs-on: "ubuntu-latest"
timeout-minutes: 60
# Same initialization as the GLPI core CI (docker-compose based), without sharding.
# GLPI core is checked out at the workspace root so that all of its
# `.github/actions/*` scripts and `docker-compose-*.yml` files are reused as-is.
# The plugin is checked out into `plugins/${{ inputs.plugin-key }}`.
#
# We cannot use the same approach as the ci job because we are required to run
# the Playwright tests in the mcr.microsoft.com/playwright container in order
# to ensure that the results are consistent with the local environment set up by the Makefile.
env:
COMPOSE_FILE: ".github/actions/docker-compose-app.yml:.github/actions/docker-compose-services.yml"
APPLICATION_ROOT: "${{ github.workspace }}"
DB_IMAGE: "githubactions-${{ inputs.db-image }}"
PHP_IMAGE: "githubactions-php-apache:${{ inputs.php-version }}"
UPDATE_FILES_ACL: true
# GLPI core branch to test the plugin against (11.0.x line).
GLPI_BRANCH: "11.0/bugfixes"
Comment thread
ccailly marked this conversation as resolved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just have a doubt about that GLPI_BRANCH var as it will mean it will be depending to this one, any way to get it from the inputs, like extracting it from inputs.glpi-version ? It should return something like 11.0.x

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11.0.x corresponds to the tag on GitHub. I don't think that's a problem?!

steps:
- name: "Set env"
run: |
echo "APP_CONTAINER_HOME=${{ runner.temp }}/app_home" >> $GITHUB_ENV
- name: "Checkout GLPI core"
uses: "actions/checkout@v6"
with:
repository: "glpi-project/glpi"
ref: "${{ env.GLPI_BRANCH }}"
# Checkout into the workspace root.
path: "."
- name: "Checkout plugin"
uses: "actions/checkout@v6"
with:
path: "plugins/${{ inputs.plugin-key }}"
- name: "Restore dependencies cache"
uses: actions/cache@v5
with:
path: |
${{ env.APP_CONTAINER_HOME }}/.composer/cache/
${{ env.APP_CONTAINER_HOME }}/.npm/_cacache/
key: "app_home_deps-8.5-${{ hashFiles('composer.lock', 'package-lock.json', 'plugins/${{ inputs.plugin-key }}/composer.lock', 'plugins/${{ inputs.plugin-key }}/package-lock.json') }}"
restore-keys: |
app_home_deps-8.5-
Comment thread
ccailly marked this conversation as resolved.
Outdated
app_home_deps-
- name: "Initialize containers"
run: |
.github/actions/init_containers-start.sh
- name: "Show versions"
run: |
.github/actions/init_show-versions.sh
- name: "Build GLPI's dependencies and translations"
run: |
docker compose exec -T app .github/actions/init_build.sh
- name: "Install plugin composer dependencies"
if: ${{ !cancelled() && hashFiles(format('plugins/{0}/composer.json', inputs.plugin-key)) != '' }}
run: |
docker compose exec -T app git config --global --add safe.directory /var/www/glpi/plugins/${{ inputs.plugin-key }}
docker compose exec -T -w /var/www/glpi/plugins/${{ inputs.plugin-key }} app composer install --ansi --no-interaction --no-progress --prefer-dist
- name: "Install plugin npm dependencies"
if: ${{ !cancelled() && hashFiles(format('plugins/{0}/package.json', inputs.plugin-key)) != '' }}
run: |
docker compose exec -T -w /var/www/glpi/plugins/${{ inputs.plugin-key }} app npm install --no-save
- name: "Build plugin assets"
# Building is plugin-specific: only run it when the plugin defines a `build`
# script in its package.json. Plugins without compiled assets just omit it.
if: ${{ !cancelled() && hashFiles(format('plugins/{0}/package.json', inputs.plugin-key)) != '' }}
run: |
if docker compose exec -T -w /var/www/glpi/plugins/${{ inputs.plugin-key }} app jq -e '.scripts.build' package.json >/dev/null 2>&1; then
docker compose exec -T -w /var/www/glpi/plugins/${{ inputs.plugin-key }} app npm run build
else
echo "ℹ️ No \"build\" script in package.json — skipping asset build."
fi
- name: "Install DB tests"
if: ${{ !cancelled() }}
run: |
docker compose exec -T app .github/actions/e2e_install.sh
- name: "Install and activate the plugin"
if: ${{ !cancelled() }}
run: |
docker compose exec -T app bin/console plugin:install --ansi --no-interaction --username=glpi --env=e2e_testing ${{ inputs.plugin-key }}
docker compose exec -T app bin/console plugin:activate --ansi --no-interaction --env=e2e_testing ${{ inputs.plugin-key }}
- name: "Type-check E2E tests"
if: ${{ !cancelled() }}
run: docker compose exec -T app npx tsc -p tsconfig.json --noEmit
- name: "Run Playwright tests"
if: ${{ !cancelled() }}
# Run the E2E tests exactly like local dev (see core `Makefile` target `playwright`):
# in the official `mcr.microsoft.com/playwright` container (browsers bundled),
# using the Playwright version pinned in GLPI core's lockfile.
run: |
docker compose exec -T app bin/console config:set url_base http://localhost:8090 --env=e2e_testing
PLAYWRIGHT_VERSION="$(docker compose exec -T app jq -r '.packages["node_modules/@playwright/test"].version' package-lock.json | tr -d '\r')"
# `--network container:glpi-test-app` shares the app container's network stack, so
# `localhost:8090` reaches GLPI's e2e server without publishing any port (the CI
# compose, unlike the local dev one, does not expose 8090 on the host).
docker run --rm --ipc=host \
-v "${{ github.workspace }}:/app" \
-w /app \
-e CI=true \
-e E2E_BASE_URL=http://localhost:8090 \
--network "container:glpi-test-app" \
"mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble" \
npx playwright test --project="plugin:${{ inputs.plugin-key }}" --reporter=html,playwright-ctrf-json-reporter,dot
- name: "Check for PHP errors"
if: ${{ !cancelled() }}
run: |
grep -v '\*\*\* Test logger' tests/e2e/glpi_files/_log/php-errors.log > /tmp/php-errors-filtered.log || true
if [[ $(wc -l < /tmp/php-errors-filtered.log) -ge 1 ]]; then
echo "PHP errors detected in log file"
echo "==============================="
cat /tmp/php-errors-filtered.log
exit 1
fi
- name: "Upload Playwright report"
Comment thread
ccailly marked this conversation as resolved.
if: ${{ !cancelled() }}
uses: "actions/upload-artifact@v7"
with:
name: "playwright-report-${{ inputs.plugin-key }}"
path: "playwright-report/"
retention-days: 30
Comment thread
ccailly marked this conversation as resolved.
if-no-files-found: ignore
- name: "Publish test summary results"
if: ${{ !cancelled() && steps.collect-reports.outputs.ctrf-exists == 'true' }}
uses: "ctrf-io/github-test-reporter@v1"
with:
report-path: "ctrf/ctrf-report.json"
collapse-large-reports: true