9b762c146f7a44a3bdc783cdd202356fc163b8fb
braney
  Wed Sep 16 12:43:32 2026 -0700
docent: one targetConf.js for the target, the hg.conf, the central and the account, refs #37892

docent.js and tests/preflight.js had grown a second and then a third copy of the
same lookups.  That is exactly the pair that must not drift: preflight checks the
fixtures for the server the RUN will drive, so a run that resolved its target, its
hg.conf, its hgcentral or its account even slightly differently would be checked
against the wrong machine, and the mismatch would show up as a green preflight in
front of a red suite.

targetConf.js answers the four questions in order, each from the one before:

resolveTarget   a `target:` (or DOCENT_TARGET) -> the .../cgi-bin URL to drive
hgConfFor       that URL -> the hg.conf it reads, if the server is on this box
centralDbFor    that conf -> which hgcentral it uses
loginLookup     that central -> the account to sign in with

Nothing in it opens a browser or the network, which is why preflight can ask all
four in the seconds before a run.

loginLookup returns the facts plus, when the account cannot be used, ONE sentence
saying why.  That sentence is the substantive half and is now written once: the
step throws it with a `login:` prefix, preflight prints it on the MISSING line.
Each caller still phrases its own success line, since one logs and the other
prints a fixture row.  No password crosses that boundary to anything that prints.

248 lines net out of the two programs, 197 into the module.

docent.js is no longer a single file, and three places now say so: its own require,
the Run section of README.md, and docent.mk, whose mp4 rule gains targetConf.js as
a prerequisite -- a change there changes what a tour renders, so it has to rebuild
one.  Nothing in the tree or in ~/docentTours copies docent.js; they all reference
it where it sits, with targetConf.js beside it.

Measured before and after, with no other change: preflight resolves the same
account, central and conf for genome-test, hgwdev-braney, a ts park on 48087 and
hgwbeta (which correctly has no section); tests/ is 18 of 18 with the derive
baselines matching; tests/regress preflights 14 fixtures for 67 scripts.

diff --git src/hg/utils/docent/docent.mk src/hg/utils/docent/docent.mk
index d7be259d845..ee182c9c357 100644
--- src/hg/utils/docent/docent.mk
+++ src/hg/utils/docent/docent.mk
@@ -12,52 +12,55 @@
 #
 # then:
 #
 #     make            # build every mp4 whose script (or docent.js) changed
 #     make AP1        # build just ../AP1.mp4 (if stale)
 #     make -B AP2     # force a rebuild
 #     make FAST=1 BP1 # figures only, no video -- roughly a third of the wall clock
 #     make -j6        # scenarios in parallel (each run gets its own browser + cart)
 #     make list       # list the base names discovered
 #     make clean      # remove generated mp4s and stills/
 #
 # Override before the include: FIGDIR (where mp4s land, default ..), PW_ENV (the
 # Playwright runtime), SCRIPTS/BASES (to build an explicit subset).
 
 DOCENT  ?= $(HOME)/kent/src/hg/utils/docent/docent.js
+# docent.js requires targetConf.js from beside it (target, hg.conf, hgcentral, account),
+# so a change there changes what a tour renders and has to rebuild one too.
+DOCENTDEPS ?= $(DOCENT) $(dir $(DOCENT))targetConf.js
 SCRIPTS ?= $(wildcard *.docent.yaml)
 BASES   ?= $(SCRIPTS:.docent.yaml=)
 FIGDIR  ?= ..
 MP4S    := $(addprefix $(FIGDIR)/,$(addsuffix .mp4,$(BASES)))
 
 # Shared Playwright/Chromium install. Anywhere you have playwright + js-yaml works;
 # at UCSC this is /hive/groups/browser/uiTest/pw, one pinned copy for every
 # browser-driving test in the tree (see its README.md for the pin). Override
 # PW_ENV to point at a private install.
 PW_DIR  ?= /hive/groups/browser/uiTest/pw
 PW_ENV  ?= PLAYWRIGHT_BROWSERS_PATH=$(PW_DIR)/browsers NODE_PATH=$(PW_DIR)/node_modules
 
 # FAST=1 -> figures only: no dwells, no cursor animation, no screen recording, no mp4.
 # Same stills, about a third of the wall clock. Use it while iterating on figure content;
 # drop it for the final build that has to produce the videos.
 FAST_ENV = $(if $(FAST),DOCENT_FAST=1 ,)
 
 .PHONY: all list clean hires $(BASES)
 
 all: $(MP4S)
 
-$(FIGDIR)/%.mp4: %.docent.yaml $(DOCENT)
+$(FIGDIR)/%.mp4: %.docent.yaml $(DOCENTDEPS)
 	$(FAST_ENV)$(PW_ENV) node $(DOCENT) $<
 
 # hires: the same tours rendered for print -- SCALE times the pixels (a wider server image
 # drawn with a bigger track font, the HTML zoomed to match), stills only, written to their
 # own tree so the screen stills and the videos are left alone. Always a full rebuild: a
 # print run is rare and cheap to ask for exactly when it is wanted. Its `session:` files go
 # to their own tree too: a print run's cart carries pix=2550 and textSize=24, which is not
 # the state anyone wants handed to them.
 #
 #   make hires                     # every scenario at 3x -> stills.hires/<base>/
 #   make hires SCALE=2             # 2x
 #   make hires BASES=BP1           # one scenario
 #
 SCALE ?= 3
 HIRES ?= stills.hires