3d98068ead92a95ea4b714f31f01119100a3c099
braney
  Wed Sep 16 10:26:18 2026 -0700
docent: preflight prints how the target is configured, refs #37892

make test TARGET=hgwdev-you points the whole directory at another server, and a
red script there can be that machine's configuration rather than a bug.  A
different curatedHubPrefix genuinely changes what a quickLift hop produces, and
a db.trackDb with a private table in front of the shared one changes what
exact: true counts.  Both failures look exactly like a bug.  The README already
warned about it, in prose, which arrives after someone has spent an hour.

make preflight now prints the settings that decide it, so a redirected run
carries its own explanation in the log:

target      https://hgwdev-braney.gi.ucsc.edu/cgi-bin
/usr/local/apache/cgi-bin-braney/hg.conf
central.db                   hgcentraltest
db.trackDb                   trackDb_braney,trackDb
curatedHubPrefix             braney
browser.quickLift            on
browser.quickLiftAlignments  on
browser.recTrackSets         on

central.db is on the list because preflight already checks named sessions and
that setting says which hgcentral it looked in.

The value printed is the EFFECTIVE one.  The reader follows include and delete
the way hg/lib/hgConfig.c does, with a later assignment winning over an earlier
one, so a sandbox conf that sets nothing still shows what it inherits from the
shared conf it includes.  Reading cgi-bin-braney/hg.conf on its own says
browser.quickLiftAlignments is unset; the CGI there sees it on, from the
include on line 2.  A ts park is the mirror case: 37547's frozen conf sets
db.trackDb twice and the second one, 114 lines later, wins.

Only the six keys in HG_CONF_KEYS are ever printed.  The includes lead to
hg.conf.private, which holds database passwords, so the reader parses whatever
it is pointed at and prints nothing off that list.

There is no way to ask a browser over http what its hg.conf says, so which file
to read is a lookup by convention: genome-test and hgwdev read
/usr/local/apache/cgi-bin/hg.conf, an hgwdev-<name> sandbox or demo reads
cgi-bin-<name>, and a ts park on 127.0.0.1 is found by port in its ports.tsv.
Anything off this machine -- hgwbeta, the RR -- says the conf cannot be read
from here, which is true and better than a guess.

Even with that in the log, a config difference and a code difference can still
look alike.  The reliable way to tell them apart is to swap only the binary:
drop a control build's CGIs into the same sandbox, leave its hg.conf alone, and
re-run.  If the failures follow the binary they are the code.  That experiment
is what turned nine plausible failures on the #37547 branch into nine proven
ones, and both READMEs now say so.

Verified against all three shapes: genome-test, hgwdev-braney, hgwdev-demo9,
and the #37547 park on 127.0.0.1:48087.  Both test directories preflight clean.

diff --git src/hg/utils/docent/tests/README.txt src/hg/utils/docent/tests/README.txt
index d4a5b3ffaa5..67494249425 100644
--- src/hg/utils/docent/tests/README.txt
+++ src/hg/utils/docent/tests/README.txt
@@ -14,30 +14,57 @@
 TARGET overrides the `target:` each script carries, for every target above, and takes
 the same values it does: a shorthand (rr, genome-test, hgwdev, hgwbeta), a bare
 hgwdev-<name> sandbox or demo, or a full .../cgi-bin URL. It is how you try a suite
 against a branch build -- a sandbox, a ticket park from `ts`, a demo browser -- without
 editing the scripts. `make preflight TARGET=...` checks that server rather than the one
 the scripts name, so the fixture check and the run agree.
 
 Read a redirected run's failures with the server in mind. A script asserts what its OWN
 server draws, so a red one somewhere else can be the other machine's trackDb rather than
 a bug: a demo sandbox that carries only one assembly fails every script on the others,
 and a sandbox trackDb with a track the RR has not released changes what `exact: true`
 counts. Redirecting is for trying a suite elsewhere, not for moving it: the committed
 scripts stay pointed at the server they were written against, which is the one the
 nightly reads.
 
+`make preflight` prints how the target is configured, so the log says which server was
+driven AND how it differs from the one the scripts name:
+
+    target      https://hgwdev-braney.gi.ucsc.edu/cgi-bin
+                /usr/local/apache/cgi-bin-braney/hg.conf
+                central.db                   hgcentraltest
+                db.trackDb                   trackDb_braney,trackDb
+                curatedHubPrefix             braney
+                browser.quickLift            on
+                browser.quickLiftAlignments  on
+                browser.recTrackSets         on
+
+Those are read off the hg.conf the server reads, following its includes the way
+hg/lib/hgConfig.c does, so the value printed is the EFFECTIVE one -- a sandbox conf that
+sets nothing still shows what it inherits from the shared conf it includes. Only a fixed
+list of settings is printed, because hg.conf includes hg.conf.private.
+
+It works for a server on this machine: genome-test, hgwdev, an hgwdev-<name> sandbox or
+demo, or a ticket park from `ts` on 127.0.0.1 (looked up by port in its registry). For
+hgwbeta or the RR it says the conf cannot be read from here, which is true and is better
+than a guess.
+
+Even with that in the log, a config difference and a code difference can still look
+alike. The reliable way to tell them apart is to swap only the BINARY: drop a control
+build's CGIs into the same sandbox, leave its hg.conf alone, and re-run. If the failures
+follow the binary they are the code.
+
 Most tests drive a real browser against a real server, so they need the network and
 the shared Playwright install (/hive/groups/browser/uiTest/pw; see ../README.md). That is why none of this is
 part of the tree-wide test target: a broken network would fail the build.
 
 A test is an ordinary Docent script that asserts with `expect:`. It passes by exiting
 0. `expect:` is the only verb that CHECKS anything, so a test with no `expect:` step in
 it tests nothing: `track:` accepts a name no assembly has and still exits 0.
 
 Other verbs do fail a run, so do not read the line above as "nothing else can stop it".
 A verb throws when it cannot do what it was told -- `mouseover:` cannot find the item,
 `loadSession:` cannot find the file, `drag:`, `convert:` and `go:` likewise -- and
 docent.js turns any step's throw into `step N (verb) failed` and exit 1. None of them
 looks at whether the page came out right, which is the part only `expect:` does.
 
 A script named *.xfail.docent.yaml is expected to FAIL, and the run fails if it passes.