Skip to content

Check extensions without starting the application - #1

Merged
alexskinner merged 2 commits into
mainfrom
fix/extension-check-no-app-boot
Oct 29, 2026
Merged

alexskinner merged 2 commits into
mainfrom
fix/extension-check-no-app-boot

Conversation

@Blute

@Blute Blute commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Why

rustcfml-warm-extensions (run by the entrypoint at every container start, before the server) ran rustcfml -c 'writeOutput("")' from the webroot. Inline code run there picks up the app's Application.cfc, so each start booted the application once before serving:

  • onApplicationStart ran, including any database work it does;
  • onRequest ran with an empty target page. An onRequest that includes its target page then fails, because an empty include resolves to the Application.cfc's own directory (Cannot read '<dir>': Is a directory), and the app's onError handles it as a 500.

Summary

  • The probe is an empty template in a mktemp -d scratch directory instead of inline code in the webroot.
  • An empty Application.cfc beside the probe stops the engine's upward search. The app's own isn't found even when the scratch directory is inside the webroot (TMPDIR under it, or a webroot of /tmp).
  • The webroot's extensions/ is symlinked into the scratch directory, because the engine takes its application directory from the template. The search order stays: --extensions / config directory, webroot extensions/, home, beside the binary. The webroot is made absolute first, so a relative RUSTCFML_WEBROOT links correctly.
  • The cwd stays the webroot, so the server .cfconfig.json (and its extensions.directory) is found exactly as the server finds it.
  • Problems are counted from the engine's unedited output. Only the lines shown are rewritten to report $WEBROOT/extensions/… paths, and that uses a literal awk replacement, so no character in a path can change what's matched.
  • With no writable temp directory (a --read-only container), the check falls back to the previous inline probe and says so on stderr, rather than failing the start.

Test plan

  • make smoke passes, with five new cases:
    • the check doesn't fire onApplicationStart;
    • the same, with TMPDIR inside the webroot;
    • a broken extension is still fatal (exit 78) from a relative webroot (RUSTCFML_WEBROOT=.);
    • the same from a webroot with | and & in its path, reported with the webroot's path;
    • a --read-only container still passes.
  • Each new case fails against the previous script.
  • Against a webroot with a .rcx in extensions/ and a throwing Application.cfc: loads the extension and reports the /srv/app/extensions/... path, exit 0.
  • Empty webroot: exit 0, quiet.

🤖 Generated with Claude Code

rustcfml-warm-extensions ran `rustcfml -c 'writeOutput("")'` in the webroot.
Inline code there runs the app's Application.cfc, so every container start
booted the application once before the server: onApplicationStart, then
onRequest with no page, which an onRequest that includes its target page
turns into an error.

The probe is now an empty template in a scratch directory, with the
webroot's extensions/ linked in so the search order is unchanged, and the
cwd still the webroot so the server .cfconfig.json is found as before.
Messages report the webroot's paths. A smoke case checks that the check
does not fire onApplicationStart.
@Blute
Blute force-pushed the fix/extension-check-no-app-boot branch from 71df227 to fb05bbf Compare October 28, 2026 02:27
…th rewrite, read-only fallback

- An empty Application.cfc beside the probe ends the engine's upward search,
  so the app's Application.cfc is not run when the scratch directory is
  under the webroot (TMPDIR inside it, or a webroot of /tmp).
- The webroot is made absolute before it is linked into the scratch
  directory; a relative one (RUSTCFML_WEBROOT=.) linked to itself and
  skipped the webroot's extensions, so a broken one passed.
- Problems are counted from the engine's unedited output, and the shown
  paths are rewritten with a literal awk replacement. A | in the webroot
  broke the sed expression, emptied the output and let a broken extension
  pass; a & garbled the shown paths.
- With no writable temp directory (a read-only container) the check falls
  back to the previous inline probe in the webroot instead of failing.

A smoke case for each; all four fail against the previous version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alexskinner
alexskinner merged commit 3fb38ab into main Oct 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants