From c5171ef1fe7fd5d717d6651cd6dc69d9536ed080 Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:44:39 +0200 Subject: [PATCH 1/8] Only pass lucee.extensions / lucee.base.config sysprops when set, empty ones hide the env vars on 7.0+ --- build.xml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/build.xml b/build.xml index 2c9d2ab..cab9c34 100644 --- a/build.xml +++ b/build.xml @@ -166,6 +166,23 @@ + + + + + + + + + + + + + + + + + @@ -410,13 +427,13 @@ - + - + From 1a44fbfbefb3f51cd9d43f3e4c94301b89da28ef Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:44:40 +0200 Subject: [PATCH 2/8] Stream forked JVM stderr live instead of capturing it, so it isn't lost when the run fails --- build.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.xml b/build.xml index cab9c34..441128a 100644 --- a/build.xml +++ b/build.xml @@ -413,7 +413,7 @@ - + @@ -466,7 +466,6 @@ --> - ${errorOut} From c0c5d79010bd22691677f7ba8a53a1e642ac8371 Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:44:40 +0200 Subject: [PATCH 3/8] Document the compile option --- README.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a9772d..c9a8332 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Examples: - `-Dextensions=` - List of extensions to install (default: empty). Accepts GUIDs (all versions) or Maven GAV coordinates on Lucee 7.0+ (e.g. `org.lucee:hibernate-extension:5.6.15.12-SNAPSHOT`) - `-DextensionDir=` - Directory containing manual extension files (`*.lex`) to install (default: empty) -- `-Dcompile=` - Compile all CFML under webroot (default: false). Set to `true` to enable +- `-Dcompile=` - Compile all CFML under webroot before executing the script (default: false). See [Compile Option](#compile-option) below - `-DluceeCFConfig=` - Path to full .CFConfig.json file for additional Lucee configuration #### Working Directory @@ -115,6 +115,39 @@ These options are good for inspecting after a run, or setting up the `/lucee-ser - `-DUseEpsilonGC=` - Enable Epsilon no-op garbage collector for testing (default: false). Also enables AlwaysPreTouch - `-DPrintInlining=` - Enable JVM compilation diagnostics (default: false). Enables PrintInlining, PrintCompilation, and UnlockDiagnosticVMOptions +### Compile Option + +`-Dcompile=true` compiles every CFML file under the webroot **before** the main `-Dexecute` script runs. Internally it invokes the Lucee admin `compileMapping` action against the web mapping `/` with `stoponerror="false"`. + +**What it's for:** + +- **CI syntax check** — catches parse errors in files your test script doesn't touch. Without `-Dcompile`, a typo in a rarely-hit CFC only surfaces when that code path runs. +- **Pre-warm the class cache** — every `.cfm`/`.cfc` gets compiled to bytecode up front, so first-hit request latency isn't paying compile cost. +- **Smoke-test a codebase** against a new Lucee version without wiring up real tests. + +**Behaviour:** + +- Compiles everything reachable from the webroot's `/` mapping (recursive). +- `stoponerror="false"` — compilation carries on past a bad file, so every error is collected. If there were any, they are all reported together (`Compilation failed with N error(s)`, with file and line for each) and the run fails before `-Dexecute` runs. Any compile error means a non-zero exit code, even if the `-Dexecute` script itself is fine. +- Runs once, before `-Dexecute`. Doesn't recompile if files change mid-run (script-runner is one-shot anyway). + +**Examples:** + +```bash +# Compile + run index.cfm +ant -Dwebroot="D:\work\myproject" -Dexecute="index.cfm" -Dcompile=true + +# compile a known-bad codebase: lists the compile errors, then fails without running index.cfm +ant -Dwebroot="./sampleBad" -Dexecute="index.cfm" -Dcompile=true +``` + +The script-runner's own CI runs both a clean webroot and the `sampleBad/` fixture (deliberately broken CFML), see `.github/workflows/main.yml`. The `sampleBad` step is `continue-on-error`, so it shows the error output but doesn't assert the failure. + +**When not to use it:** + +- Iterating locally on a single script — adds startup cost for no benefit. +- Webroots with large amounts of unrelated CFML (e.g. a full app when you only want to run one test) — you'll pay the full compile cost. + ### Java Flight Recorder (JFR) Profiling Enable JFR to capture detailed performance data during script execution: From 2391503b4e5894724d6493f7e1aebea65dfbaeff Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:51:32 +0200 Subject: [PATCH 4/8] CI: concurrent matrix of Lucee 5.4 to 8.0, assert compile failures and LUCEE_BASE_CONFIG --- .github/workflows/main.yml | 80 ++++++++++++++++++++---- README.md | 2 +- tests/base-config/.CFConfig.json | 3 + tests/base-config/index.cfm | 7 +++ tests/compile-mixed/index.cfm | 3 + tests/compile-mixed/sub/BadComponent.cfc | 3 + tests/compile-mixed/sub/badpage.cfm | 1 + 7 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 tests/base-config/.CFConfig.json create mode 100644 tests/base-config/index.cfm create mode 100644 tests/compile-mixed/index.cfm create mode 100644 tests/compile-mixed/sub/BadComponent.cfc create mode 100644 tests/compile-mixed/sub/badpage.cfm diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 11af821..e8f6d33 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,7 +6,73 @@ on: workflow_dispatch: jobs: - build-ubuntu: + versions: + name: Lucee ${{ matrix.lucee }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - { lucee: 5.4/stable/jar, java: 11 } + - { lucee: 6.2/stable/jar, java: 21 } + - { lucee: 6.2/snapshot/jar, java: 21 } + - { lucee: 7.0/stable/jar, java: 21 } + - { lucee: 7.0/snapshot/jar, java: 21 } + - { lucee: 7.1/snapshot/jar, java: 21 } + - { lucee: 8.0/snapshot/jar, java: 21 } + + steps: + - uses: actions/checkout@v4 + + - name: Set up Java ${{ matrix.java }} + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: ${{ matrix.java }} + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ~/.m2 + key: lucee-script-runner-maven-cache + + - name: Cache Lucee files + uses: actions/cache@v4 + with: + path: ~/work/script-runner/script-runner/lucee-download-cache/ + key: lucee-downloads + + - name: Run debug.cfm, passing variables + run: ant -DluceeVersionQuery="${{ matrix.lucee }}" -Dexecute="/debug.cfm" -Dtruth="cfml rocks" -Dauthor="Zac Spitzer" + + - name: Compile webroot + run: ant -DluceeVersionQuery="${{ matrix.lucee }}" -Dexecute="/index.cfm" -Dcompile="true" + + - name: Compile webroot with errors, expect the run to fail before executing + run: | + if ant -DluceeVersionQuery="${{ matrix.lucee }}" -Dexecute="/index.cfm" -Dcompile="true" \ + -Dwebroot="${{ github.workspace }}/tests/compile-mixed" > compile-mixed.txt 2>&1; then + cat compile-mixed.txt + echo "::error::compile errors didn't fail the run" + exit 1 + fi + cat compile-mixed.txt + grep -q "badpage.cfm" compile-mixed.txt || { echo "::error::badpage.cfm compile error not reported"; exit 1; } + grep -q "BadComponent.cfc" compile-mixed.txt || { echo "::error::BadComponent.cfc compile error not reported"; exit 1; } + if grep -q "compile-mixed index.cfm ran" compile-mixed.txt; then + echo "::error::index.cfm ran despite compile errors" + exit 1 + fi + + # Lucee writes its config back to the file it's given, so pass a copy + - name: LUCEE_BASE_CONFIG env var is applied + if: ${{ !startsWith( matrix.lucee, '5.' ) }} + run: | + cp tests/base-config/.CFConfig.json "$RUNNER_TEMP/base-config.json" + LUCEE_BASE_CONFIG="$RUNNER_TEMP/base-config.json" \ + ant -DluceeVersionQuery="${{ matrix.lucee }}" -Dexecute="/index.cfm" -Dwebroot="${{ github.workspace }}/tests/base-config" + + variants: runs-on: ubuntu-latest steps: @@ -27,11 +93,8 @@ jobs: - name: Run default run: ant - - name: Run Latest Lucee 6 (via version query) - run: ant -DluceeVersionQuery="6/all/jar" -Dexecute="/debug.cfm" - - name: Run Lucee 6 Stable - run: ant -DluceeVersion="6.2.2.91" -Dexecute="/debug.cfm" -Dtruth="cfml rocks" -Dauthor="Zac Spitzer" + run: ant -DluceeVersion="6.2.2.91" -Dexecute="/debug.cfm" - name: Run Lucee 5 (using Lucee light, no extensions) run: ant -DluceeVersion="light-5.4.2.17" -Dexecute="/debug.cfm" @@ -42,13 +105,6 @@ jobs: - name: Run Latest Lucee 5 RC Light run: ant -DluceeVersionQuery="5/rc/light" -Dexecute="/debug.cfm" - - name: Run Latest Stable Lucee 5, compile webroot - run: ant -DluceeVersionQuery="5/stable/jar" -Dexecute="/index.cfm" -Dcompile="true" - - - name: Run Latest Stable Lucee 5, compile webroot (invalid code) - continue-on-error: true - run: ant -DluceeVersionQuery="5/stable/jar" -Dexecute="/index.cfm" -Dcompile="true" -Dwebroot="${{ github.workspace }}/sampleBad/" - - name: Test concurrent execution with unique working directories run: | ant -DuniqueWorkingDir="true" -Dexecute="/debug.cfm" & diff --git a/README.md b/README.md index c9a8332..4530f02 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ ant -Dwebroot="D:\work\myproject" -Dexecute="index.cfm" -Dcompile=true ant -Dwebroot="./sampleBad" -Dexecute="index.cfm" -Dcompile=true ``` -The script-runner's own CI runs both a clean webroot and the `sampleBad/` fixture (deliberately broken CFML), see `.github/workflows/main.yml`. The `sampleBad` step is `continue-on-error`, so it shows the error output but doesn't assert the failure. +The script-runner's own CI compiles a clean webroot, and `tests/compile-mixed/` (a good `index.cfm` plus broken files under `sub/`) on every Lucee version in its matrix, asserting that both errors are reported and the run fails without executing `index.cfm`. See `.github/workflows/main.yml`. **When not to use it:** diff --git a/tests/base-config/.CFConfig.json b/tests/base-config/.CFConfig.json new file mode 100644 index 0000000..cb72564 --- /dev/null +++ b/tests/base-config/.CFConfig.json @@ -0,0 +1,3 @@ +{ + "timezone": "Pacific/Chatham" +} diff --git a/tests/base-config/index.cfm b/tests/base-config/index.cfm new file mode 100644 index 0000000..ba328a1 --- /dev/null +++ b/tests/base-config/index.cfm @@ -0,0 +1,7 @@ + + // .CFConfig.json here sets the timezone, CI passes a copy via the LUCEE_BASE_CONFIG env var (Lucee writes its config back to that file) + tz = getTimeZone(); + systemOutput( "timezone [#tz#]", true ); + if ( tz != "Pacific/Chatham" ) + throw( message="LUCEE_BASE_CONFIG wasn't applied, timezone is [#tz#], expected [Pacific/Chatham]" ); + diff --git a/tests/compile-mixed/index.cfm b/tests/compile-mixed/index.cfm new file mode 100644 index 0000000..2258fe8 --- /dev/null +++ b/tests/compile-mixed/index.cfm @@ -0,0 +1,3 @@ + + systemOutput( "compile-mixed index.cfm ran", true ); + diff --git a/tests/compile-mixed/sub/BadComponent.cfc b/tests/compile-mixed/sub/BadComponent.cfc new file mode 100644 index 0000000..96abe87 --- /dev/null +++ b/tests/compile-mixed/sub/BadComponent.cfc @@ -0,0 +1,3 @@ +component { + function broken( { +} diff --git a/tests/compile-mixed/sub/badpage.cfm b/tests/compile-mixed/sub/badpage.cfm new file mode 100644 index 0000000..6cef2ca --- /dev/null +++ b/tests/compile-mixed/sub/badpage.cfm @@ -0,0 +1 @@ +#name From 35002f3548624ec153f757856751211dc29f95a7 Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:51:33 +0200 Subject: [PATCH 5/8] CI: webroot handling matrix is manual trigger only --- .github/workflows/webroot-matrix.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/webroot-matrix.yml b/.github/workflows/webroot-matrix.yml index e8cd5de..f8c6abb 100644 --- a/.github/workflows/webroot-matrix.yml +++ b/.github/workflows/webroot-matrix.yml @@ -1,7 +1,5 @@ name: Webroot Handling Matrix on: - push: - pull_request: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} From 426f7d7b3f8dbde98366a5ac20b39647b28980ff Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:54:49 +0200 Subject: [PATCH 6/8] CI: bump actions/checkout to v7, cache and setup-java to v6 (node 24) --- .github/workflows/main.yml | 14 ++++++------- .github/workflows/webroot-matrix.yml | 30 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e8f6d33..d44a87f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,22 +22,22 @@ jobs: - { lucee: 8.0/snapshot/jar, java: 21 } steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Set up Java ${{ matrix.java }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: distribution: temurin java-version: ${{ matrix.java }} - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2 key: lucee-script-runner-maven-cache - name: Cache Lucee files - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/work/script-runner/script-runner/lucee-download-cache/ key: lucee-downloads @@ -76,16 +76,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2 key: lucee-script-runner-maven-cache - name: Cache Lucee files - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/work/script-runner/script-runner/lucee-download-cache/ key: lucee-downloads diff --git a/.github/workflows/webroot-matrix.yml b/.github/workflows/webroot-matrix.yml index f8c6abb..4183266 100644 --- a/.github/workflows/webroot-matrix.yml +++ b/.github/workflows/webroot-matrix.yml @@ -9,16 +9,16 @@ jobs: name: MacOS Bash runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: distribution: 'temurin' java-version: '21' @@ -50,16 +50,16 @@ jobs: name: Ubuntu Bash runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: distribution: 'temurin' java-version: '21' @@ -92,16 +92,16 @@ jobs: name: Windows CMD runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: distribution: 'temurin' java-version: '21' @@ -142,16 +142,16 @@ jobs: name: Windows PowerShell runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: distribution: 'temurin' java-version: '21' @@ -188,16 +188,16 @@ jobs: name: Windows Bash runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v6 with: distribution: 'temurin' java-version: '21' From 615d8e26af946a08d2f38381b52b3850236b64c7 Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:55:51 +0200 Subject: [PATCH 7/8] CI: fail the Windows PowerShell webroot job when a run fails --- .github/workflows/webroot-matrix.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/webroot-matrix.yml b/.github/workflows/webroot-matrix.yml index 4183266..6fa78df 100644 --- a/.github/workflows/webroot-matrix.yml +++ b/.github/workflows/webroot-matrix.yml @@ -164,6 +164,7 @@ jobs: $webroots = @('.', "${{ github.workspace }}\tests\webroot") pwd $executes = @('index.cfm', 'test.cfm', 'sub/test.cfm') + $failed = $false foreach ($w in $webroots) { foreach ($e in $executes) { $luceeVersionQuery = $env:LUCEE_VERSION_QUERY @@ -172,7 +173,8 @@ jobs: $LASTEXITCODE = 0 iex $cmd if ($LASTEXITCODE -ne 0) { - $cmd = "ant -buildfile=../../build.xml `"-Dwebroot=$w`" `"-Dexecute=$e`" -DpreCleanup=false -DpostCleanup=false -DluceeVersionQuery=$luceeVersionQuery" + $failed = $true + $cmd ="ant -buildfile=../../build.xml `"-Dwebroot=$w`" `"-Dexecute=$e`" -DpreCleanup=false -DpostCleanup=false -DluceeVersionQuery=$luceeVersionQuery" $platform = "windows-latest" $shell = "pwsh" $summary = @() @@ -184,6 +186,7 @@ jobs: } } } + if ($failed) { exit 1 } windows-bash: name: Windows Bash runs-on: windows-latest From cb6d050bd85f629423bd8786d61de6b3cbdfb27e Mon Sep 17 00:00:00 2001 From: Zac Spitzer Date: Wed, 14 Oct 2026 14:59:00 +0200 Subject: [PATCH 8/8] CI: cache each resolved Lucee jar under its own key, the shared lucee-downloads cache never updated --- .github/workflows/main.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d44a87f..74e42ff 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,11 +36,16 @@ jobs: path: ~/.m2 key: lucee-script-runner-maven-cache - - name: Cache Lucee files + # jar names include the full version, so a new snapshot is a new key, saved once + - name: Resolve Lucee jar + id: lucee + run: echo "jar=$(curl -sf https://update.lucee.org/rest/update/provider/latest/${{ matrix.lucee }}/filename | tr -d '"')" >> "$GITHUB_OUTPUT" + + - name: Cache Lucee jar ${{ steps.lucee.outputs.jar }} uses: actions/cache@v6 with: - path: ~/work/script-runner/script-runner/lucee-download-cache/ - key: lucee-downloads + path: lucee-download-cache/${{ steps.lucee.outputs.jar }} + key: lucee-jar-${{ steps.lucee.outputs.jar }} - name: Run debug.cfm, passing variables run: ant -DluceeVersionQuery="${{ matrix.lucee }}" -Dexecute="/debug.cfm" -Dtruth="cfml rocks" -Dauthor="Zac Spitzer" @@ -84,11 +89,12 @@ jobs: path: ~/.m2 key: lucee-script-runner-maven-cache + # pinned versions only, so a fixed key is fine - name: Cache Lucee files uses: actions/cache@v6 with: - path: ~/work/script-runner/script-runner/lucee-download-cache/ - key: lucee-downloads + path: lucee-download-cache/ + key: lucee-downloads-variants - name: Run default run: ant