Repository navigation
1.9.79: the container image ships no test suite, and its runners refuse the web - #306
Merged
Merged
Conversation
…se the web
The app stage of the Dockerfile copies the checkout into the web root, and
.dockerignore did not leave tests/ out, so every built image (the one the
Coolify and production compose stacks deploy) served the test suite. About
thirty scripts there are the child processes of integration tests and the
live passes' drivers: they act on the database their environment or their
defaults name, with no sign-in. Most stop over HTTP before acting only
because $argv is a CLI-only global; measured on php -S against a scratch
database, a GET of the schema installer's runner created 164 tables and a
GET of the ladder runner ran the upgrade.
- .dockerignore leaves tests/ out. Docker's own context transfer (a FROM
scratch stage with the app stage's COPY, exported) carried 611 PHP files
under tests/ before and none after, the app files still there. The Docker
Image workflow now checks the built image has no tests/ and that a request
for a runner is a 404.
- Every runnable script under tests/ (26 of them; tests/live/goals-ingest.php
already was) refuses any SAPI but the CLI first:
`if (PHP_SAPI !== 'cli') { http_response_code(404); exit; }`, the shape
#292's runner uses. Under the CLI nothing changes.
- TestScriptsAreNotServedTest reads every PHP file under tests/ by its
top-level statements: declarations, imports and a load of a file the
repository holds are not acts; the first other statement must be the
guard. The agent-eval router, which runs under php -S on purpose, is
listed with why. It also holds the release zip to shipping none of these
scripts, refuses another extension a host may run as PHP, requests every
guarded script over php -S (each an empty 404, a function library a 200
as the control), and reads .dockerignore as BuildKit does (checked file
for file against BuildKit on this tree and on 14 pattern shapes) to hold
tests/ out of the image's context while the files the Dockerfile copies
by name stay in.
Backlog: CR7W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRoS2SViuxaucFaKWsFnLr
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Contributor
Contributor
Brings in 1.9.79's new commits. The conflicts were in 202-config/changelogs.json, changelogs.txt, where both sides added lines: the incoming lines are kept as they are and this branch's follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VRoS2SViuxaucFaKWsFnLr
tracking202
added a commit
that referenced
this pull request
Oct 28, 2026
…ike the others #272's JVZooAdapter read 202_users_pref itself, which the branches that made AccountSecrets::stored() the one read (a deleted account owns no key) did not know of; StoredSecretsReadThroughAccountSecretsTest holds every adapter to it. Also: #323's session runner refuses a web request first (#306).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backlog: CR7W
What and why
The Dockerfile's app stage runs
COPY . /var/www/html, and.dockerignoredid not excludetests/. So every built image served the test suite from the web root, including the image the Coolify and production compose stacks deploy. About thirty scripts undertests/are integration-test child processes or live-pass drivers. Each acts on whatever database its environment or its defaults name (root with no password, databaseprosper202), with no sign-in. The same is true of any checkout served as the web root, such as the dev compose stack's bind mount or a clone on a web server.Most of these scripts stop over HTTP before they act, but only by accident:
$argvis a CLI-only global. Under a web SAPI only$_SERVER['argv']gets the query string (measured). The schema installer runner and the ladder runner read no argument, so they run. Before, measured onphp -Sagainst a scratch database:GET /tests/Install/fixtures/schema-installer-runner.phpansweredSUCCESSand created 164 tables.GET /tests/Upgrade/fixtures/ladder-runner.phpran the upgrade ladder.Changes
.dockerignorenow leavestestsout. The new lines are separate from 1.9.79: the cron job holds an flock() for the whole run #299's cron-lock line, and the trial merge applies cleanly.index.phpand notests/, and after boot a request for a runner must answer 404.tests/(26 of them) now refuses any SAPI but the CLI as its first statement afterdeclare/namespace/use.tests/live/goals-ingest.phpalready did. The guard has the same shape and answer as 1.9.79: find and move back the traffic sources the rename took before 1.9.79 #292's runner,if (PHP_SAPI !== 'cli') { http_response_code(404); exit; }. Under the CLI nothing changes.tests/Release/TestScriptsAreNotServedTest.php(new structural test):How "runnable" is decided: it reads every
.phpfile undertests/by its top-level statements, in order. These do not count as acts:declare,namespaceandusestatements;require/includewhose path is__DIR__ordirname(__DIR__[, n])plus a plain string, and stays in the repository: outsidetests/(served on its own anyway) or a.phpfile inside it (held by this same test).The first other statement must be the guard. A construct it cannot read counts as an act (the loud direction): a load from a variable, a top-level
const,return, inline HTML or a shebang, a blockdeclare. In a namespaced file, or one with a function or constant import, the guard must use\PHP_SAPIand\http_response_code.The agent-eval router is the one listed exception, with its reason: it is
php -S's router, so it runs under cli-server. A second test removes it from the list once it is guarded or gone.It holds the release zip to shipping none of these scripts (
ReleaseTree::ships()).It refuses
.phtml,.pht,.pharand.php5-style files undertests/, since a host may run them as PHP and the reading does not see them.It starts
php -Son the repository and requests every guarded script. Each must answer an empty 404. A function library answering 200 is the control.It reads
.dockerignorethe way BuildKit does and holds every file undertests/out of the context. The files the Dockerfile copies by name, and the app's entry points, must stay in.It plants 46 file shapes through a data provider.
build/README.mdupdated.How the release zip leaves tests/ out
build/release-manifest.phpdoes it withkeep_only:testskeeps onlyfixtures, andtests/fixtureskeeps onlyagent-evalandapp-sdk-contract. It also usesexclude_nestedfortests/fixtures/agent-eval/ci, where the router lives. So the zip ships no PHP fromtests/. The new test now holds that.Dockerfile
No stage uses
tests/. The onlyCOPYsources from the context arecomposer.json,build/scripts/docker-entrypoint.shand.. Composer'sautoload-dev(Tests\→tests/) is dropped bydump-autoload --no-dev, and no runtime code readstests/.Verification
Ladder (
verify.sh --since origin/1.9.79 --changed, with actionlint 1.7.12, CI's pinned version, on PATH):The unit tier ran 6,156 tests with 4 skipped, the documented "User class requires DB singleton" skips. PHP is 8.3.6, as in CI.
php -Son port 8151, serving the worktree, withP202_TEST_DB_*naming a scratch MariaDB 10.11 database):false), and the database still had 0 tables.202-config.phpwas needed.dockerdand used aFROM scratchstage with the app stage'sCOPY . /var/www/html, exported with--output type=local:.dockerignore,tests/reached the docroot: 611 PHP files,schema-installer-runner.phpamong them, 2,621 files in all.tests/is absent andindex.php,202-config/connect.phpandbuild/scripts/docker-entrypoint.share present, 1,892 files in all..dockerignorereading matches BuildKit file for file on both: 0 differences either way. It also matches on 14 pattern shapes (negation,*,**,?, a leading/or./, comments and padding) on a synthetic context.cmp. Each fails the test it targets:exit, or usingphp_sapi_name();tests/live, and a PHPUnit case that acts at file scope;.phtmlfile undertests/, and the router guarded;.dockerignorewithouttests, re-includingtests/fixtures, naming onlytests/*/fixtures, or leaving out everything, and aDockerfile.dockerignoreplaced beside the Dockerfile;tests/Attributionoragent-eval/ci;tests/run-integration-suites.sh(CI's runner, one fresh database per suite,p202_cr7w_test) passed 145 of 146 suites, 1,365 tests. All 29 suites that spawn a runner I touched passed. The one failure isMysqlLookupRepositoriesIntegrationTest::testTheFactoryCachesThroughTheBootstrapHelpers, and it is environmental: this PHP has nomemcachedextension, and the test extends\Memcached.ClickPathUncaughtTest,TrackerPlaceholdersReadTheClickOnlyWhenAskedTest,FallbackRedirectScriptsTest,IntegrationSuiteSelectionTest,SourceScanTestandReleaseTreeTest.tests/live/schema-diff.phpfrom the CLI behaves as before: 0 differences on identical databases, refusing an empty one, and usage with exit 2.1.9.79-ts-taken-before-fix, this test passes and reads 1.9.79: find and move back the traffic sources the rename took before 1.9.79 #292'straffic-source-repair-runner.phpas guarded, unchanged. 1.9.79: find and move back the traffic sources the rename took before 1.9.79 #292's ownTrafficSourceRepairRunnerIsNotServedTestalso passes there.Not run
php:8.3.36-apacheor run its apt, pecl and composer steps through the TLS-intercepting proxy without changing the Dockerfile. The Docker Image workflow runs on this PR, because.dockerignorechanged, with the two new checks.upgrade-equals-install.sh, which drivesschema-diff.phpand the router. Both are covered above in isolation.For the reviewer
tests/, while the zip keeps two fixture trees: the SDK contract vectors and the eval cases the CLI help names. Nothing in the server reads them, so the image doesn't need them.DollarFormatTest,MobileAppsRegistrationTestandHtmlReportFormatterTest, whichrequire_oncean app function file at file scope. A guard'sexitin a file PHPUnit loads in-process would silently end a run under a SAPI other than the CLI, such as phpdbg.Generated by Claude Code