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
6 changes: 5 additions & 1 deletion .github/files/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ services:
image: gotenberg/gotenberg:8

mercure:
image: dunglas/mercure
# Pinned to the 0.x protocol: Mercure 1.0 (2026-09-16) only accepts OAuth 2.0 access tokens
# (typ at+jwt, iss, aud, authorization_details) and rejects the legacy `mercure`-claim JWT
# Pimcore publishes with ("invalid JWT: untrusted issuer"), which leaves every
# execution-engine job stuck in "running".
image: dunglas/mercure:v0.24
restart: unless-stopped
environment:
SERVER_NAME: ':80'
Expand Down
6 changes: 6 additions & 0 deletions .github/scripts/02-install-pimcore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ docker compose exec -T php bin/console generic-data-index:update:index -r 2>/dev
echo " [sudo] Setting ownership to match container user (DOCKER_UID:DOCKER_GID)"
sudo chown -R "${DOCKER_UID}:${DOCKER_GID}" .

# The supervisord container was started in step 1, before Pimcore was installed. Its long-running
# messenger:consume worker would otherwise keep whatever state it booted with (no schema, stale
# container cache), so restart it now that installation, cache:clear and chown are done.
echo ">>> Restarting supervisord so the messenger worker boots against the installed app..."
docker compose restart supervisord

echo ""
echo ">>> Installation complete."
echo " Pimcore UI: http://localhost:${NGINX_PORT}/pimcore-studio"
Expand Down
70 changes: 70 additions & 0 deletions .github/scripts/07-collect-logs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
#
# 07-collect-logs.sh — Save container and Pimcore logs before shutdown
#
# Used by CI (on failure, before 04-shutdown.sh) and local.
# Writes everything to <repo>/container-logs/.
#
set -euo pipefail

SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPTS_DIR}/../.." && pwd)"
FILES_DIR="${SCRIPTS_DIR}/../files"
PROJECT_PATH="${REPO_ROOT}/../test-project"
LOGS_DIR="${REPO_ROOT}/container-logs"

if [[ ! -d "$PROJECT_PATH" ]]; then
echo ">>> No project directory found at ${PROJECT_PATH}, no logs to collect."
exit 0
fi

source "${FILES_DIR}/.env"
[[ -f "${SCRIPTS_DIR}/.env.local" ]] && source "${SCRIPTS_DIR}/.env.local"

export NGINX_PORT OPENSEARCH_DASHBOARDS_PORT MAILPIT_PORT MERCURE_PORT DB_PORT
export PHP_IMAGE PHP_SUPERVISORD_IMAGE
export MYSQL_ROOT_PASSWORD MYSQL_DATABASE MYSQL_USER MYSQL_PASSWORD
export OPENSEARCH_INITIAL_ADMIN_PASSWORD
export DOCKER_UID="${DOCKER_UID:-$(id -u)}"
export DOCKER_GID="${DOCKER_GID:-$(id -g)}"

mkdir -p "$LOGS_DIR"
cd "$PROJECT_PATH"

echo ">>> Collecting container logs into ${LOGS_DIR}..."
docker compose ps --all > "${LOGS_DIR}/compose-ps.txt" 2>&1 || true
for service in $(docker compose config --services); do
docker compose logs --no-color --timestamps "$service" > "${LOGS_DIR}/${service}.log" 2>&1 || true
done

echo ">>> Collecting Pimcore var/log..."
if [[ -d var/log ]]; then
cp -r var/log "${LOGS_DIR}/var-log" || true
fi

# The artifact is downloadable from a public repository, so scrub the secret values the job
# exports before it is uploaded — GitHub only masks them in the step log, not in artifacts.
echo ">>> Redacting secrets..."
for secret_var in PIMCORE_PRODUCT_KEY PIMCORE_ENCRYPTION_SECRET PIMCORE_INSTANCE_IDENTIFIER COMPOSER_TOKEN; do
secret="${!secret_var:-}"
[[ -z "$secret" ]] && continue
# JSON log lines (Mercure, Monolog context) escape "/" as "\/", so scrub that form as well.
variants=("$secret")
json_escaped="${secret//\//\\/}"
[[ "$json_escaped" != "$secret" ]] && variants+=("$json_escaped")
for variant in "${variants[@]}"; do
SECRET="$variant" find "$LOGS_DIR" -type f -exec \
perl -pi -e 's/\Q$ENV{SECRET}\E/[REDACTED]/g' {} +
# perl -i only warns and still exits 0 when it cannot open a file, so verify the result
# instead: grep exits 1 only if every file was read and none still holds the secret.
grep_status=0
grep -rqF -- "$variant" "$LOGS_DIR" || grep_status=$?
if [[ "$grep_status" -ne 1 ]]; then
echo ">>> ${secret_var} could not be redacted from every file, refusing to keep the logs." >&2
rm -rf "$LOGS_DIR"
exit 1
fi
done
done

echo ">>> Log collection complete."
16 changes: 16 additions & 0 deletions .github/workflows/api-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ jobs:
path: tests/test-results/
retention-days: 30

- name: Collect container logs
id: collect-logs
if: failure()
env:
COMPOSER_TOKEN: ${{ secrets.COMPOSER_PIMCORE_REPO_PACKAGIST_TOKEN }}
run: bash .github/scripts/07-collect-logs.sh

- name: Upload container logs
# The artifact is public: only upload once the collector has finished redacting.
if: failure() && steps.collect-logs.outcome == 'success'
uses: actions/upload-artifact@v7
with:
name: container-logs-${{ matrix.platform }}
path: container-logs/
retention-days: 30

- name: Shutdown
if: always()
run: bash .github/scripts/04-shutdown.sh
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ Thumbs.db
/tests/playwright-report
/tests/test-results
/tests/.env

# API test log dumps (.github/scripts/07-collect-logs.sh)
/container-logs/
5 changes: 3 additions & 2 deletions doc/04_API_Testing/01_API_TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ Admin credentials: `admin` / `admin`
## Reset / shutdown

```bash
.github/scripts/05-reset.sh # fast DB reset, keeps containers
.github/scripts/06-teardown.sh # full shutdown
.github/scripts/05-reset.sh # fast DB reset, keeps containers
.github/scripts/06-teardown.sh # full shutdown
.github/scripts/07-collect-logs.sh # dump container logs + var/log to container-logs/
```

## Testing a Platform Version Before Its Release
Expand Down
Loading