Follow-ups from #22: host path guards — the parts the approval left open #47
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Non-blocking findings from @thisilike's approving review of #22 (review at
f832cb2). None of these blocked the merge; all five are recorded here so they are not lost with the PR.They are independent — take them separately or in one pass.
1.
hostFs.read's loud refusal reaches the operator by an accident of call placementpin_apply.ts:59:hostPaththrows synchronously, before the promise exists, soapplyPin's read guard atpin_apply.ts:85-89— which turns an unreadable file into "not here" — never attaches. That is what makes the new drive-under-mounted-root refusal visible.Checked against the shipped code, both spellings:
The async variant is
read: async (f) => await Deno.readTextFile(hostPath(f))— a refactor with no intent behind it — and it silently converts the named refusal intono-image-line("no compose file declares an image for this service"), on the write path the refusal exists to protect.Fix: either a comment at
hostFssaying the call placement is load-bearing, or narrow the catch toDeno.errors.NotFoundso only a genuinely absent file becomes "not here". The second is the real fix.2.
envFilesis still outside the one definitioncomposeProjectreads three sets of label paths (compose_update.ts:52-70).composeEligibilityresolves and stats two of them (:96).envFilesis not resolved, not refused, not stat'd — and goes straight to the host compose CLI atcompose_update.ts:158as--env-file.The guard's own docstring is "are the project's files really there … a stack whose file moved or died must fall back to the API updater instead of failing mid-run", and a missing
--env-filefails the real update exactly the way a missing-fdoes.Pre-existing, not a regression — but sharper after #22, because the same label (
com.docker.compose.project.environment_file) now gets a dedicated normalising function inwantedEnvFilesfor the stack page while staying raw and unchecked for the invocation. The working directory was added to the loop for precisely this argument; the env files are the third leg.3.
effectiveHostRootwidens the strategy tostringhostpath.ts:113takes{ host: { strategy: string | null } }, butHostStrategy = "chroot" | "nsfile" | "pidns" | "direct"is exported from@opsdeck/sdk(sdk/mod.ts:72) and this module already imports from it.As typed, renaming a union member leaves the comparison compiling and silently always-false — and everything now rides on that one string equality.
HostStrategy | nullcovers every row the test uses and costs an import. Same trade as deletingdirfromCommitLines: make it structural.4. The new README sentence stops one clause short
OPSDECK_HOST_ROOT=/fixes the paths, and reads genuinely work after it. Anything throughctx.hoststill does not.The probe's candidates are
chroot/nsenter/nsenter/direct, and its functional test is itself ash -c(hostexec.ts:135-141), with noDeno.build.osanywhere in host-exec. Without a POSIXshonPATHthe strategy staysnullandmoduleHostExec.runthrows before spawning anything (hostexec.ts:236-238).Concretely: on a Windows checkout the stack page works, and a pin dies at
h.step("validate")(actions.ts:398, unguardedctx.host.run) with "host command execution unavailable" — honestly reported, edit rolled back by the compensator, and entirely outside #22's diff. ButREADME.md:48is now the place the Windows setup is documented, so a clause saying host-exec (compose validate, the compose updater, the pin's git commit) needs a shell onPATHwould stop the next person concluding the variable was the whole story.5. Record that the working-directory stat's failure mode is graceful
composeEligibilitystats the project working directory now — a POSIX behaviour change. A stack whoseworkingDirhas gone away but whose compose files are still present was eligible and is now not.The reasoning is right and #22's description owns the change. What is not written down anywhere is that the failure mode is graceful: the engine-API updater takes over, no run fails. Worth a line so nobody has to work that out from the diff.
Refs #20, #22.