cd0d053cdf8a7f53ee89a920eab46353797a90ed braney Mon Aug 31 15:33:37 2026 -0700 ts: drop the cookie domain so a parked instance can hold a cart, refs #37867 The shared config sets central.domain=.ucsc.edu, and cartWriteCookie puts that on the cart cookie. A parked instance answers on loopback, so the browser dropped the cookie and every request got a fresh cart. Each track then came up at its trackDb default instead of the setting the run had asked for. Nothing errored, which is what made it worth fixing rather than documenting. The page still rendered, so a scripted check measured the defaults and reported a clean pass. Clicking through a park by hand hid it completely, because hgTracks puts the hgsid into the links on its own pages; only a run that navigates by absolute URL has nothing to carry. setCookieDomain writes an empty central.domain into the frozen hg.conf, which leaves the domain attribute off the cookie and makes it host-only. That works whether the instance is reached as localhost or as 127.0.0.1, so neither the tunnel line nor any existing script has to change. HTTPHOST would not do: it uses the request's own host, and an IP address has a dot in it, so 127.0.0.1 becomes a real Domain attribute and the browser rejects that too. The login cookies follow the same setting through getCookieDomainString in wikiLink.c. It is written the way setUdcDir is, idempotent on a marker comment and called from both freeze and conf, so "ts conf NNNNN" retrofits an instance frozen before this existed. diff --git src/utils/ts/README src/utils/ts/README index 7e5c0cdb130..41ab62812a0 100644 --- src/utils/ts/README +++ src/utils/ts/README @@ -1,81 +1,94 @@ ts - ticket sandboxes ===================== ts parks a Redmine ticket as its own frozen browser instance on hgwdev. You can leave the ticket, work on something else, and return to it later. You can also give a reviewer a URL for it. refs #37867 Only the code is frozen. Each parked instance holds a full copy of your live cgi-bin-$USER and htdocs-$USER, plus a rewritten hg.conf. The MySQL databases, /gbdb, and the browser trash stay shared with the live CGIs. A private httpd, running as you, serves the copy on a loopback high port. It needs no root, no DNS, and no vhost. The one thing ts does not share is the udc cache. Each ticket gets its own directory under the shared trash, trash/udcCache/ts/NNNNN. See Notes. Two files: ts the real tool. Runs on hgwdev. ts.mac a thin wrapper for your laptop. It runs ts subcommands over ssh and opens the local ssh -L tunnel. Install it as "ts" on the laptop. Setup on hgwdev. A freeze uses a few gigabytes per ticket, so keep the parked instances on a large local pool instead of your home directory: mkdir -p /data/home/$USER/ticketSandboxes ln -s /data/home/$USER/ticketSandboxes ~/ticketSandboxes Set TS_ROOT if you want them somewhere else. Run "ts" with no arguments for the subcommand list. Typical use: ts create 37867 "some note" freeze the live sandbox and start the httpd ts sync 37867 re-freeze after more work on the live sandbox ts conf 37867 rewrite the config only, keeping the freeze ts list show every parked ticket and its status ts tunnel 37867 open the tunnel and print the browser URL ts remove 37867 stop the httpd and delete the instance Any hgwdev account can reach a parked instance, because all hgwdev users share the machine's loopback: ssh -N -L PORT:localhost:PORT you@hgwdev.gi.ucsc.edu # then open http://localhost:PORT/cgi-bin/hgTracks There is no password on a parked instance. It shows only what any hgwdev user can already build and query. Notes ----- The freeze is a full copy, not hardlinks. Hardlinks only freeze a file against replacement by rename, so an in-place edit of a live file would also change the parked copy. The CGIs read two htdocs directories. The frozen htdocs-$USER is the DocumentRoot, and the code also reads a sibling ../htdocs for files such as the URW fonts. Each parked instance keeps a symlink to the shared /usr/local/apache/htdocs for that reason. Without it, rendering fails because it cannot find a font file. udc caches remote bigData files by URL. The live sandbox and every parked ticket would otherwise read and write the same trash/udcCache tree, so a cache entry written by one instance is read by all of them. That breaks the freeze: a sparse or bad entry written by one build reappears under another. ts gives each ticket its own trash/udcCache/ts/NNNNN instead. It still lives in the shared trash, so the trash cleaner ages it out like any other udc cache, and it is still data: "ts sync" does not clear it. "ts remove" does delete it. "ts conf" adds this setting to an instance frozen before ts had it, so you do not have to re-freeze to get a private cache. +The cart cookie is written with no domain on it. The shared config sets +central.domain=.ucsc.edu, and a parked instance answers on localhost, so a +browser drops a cookie scoped to .ucsc.edu. Every request then gets a fresh +cart, and each track comes up at its trackDb default rather than the setting you +chose. Nothing errors, which is what makes this worth saying out loud: the page +still renders. Clicking through a park by hand hides the problem, because +hgTracks puts the hgsid into the links on its own pages. A script that +navigates by URL has nothing to carry, so it quietly measures the defaults and +reports a clean run. ts writes an empty central.domain into the frozen hg.conf. +That leaves the domain attribute off the cookie and makes it host-only, which +works whether you reach the instance as localhost or as 127.0.0.1. "ts conf" +adds it to an instance frozen before ts had it. + Each instance draws its ticket number faintly across the page background, so you always know which frozen browser you are viewing. ts writes that stylesheet into the frozen htdocs and sets browser.style in the frozen hg.conf. ts does not replace the tip/beta/rel Docker instances. Those reproduce an exact released environment, including the database. Write-up: https://hgwdev.gi.ucsc.edu/~braney/per-rm-sandboxes.html