diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 11af821..74e42ff 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -6,32 +6,101 @@ 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
+ - uses: actions/checkout@v7
+
+ - name: Set up Java ${{ matrix.java }}
+ 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
+ # 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: 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"
+
+ - 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:
+ - uses: actions/checkout@v7
+
+ - name: Cache Maven packages
+ uses: actions/cache@v6
+ with:
+ path: ~/.m2
+ key: lucee-script-runner-maven-cache
+
+ # pinned versions only, so a fixed key is fine
- 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
+ path: lucee-download-cache/
+ key: lucee-downloads-variants
- 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 +111,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/.github/workflows/webroot-matrix.yml b/.github/workflows/webroot-matrix.yml
index e8cd5de..6fa78df 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 }}
@@ -11,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'
@@ -52,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'
@@ -94,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'
@@ -144,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'
@@ -166,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
@@ -174,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 = @()
@@ -186,20 +186,21 @@ jobs:
}
}
}
+ if ($failed) { exit 1 }
windows-bash:
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'
diff --git a/README.md b/README.md
index 8a9772d..4530f02 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 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:**
+
+- 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:
diff --git a/build.xml b/build.xml
index 2c9d2ab..441128a 100644
--- a/build.xml
+++ b/build.xml
@@ -166,6 +166,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -396,7 +413,7 @@
-
+
@@ -410,13 +427,13 @@
-
+
-
+
@@ -449,7 +466,6 @@
-->
- ${errorOut}
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