Skip to content

chore(deps): update mariadb docker tag to v12 #53

chore(deps): update mariadb docker tag to v12

chore(deps): update mariadb docker tag to v12 #53

Workflow file for this run

# SPDX-License-Identifier: MIT
# Copyright (c) 2026 Netresearch DTT GmbH
#
# Smoke tests for the glpi-docker-compose-stack repo.
#
# Jobs:
# - image-surface → delegates buildx --load amd64 +
# container-structure-test to the netresearch/.github
# reusable smoke-test-container.yml (@main).
# - compose-up → stays inline. Builds the image locally from
# .glpi-version (with the resolved tarball sha256),
# boots the full compose stack against a generated .env,
# and asserts the stack actually serves GLPI: the login
# page returns HTTP 200 AND its body carries the
# "Authentication - GLPI" page title (proof GLPI
# rendered, not a placeholder), with app + web healthy.
# - init-idempotency → stays inline. Verifies bin/init.sh is idempotent — a
# second run must not re-roll the generated DB passwords.
# (GLPI's encryption key is minted by the app on first
# boot inside the glpi-config volume, never in .env.)
name: smoke-test
on:
pull_request:
branches: [main]
push:
branches: [main]
paths-ignore:
- 'docs/**'
- '**.md'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: smoke-test-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
image-surface:
uses: netresearch/.github/.github/workflows/smoke-test-container.yml@main
permissions:
contents: read
with:
image-tag: glpi-php-fpm:test
target: runtime
cst-config-path: tests/container-structure-test.yaml
cache-scope: smoke-test
compose-up:
name: stack serves GLPI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Resolve GLPI version + tarball sha256
id: glpi
# Same supply-chain pin the production build uses (cf. build.yml):
# hash the bundled release tarball and feed it to the build as
# GLPI_SHA256 so a swapped asset can't slip into the smoke image.
run: |
set -euo pipefail
VERSION=$(tr -d '[:space:]' < .glpi-version)
URL="https://github.com/glpi-project/glpi/releases/download/${VERSION}/glpi-${VERSION}.tgz"
SHA=$(curl -fsSL "$URL" | sha256sum | cut -d' ' -f1)
[ -n "$SHA" ] || { echo "could not hash $URL" >&2; exit 1; }
{
echo "version=$VERSION"
echo "sha256=$SHA"
} >> "$GITHUB_OUTPUT"
echo "resolved GLPI $VERSION sha256=${SHA:0:16}…"
- name: Build glpi-php-fpm:smoke (amd64) and load into docker
# compose.yml references ghcr.io/netresearch/glpi-php-fpm:${GLPI_IMAGE_TAG},
# so tag the local build :smoke and set GLPI_IMAGE_TAG=smoke in .env
# below — compose then resolves the locally-loaded image instead of
# pulling from the registry. No build secret: the GLPI image is built
# FROM the bundled release tarball (vendor/ pre-installed), so there is
# no composer step needing authenticated github.com access.
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
target: runtime
platforms: linux/amd64
load: true
tags: ghcr.io/netresearch/glpi-php-fpm:smoke
build-args: |
GLPI_VERSION=${{ steps.glpi.outputs.version }}
GLPI_SHA256=${{ steps.glpi.outputs.sha256 }}
cache-from: type=gha,scope=smoke-test
cache-to: type=gha,scope=smoke-test,mode=max
- name: Bootstrap .env (smoke image tag + random DB passwords)
env:
PORT: '8080'
run: |
set -eu
./bin/init.sh # creates .env, fills DB passwords
./bin/env-set.sh GLPI_IMAGE_TAG smoke
./bin/env-set.sh GLPI_HTTP_PORT "$PORT"
- name: Start the stack
run: docker compose up -d
- name: Assert GLPI login page is served (HTTP 200 + page title)
env:
PORT: '8080'
run: |
set -u
url="http://127.0.0.1:${PORT}/"
body="$(mktemp)"
for i in $(seq 1 72); do
# Follow `/` → login redirect; capture body + final status code.
code=$(curl -sS -L -o "$body" -w '%{http_code}' "$url" || true)
# A bare 200 is not proof on its own (nginx could be serving an
# error/placeholder page) — assert GLPI's own login-page <title>.
if [ "$code" = "200" ] && grep -q 'Authentication - GLPI' "$body"; then
echo "GLPI login page served (HTTP 200, title 'Authentication - GLPI') after $(( (i - 1) * 5 ))s"
exit 0
fi
echo "[$i] HTTP ${code:-000} — no GLPI login marker yet; retrying in 5 s"
sleep 5
done
echo "::error::GLPI never served its login page (HTTP 200 + 'Authentication - GLPI') in time"
docker compose ps
docker compose logs --tail=200
exit 1
- name: Assert GLPI routes legacy .php entry points (regression guard)
env:
PORT: '8080'
run: |
set -eu
# GLPI 11 routes /apirest.php, /front/*.php and /ajax/*.php through
# public/index.php. A blanket nginx `.php` deny would 403 these even
# though the login page at / still works (exactly the bug the serve
# check above cannot see). Assert none of them is forbidden.
rc=0
for p in /apirest.php /front/central.php /ajax/dashboard.php; do
code=$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1:${PORT}${p}" || true)
echo " ${p} -> HTTP ${code}"
if [ "$code" = "403" ] || [ "$code" = "000" ]; then
echo "::error::${p} returned ${code} — nginx is not routing a GLPI .php entry point"
rc=1
fi
done
[ "$rc" -eq 0 ] || { docker compose logs web --tail=50; exit 1; }
- name: Assert app + web report healthy
run: |
set -eu
# web depends_on `app: service_healthy`, so it only starts once app is
# healthy (~2-3 min into the GLPI install). web is then functional —
# the serve-check above already proved it — but its docker healthcheck
# (start_period 20s + interval 30s) needs a cycle to flip to "healthy".
# Poll for up to 120s instead of checking once.
deadline=$(( $(date +%s) + 120 ))
while :; do
docker compose ps
rc=0
for svc in app web; do
cid=$(docker compose ps -q "$svc")
if [ -z "$cid" ]; then echo "$svc: no container yet"; rc=1; continue; fi
health=$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$cid")
echo "$svc: $health"
[ "$health" = "healthy" ] || rc=1
done
[ "$rc" -eq 0 ] && { echo "app + web report healthy"; break; }
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "::error::app/web did not become healthy within 120s"
docker compose logs --tail=200
exit 1
fi
sleep 6
done
- name: Tear down (cleanup)
if: always()
run: docker compose down -v
init-idempotency:
name: init.sh is idempotent
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# No image build needed: bin/init.sh only writes .env (random DB
# passwords via openssl). GLPI's encryption key is minted by the app on
# first boot inside the glpi-config volume — not by init.sh — so the
# only generated secrets to check for stability are the DB passwords.
- name: First run
run: ./bin/init.sh
- name: Snapshot .env
run: cp .env .env.firstrun
- name: Second run (must not re-roll the generated DB passwords)
run: |
set -eu
./bin/init.sh
if ! diff -u .env.firstrun .env; then
echo "::error::init.sh is NOT idempotent — generated DB passwords were re-rolled"
exit 1
fi
echo "init.sh idempotent — DB passwords stable across runs"