This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A single Dockerfile that builds a base Docker image for testing Request Tracker (RT)
and its Perl dependencies. The image deliberately installs a "maximal" set of dependencies
(all databases, dev features, most optional features) so RT's full test suite can run against
it, and so the compiled dependency stack can be redeployed to same-distro/arch hosts without
rebuilding. It is not meant for slim production use.
There is no application code here — the deliverable is the image. README is the canonical
source for build arguments and usage; read it before changing build behavior.
- Build the image from this
Dockerfile(below) and push it to Docker Hub underbpssysadmin/rt-base-debian:<tag>. - The RT repository pulls it in: RT's own
Dockerfile(a testing-only Dockerfile at the root of the RT source tree) starts withFROM bpssysadmin/rt-base-debian:<tag>— pinned to a specific tag — adds test env vars and thert-user, then RT's GitHub Actions (.github/workflows/test-all.yml,test-oracle.yml) build RT on top of it and run the suite across SQLite / MariaDB / Postgres / Oracle and various server configs.
So a new base image only takes effect once someone bumps the pinned FROM tag in the RT
repo's Dockerfile. Building/pushing here is not enough on its own.
- Forward-only: we only move forward in time. When we adopt a newer Debian version we do not go back and update older-version branches. Old distro branches are frozen.
- One image serves both RT 5 and RT 6: the same base image is expected to run both the RT 5
and RT 6 branches, and has managed to so far. When changing dependencies, keep both in mind —
don't drop or pin something in a way that breaks the other line. (
CPANFILEdefaults to6.0-trunk, but the installed stack must still satisfy RT 5's tests.)
The primary path is the GitHub Actions workflow .github/workflows/build-push.yml
("Build and push base image", triggered manually via workflow_dispatch). It builds on
native amd64 runners and pushes to Docker Hub — so the image is always linux/amd64
regardless of the host. See README ("Building and publishing the image") for the full
hand-off procedure and the one-time Docker Hub secret setup.
Two reasons to build: refresh (run the workflow with no source change to pull the latest
Debian packages and CPAN module versions — a fresh, tested dependency snapshot) or change
(edit the Dockerfile for anything structural — new package, module pin/skip, test workaround,
new Debian release — or vary PERL_VERSION/CPANFILE/distro from the workflow inputs). The
workflow builds the committed repo, so push Dockerfile changes before dispatching (you can
dispatch from a branch to test before merging). Either way you get a new date-stamped tag.
Local builds are a fallback for reproducing a single failing step. You MUST build for
amd64 and push in one step, or a separate docker push can publish a stale wrong-arch image:
docker buildx build --platform linux/amd64 --push -t bpssysadmin/rt-base-debian:<tag> .
docker buildx imagetools inspect bpssysadmin/rt-base-debian:<tag> # confirm linux/amd64On Apple Silicon the local build runs under slow QEMU emulation.
Running the image (default CMD) prints all installed Perl modules and versions in CPAN
autobundle format — used to diff dependency sets between builds.
PERL_VERSION— Perl source release to build/test/install (e.g.5.34.3).CPANFILE— URL of RT'scpanfile; controls which RT version's deps are installed. Change6.0-trunk/stable/etc. in the URL to target a different RT version.CPM— URL of thecpminstaller script (rarely changed).PERL_CONFIGURE— options for Perl'sConfigure(default-des). Do not set-Dprefixhere.PERL_PREFIX— install path (default/opt/perl-$PERL_VERSION, symlinked to/opt/perl).
There is no single main line of development here — each branch targets a distro/variant, and that is how variants are maintained (not via build args in one branch):
stretch(repo default / origin HEAD),buster,bullseye— Debian base per branch (FROM debian:<distro>-slim).-oraclevariants add Oracle instantclient drivers.bullseye-rt6(current) — bullseye targeting RT 6.
When changing something distro- or version-specific, confirm which branch you're on and
whether the change belongs on other branches too. Diff branches (e.g. git diff stretch..bullseye-rt6)
to see how a variant diverges.
The steps run in a deliberate order; several carry non-obvious workarounds documented inline:
- System packages — build tools, Apache/fcgid, DB client libs (mariadb, libpq via the PostgreSQL APT repo), browsers (chromium, firefox-esr) and driver deps.
- Oracle instantclient — RPMs converted with
alien; setsORACLE_HOME/LD_LIBRARY_PATH. - geckodriver + Node.js/Playwright — for RT's browser/dashboard-email tests. Playwright
browsers install under
PLAYWRIGHT_BROWSERS_PATH=/tmp/playwright. - Perl from source — built, then
make testrun asnobody(non-root$<) to avoid Net::Ping raw-packet test assumptions; aseddeletes POSIX termios tests that fail under podman/runc. Installed toPERL_PREFIX, symlinked/opt/perl, put onPATH. - cpm downloaded to
/opt/perl/bin. - Individually installed modules (
XML::Simple,Mail::Sendmail,Module::Pluggable,CSS::Inliner,WWW::Mechanize::Chrome,Playwright) — each is a separateRUNbecause it needs--no-testor must be installed before the bulk step to dodge a specific test failure or parser-selection issue. The inline comments explain each; preserve them. - Bulk RT deps — downloads RT's
cpanfile, usesawkto turn eachfeature(exceptmodperl1) into a--feature=flag, and runscpm install --testfor the whole set.
Because Docker layer caching keys on RUN text and preceding layers, reordering or merging
these steps changes caching and can resurrect the test failures the current split avoids.
build_log.txt and cpanfile in the working tree are local scratch outputs, not part of the
image build (the build downloads its own cpanfile). Leave them untracked; don't commit them.