Files
bau-pm-pdf-tools/.gitea/workflows/ci.yml
T
magdevandClaude Opus 5.5 47138ddfbe BentoPDF for bau-pm, without third-party hosts (bau-pm BAU-119)
BentoPDF v2.8.8 built from source at its pinned commit with BentoPDF's own
air-gapped build options, every module it would load from a CDN vendored and
checked against vendor.lock, a Content-Security-Policy without a single host,
digital-sign-pdf and timestamp-pdf disabled because both need a third party,
and the hand-off glue on every page: the AGPL source link, the hand-in of a
file from bau-pm through a one-minute cookie into sessionStorage, confirmed by
the tool's reaction, the hand-back of a result from every window, and the
signing tool's flatten switch locked on.

The zero-host gate drives all 117 enabled tool pages in Chromium and fails on
any request to another origin, any CSP violation, a CSP that names a host, and
a disabled id that names no page. Green on this image (3 min 52 s on a private
network), red on the stock upstream image (115 findings) and on a misspelled
id. CI runs it on every push, the release workflow before it pushes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:36:02 +02:00

50 lines
2.0 KiB
YAML

# CI - every push to dev and every pull request: the scripts linted, the image
# built from BentoPDF's pinned commit, and the gate this repository exists for
# (README, "The gate"): a page may talk to its own origin and to nobody else.
name: CI
on:
push:
branches: [dev]
pull_request:
jobs:
gate:
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
# Over stdin: the runner passes the host's Docker socket through, so a
# mounted workspace would resolve on the host and be empty.
- name: shellcheck
run: |
for f in scripts/*.sh; do
echo "-- $f"
docker run --rm -i koalaman/shellcheck:v0.11.0 - < "$f"
done
# npm ci and the Vite build are the slow part, several minutes on the
# shared runner; the vendor stage downloads about 60 MB from npm.
- name: build the image
timeout-minutes: 60
run: docker build --build-arg VERSION="ci-${GITHUB_SHA::8}" -t bau-pm-pdf-tools:ci .
- name: build the gate
timeout-minutes: 15
run: docker build -f test/Dockerfile -t bau-pm-pdf-tools-gate:ci .
- name: gate - nothing leaves the origin
timeout-minutes: 40
run: |
net="bau-pm-pdf-tools-ci-${GITHUB_RUN_ID}"
docker network create "$net" >/dev/null
trap 'docker rm -f -v "$net-app" >/dev/null 2>&1; docker network rm "$net" >/dev/null 2>&1' EXIT
docker run -d --name "$net-app" --network "$net" --network-alias pdf-tools bau-pm-pdf-tools:ci >/dev/null
for i in $(seq 1 30); do
docker run --rm --network "$net" bau-pm-pdf-tools-gate:ci wget -q --spider http://pdf-tools:8080/ && break
[ "$i" -eq 30 ] && { echo "the image never answered" >&2; exit 1; }
sleep 2
done
docker run --rm --network "$net" bau-pm-pdf-tools-gate:ci node test/zero-hosts.mjs http://pdf-tools:8080