ci: add Adobe 2023 smoke legs so the #3029 failure class is PR-gated - #3051
Conversation
smoke-env.yml gains a smoke-adobe job (production/testing matrix) that boots the compat-matrix adobe2023 Docker engine with config/environment.cfm sed'd to the matrix environment before container start and runs the engine-agnostic probes in tools/ci/smoke-env.sh against http://localhost:62023. Design notes: - compat-matrix.yml runs weekly/manual only, so bolting the probes there would not make a regressing PR red; the PR-gated smoke-env.yml is the honest home. Cost measured on compat-matrix run 27081098861: the adobe2023 docker compose build is ~90s and the engine serves in ~4 min, so each leg lands around 6-7 minutes of parallel runner time, behind the same paths filter as the Lucee legs (plus compose.yml and tools/docker/adobe2023/**). - No database containers: the probes never query the datasource, and the bind-mounted harness settings.cfm is sed'd from wheelstestdb_sqlserver to wheelstestdb_sqlite (driver jar ships in tools/docker/adobe2023/lib/, DB files created at the repo root behind the bind mount). - Both seds run before docker compose up so the app cold-boots straight into the matrix environment; readiness loop adapted from compat-matrix (crash-restart, 200/302/404 accepted, last-HTTP-code diagnostics). - The harness settings.cfm reloadPassword is empty, which blocks reload (ReloadPasswordSpec), so the reload-refusal probes hold. - tools/ci/smoke-env.sh is unchanged (already engine-agnostic via BASE_URL). Probe behavior on Adobe was hand-verified green for both environments in PR #3044 (transcripts in its body) against wheels-test-adobe2023:v1.0.1, including red-verification on the pre-fix tree reproducing the #3029 500s. Fixes #3047. Refs #3029. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Peter Amiri <peter@alurium.com>
Signed-off-by: Peter Amiri <peter@alurium.com> # Conflicts: # .github/workflows/smoke-env.yml
There was a problem hiding this comment.
Wheels Bot — Reviewer
TL;DR: This PR adds the Adobe 2023 smoke legs (#3047) that PR-gate the #3029 failure class, and the job design is sound — every sed pattern, the readiness loop, the container-name assumption, and the SQLite recipe all verify against the repo, and probes 1–5 pass on both legs. But the verdict is request changes: both new legs went red on this PR's own CI because probe 6 (reload-authorized-restarts) gets HTTP 500 instead of 302 on Adobe 2023 in both environments. The probe found a real, pre-existing Adobe-only framework bug in the authorized-reload path — exactly what the leg exists to catch — but the PR cannot merge with its own gate red, since every subsequent PR touching the filtered paths would inherit two failing checks. Either land a fix for the underlying bug first, or disengage probe 6 on the Adobe legs with a tracked follow-up.
Correctness
1. Both Adobe legs fail probe 6 on this PR's own run (blocking).
Run 27394436934, jobs Smoke: production (Adobe 2023) and Smoke: testing (Adobe 2023):
PASS probe=root (404, clean)
PASS probe=wheels-info-clean-404 (404)
PASS probe=unknown-route-404 (404)
PASS probe=reload-unauthenticated-refused (404)
PASS probe=reload-wrong-password-refused (404)
FAIL probe=reload-authorized-restarts url=http://localhost:62023/?reload=true&*** (expected 302, got 500)
Root cause (from the job's own Debug container logs step, timestamped to the probe-6 request):
Error [XNIO-1 task-2] - Could not find the ColdFusion component or interface application.
... The specific sequence of files included or processed is: /wheels-test-suite/public/index.cfm, line: 320
Line 320 is vendor/wheels/Global.cfc:320 — cfinvoke(attributeCollection = "#local.args#") inside $invoke(). The reload gate in public/Application.cfc:284-285 invokes the restart through the lock path:
local.executeArgs = {"componentReference" = "application"};
application.wo.$simpleLock(name = local.lockName, execute = "$handleRestartAppRequest", type = "exclusive", timeout = 180, executeArgs = local.executeArgs);$invoke() (vendor/wheels/Global.cfc:289-324) turns that string into cfinvoke component="application". Lucee resolves the string; Adobe treats it as a CFC path lookup, fails to find a component named application, and 500s before $handleRestartAppRequest() ever runs (which is why the probe sees 500, not 302 — applicationStop() never executes). Probes 4/5 passing prove the password gate itself is fine; this is not a job-configuration error. The same string-"application" idiom also sits in public/Application.cfc:165-167 (onSessionStart's shared-app-name recovery path), so the latent Adobe exposure is wider than the reload gate.
Note what this means: the authorized reload path (?reload=true&password=..., i.e. what wheels reload hits) appears to be broken on Adobe CF in any environment on the current tree. The #3044 transcripts never caught it because they ran with an empty reloadPassword, so probe 6 was SKIPped there — this PR is the first time the path was exercised on Adobe.
Concrete paths forward (either unblocks this PR):
- (a) Fix the underlying bug first, then re-run these legs green and merge. The smallest plausible fix is to stop passing the component as a string on the lock path — e.g. use
$simpleLock's existingobjectbranch (vendor/wheels/Global.cfc:30-37) by passing the instance (object = this) instead ofexecuteArgs = {"componentReference" = "application"}, at bothpublic/Application.cfc:284-285and:165-167(and the matching template copies undercli/lucli/templates/app/public/Application.cfcandexamples/*/public/Application.cfc). That needs its own PR with cross-engine verification — file an issue and link it here. - (b) De-scope probe 6 from the Adobe legs for now: drop
SMOKE_RELOAD_PASSWORD="wheels-dev"from theRun smoke probesstep (.github/workflows/smoke-env.yml, smoke-adobe job) and thereloadPasswordsed inPoint the Adobe harness datasource at SQLite, so probe 6 reportsSKIPexactly as in the #3044 transcripts. Probes 1–2 still fully gate the #3029 class (the #3047 acceptance criterion), and the Lucee legs keep gating #3053. File an issue for the Adobe reload 500 and a follow-up to re-engage probe 6 once fixed, and note the skip in the job's comment block.
Either way, please file the Adobe reload bug as an issue — these legs just earned their keep, and the finding should not evaporate into a re-pushed commit.
Docs
2. PR body and commit body are stale against the final diff (minor, but worth fixing because the repo squash-merges). The PR body says "the bind-mounted harness settings.cfm sets reloadPassword="", and an empty reload password blocks reload … confirmed end-to-end by the green Adobe transcripts (both reload probes refused, 404)", and the commit body (a19afe7) repeats "The harness settings.cfm reloadPassword is empty, which blocks reload". The shipped diff does the opposite: it seds set(reloadPassword="") → set(reloadPassword="wheels-dev") and passes SMOKE_RELOAD_PASSWORD, engaging probe 6 — which the #3044 transcripts never covered (probe 6 was skipped there). That gap is precisely where the legs went red. Whichever path you take for finding 1, please update the PR description to match the final probe scope before merge.
What was verified clean
- Both sed patterns match the real files exactly (
config/environment.cfm:9; bothwheelstestdb_sqlserverlines andset(reloadPassword="")intools/docker/adobe2023/settings.cfm), each backed by agrep -qFtripwire. CONTAINER="wheels-adobe2023-1"matches compat-matrix prior art (.github/workflows/compat-matrix.yml:103usesCONTAINER="wheels-${CFENGINE}-1"), and the readiness loop is a faithful adaptation that additionally fixes compat-matrix's final-attempt off-by-one via theREADYflag.- The SQLite recipe is identical to
.github/actions/setup-wheels-test-env/action.yml:50-52; the adobe2023 CFConfig'swheelstestdb_sqliteDSN (jdbc:sqlite:/wheels-test-suite/wheelstestdb.db) and the committed driver jar (tools/docker/adobe2023/lib/sqlite-jdbc-3.50.3.0.jar, loaded viaserver.jsonlibDirs) both check out. - Paths filter additions (
compose.yml,tools/docker/adobe2023/**) are correct for the new job's inputs. - Commit header is a valid conventional commit (
ci:type, 69-char header), the Validate Commit Messages check is green, and the DCO sign-off is present (Signed-off-by: Peter Amiri <peter@alurium.com>). - Changelog fragment correctly omitted (ci-only, not user-facing).
- No security concerns:
permissions: contents: read, the staged reload password is the same non-secret throwaway value the Lucee leg documents, and the${{ matrix.wheels_env }}interpolations only ever expand the static matrix values.
…ve case-sensitive filesystems (#3071) The reload gate in onRequestStart() and the shared-application-name branch in onSessionStart() dispatch their handlers through $simpleLock with componentReference = "application" — a component PATH that Global.cfc's $invoke hands to cfinvoke. On case-sensitive filesystems Adobe CF resolves CFC names by exact case then all-lowercase, so the lowercase literal never matches Application.cfc and every authorized reload (?reload=true&password=...) returns HTTP 500 "Could not find the ColdFusion component or interface application" — in EVERY environment, development included. Lucee resolves case-insensitively and was unaffected, and macOS bind mounts are case-insensitive, which is why #3057's local verification and the Lucee smoke legs stayed green while the #3051 Adobe smoke legs (Linux runners) caught it. Fix: case-exact "Application" literal in all four same-lineage copies (repo demo app, CLI app template, starter-app and tweet examples), pinned by a sixth it-block in ReloadEnvironmentSwitchParitySpec (line-anchored, comment-skipping, case-sensitive scan). Verified: pre-fix 500 reproduced on a case-sensitive Docker volume in testing, production AND development; post-fix all six smoke probes pass in testing + production on the same volume, case-insensitive Adobe control unaffected, Lucee control green, full Lucee core suite at baseline (4409 pass / 12 tolerated testClientSpec artifacts). Signed-off-by: Peter Amiri <peter@alurium.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Wheels Bot — Reviewer
TL;DR: This PR adds the Adobe 2023 smoke legs (#3047) that PR-gate the #3029 failure class. The diff is byte-identical to the version reviewed previously — the only change since is the merge of develop (head f2b7f034e), which brings in the #3071 fix for the Adobe reload 500 that was the sole blocking finding. On this exact head, both Adobe legs run green with all six probes passing, including the previously failing probe 6. Verdict: approve — this supersedes the earlier CHANGES_REQUESTED review, whose blocking finding is resolved (audit trail below).
Previously blocking finding — resolved
Probe 6 (reload-authorized-restarts) returned HTTP 500 on both Adobe legs. The earlier review traced this to componentReference = "application" (lowercase) in public/Application.cfc's reload-gate and onSessionStart paths — Adobe CF on case-sensitive filesystems resolves CFC names by exact case and never matched Application.cfc, so $handleRestartAppRequest() never ran.
Evidence of resolution:
- Fix landed on develop: commit
f84bf8c4f("fix: case-exact Application componentReference so Adobe reloads survive case-sensitive filesystems", #3071) case-exacts the"Application"literal in all four same-lineage copies (demo app, CLI template, both examples) and pins it with a sixth it-block inReloadEnvironmentSwitchParitySpec. - Merged into this branch: head
f2b7f034eis the merge of develop containing that fix. - Both legs green on this head (run 27395934863):
Smoke: production (Adobe 2023)andSmoke: testing (Adobe 2023)both pass, with probe logs showingPASS probe=reload-authorized-restarts (302)in each leg — alongsidePASSon probes 1–5. The gate is now exercising the full probe set it was designed to run, and it has already proven its worth: the red run on the previous head is what surfaced #3071 in the first place.
The earlier review's request — "either land a fix for the underlying bug first, then re-run these legs green and merge" — is exactly what happened (path (a)).
What re-verified clean at the merge head
- Both sed targets still match post-merge:
config/environment.cfm:9(set(environment = "development")) andtools/docker/adobe2023/settings.cfm:12-13,26(wheelstestdb_sqlserver×2,set(reloadPassword="")), each backed by agrep -qFtripwire in the job. tools/ci/smoke-env.shis untouched by this PR and unchanged on develop since #3057 — probe semantics are exactly what the legs validated.- All other checks green on this head: Lucee 7 + SQLite suite, both Lucee smoke legs, Validate Commit Messages, Bot PR TDD Gate.
- All clean verifications from the prior review (container name vs compat-matrix prior art, readiness-loop
READYflag fix, SQLite recipe parity withsetup-wheels-test-env, paths-filter additions,permissions: contents: read, non-secret throwaway reload password, changelog fragment correctly omitted for a ci-only change) apply unchanged to the identical diff.
Docs
PR body is still stale on probe scope (minor, non-blocking). The "Verification" section still says "Reload probes (4/5): the bind-mounted harness settings.cfm sets reloadPassword="", and an empty reload password blocks reload … confirmed end-to-end by the green Adobe transcripts below (both reload probes refused, 404)" — but the shipped diff seds the harness password to wheels-dev (.github/workflows/smoke-env.yml, "Point the Adobe harness datasource at SQLite" step) and passes SMOKE_RELOAD_PASSWORD="wheels-dev", engaging probe 6. Since the repo squash-merges, please refresh that paragraph (and ideally note the #3071 detour) before merge so the permanent record matches what the job actually does.
What
Adds a
smoke-adobejob to.github/workflows/smoke-env.yml: a PR-gated production/testing matrix that boots the compat-matrixadobe2023Docker engine withconfig/environment.cfmforced to the matrix environment and runs the existing engine-agnostic probes intools/ci/smoke-env.shagainsthttp://localhost:62023.tools/ci/smoke-env.shis unchanged.Fixes #3047. Refs #3029.
Why this home (cost investigation)
Issue #3047 offered two candidate homes. Investigated both before writing a line:
compat-matrix.ymlAdobe legs (rejected): that workflow runs onschedule(weekly, Sunday 02:00 UTC) andworkflow_dispatchonly. A smoke step there would never make a regressing PR red — the acceptance criterion ("a PR reintroducingcfabort;at the dispatch: bare cfabort crashes every Adobe engine in the public-component 404 branch #3029 site goes red in CI") cannot be met at that cadence. A regression would surface days after merge, in a non-blocking (continue-on-error: true) scheduled run with no PR association.smoke-env.ymlAdobe job (chosen): the engine images are not registry-pullable (wheels-test-adobe2023:v1.0.1is a local build tag), but the build is cheap in CI. Measured on compat-matrix run 27081098861 (2026-06-07, adobe2023 job):docker compose build --no-cache+up -d= 91s; engine serving = ~4 min more. Each matrix leg should land around 6–7 minutes of parallel runner time, behind the same paths filter as the Lucee legs (now alsocompose.yml+tools/docker/adobe2023/**).Boot → sed → probe order (dry reasoning)
The #3047 plan constraint is that
config/environment.cfmmust be sed'd before app start (the environment is read once at application start; in-place reload does not re-read it). The job ordering guarantees this without any restart:Force <env> environment— GNUsedrewritesset(environment = "development")→ matrix value inconfig/environment.cfm, with agrep -qFtripwire against pattern drift. No container exists yet. (Step text identical to the proven Lucee job.)Create SQLite test databases—wheelstestdb.db/wheelstestdb_tenant_b.dbat the repo root; the adobe2023 CFConfig'swheelstestdb_sqliteDSN isjdbc:sqlite:/wheels-test-suite/wheelstestdb.db, i.e. exactly these files through the bind mount. Same recipe assetup-wheels-test-env.Point the Adobe harness datasource at SQLite—compose.ymlbind-mountstools/docker/adobe2023/settings.cfmoverconfig/settings.cfm, and that file defaults towheelstestdb_sqlserver— a container this job does not start. Sed towheelstestdb_sqlite(driver jar is committed attools/docker/adobe2023/lib/sqlite-jdbc-3.50.3.0.jar, loaded viaserver.jsonlibDirs), verified bygrep -qF. Runs beforeupso the bind mount captures the rewritten inode. The probes never query the DB, but this keeps any lazily-triggered datasource touch from 500ing a probe; it also means zero DB containers.Build and start Adobe 2023—docker compose build adobe2023with the compat-matrix retry loop (transient-download absorption), thenup -d. The container's first sight ofconfig/environment.cfmis the already-sed'd file via the./:/wheels-test-suitemount → the app cold-boots directly into the matrix environment. No restart needed.Wait for Adobe 2023 to be ready— readiness loop adapted from compat-matrix (crash-restart up to 3×, accept 200/302/404 — in non-dev the root route is a clean 404 since the public welcome page is development-only — last-HTTP-code + log diagnostics on timeout, off-by-one on the final attempt fixed via aREADYflag), then one warm-upcurlsoonApplicationStarthas fully completed.Run smoke probes—BASE_URL="http://localhost:62023" SMOKE_ENV=<env> bash tools/ci/smoke-env.sh. The script'sTRACE_MARKERSalready includecoldfusion\.runtimeand the Adobe error-template markerError Occurred While Processing Request, so engine-template leakage on/or/wheels/info(the dispatch: bare cfabort crashes every Adobe engine in the public-component 404 branch #3029 class) fails probes 1–2.Reload probes (4/5): the bind-mounted harness
settings.cfmsetsreloadPassword="", and an empty reload password blocks reload (vendor/wheels/tests/specs/security/ReloadPasswordSpec.cfc: "rejects reload when reloadPassword is empty") — confirmed end-to-end by the green Adobe transcripts below (both reload probes refused, 404).Verification
Per the work plan, no local Adobe boot was performed for this PR — the probe behavior on Adobe 2023 is already proven by PR #3044's hand-run transcripts against
wheels-test-adobe2023:v1.0.1with the harness configs staged:testingandproduction(transcripts in the #3044 body).cadfb13b9): Adobe 2023 +testingreproduced the dispatch: bare cfabort crashes every Adobe engine in the public-component 404 branch #3029 class verbatim —FAIL probe=root-no-5xx ... status=500andFAIL probe=wheels-info-clean-404 ... status=500with the Adobe error template in the body. That is exactly what this job now gates at PR time.What was run for this change:
ruby -ryamlparse: YAML OK.actionlint: zero findings in the newsmoke-adobejob; the single remaining warning (SC2046, line 79) is the pre-existing Lucee "Stop server" step inherited verbatim from ci: non-dev environment smoke probes (production/testing matrix) #3044 and untouched here.config/environment.cfmandtools/docker/adobe2023/settings.cfmfiles — pattern matches andgreptripwires confirmed (set(environment = "testing");coreTestDataSourceName/dataSourceName→wheelstestdb_sqlite).wheels-adobe2023-1) is the same sequence compat-matrix executes green in CI weekly; first executed run of this job will be this PR's own checks, since the workflow's paths filter includes.github/workflows/smoke-env.yml.Honest caveats
adobe2025is deliberately left out: the dispatch: bare cfabort crashes every Adobe engine in the public-component 404 branch #3029 idiom failed on every Adobe engine (bare script-contextcfabortis a parse/runtime error family-wide), and one Adobe leg keeps the per-PR cost at ~13 runner-minutes total instead of ~26.ci-only change, not user-facing.🤖 Generated with Claude Code