diff --git a/.github/workflow-results/test-lucee7-mysql.md b/.github/workflow-results/test-lucee7-mysql.md index 14115da90e..13a9ea6da9 100644 --- a/.github/workflow-results/test-lucee7-mysql.md +++ b/.github/workflow-results/test-lucee7-mysql.md @@ -1,15 +1,15 @@ # Workflow Results: Test Lucee 7 + MySQL **Status:** PASSED -**Run:** [#18](https://github.com/wheels-dev/wheels/actions/runs/22270240179) -**Commit:** ff8fe7c99be289e1e15b11cfb867e0b1c2fe7b24 -**Branch:** claude/fix-pr-1891-workflow-pGc9Z -**Date:** 2026-02-22 04:18:58 UTC +**Run:** [#23](https://github.com/wheels-dev/wheels/actions/runs/26032173536) +**Commit:** 6b6d1acc0e60fe9cb42d3d731cd80a1d1a6f4829 +**Branch:** claude/evaluate-rustcfml-feasibility-40oUw +**Date:** 2026-05-18 12:03:32 UTC ## Test Results ``` -Bundle: wheels.tests_testbox.specs.BasicsSpec +Bundle: wheels.tests.specs.BasicsSpec CFML Engine: Lucee 7.0.1.100 Duration: 7ms Labels: @@ -20,9 +20,20 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.cachingSpec +Bundle: wheels.tests.specs.channel.DatabaseAdapterSpec CFML Engine: Lucee 7.0.1.100 -Duration: 102ms +Duration: 203ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 1 ║ 8 ║ 8 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.controller.cachingSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 76ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -31,9 +42,20 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.csrf.cookieSpec +Bundle: wheels.tests.specs.controller.channelSpec CFML Engine: Lucee 7.0.1.100 -Duration: 298ms +Duration: 88ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 3 ║ 22 ║ 22 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.controller.csrf.cookieSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 277ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -42,9 +64,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.csrf.sessionSpec +Bundle: wheels.tests.specs.controller.csrf.sessionSpec CFML Engine: Lucee 7.0.1.100 -Duration: 219ms +Duration: 211ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -53,9 +75,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.filtersSpec +Bundle: wheels.tests.specs.controller.filtersSpec CFML Engine: Lucee 7.0.1.100 -Duration: 68ms +Duration: 61ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -64,9 +86,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.flashSpec +Bundle: wheels.tests.specs.controller.flashSpec CFML Engine: Lucee 7.0.1.100 -Duration: 132ms +Duration: 152ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -75,9 +97,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.initializationSpec +Bundle: wheels.tests.specs.controller.initializationSpec CFML Engine: Lucee 7.0.1.100 -Duration: 41ms +Duration: 43ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -86,9 +108,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.miscellaneousSpec +Bundle: wheels.tests.specs.controller.miscellaneousSpec CFML Engine: Lucee 7.0.1.100 -Duration: 188ms +Duration: 146ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -97,9 +119,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.providesSpec +Bundle: wheels.tests.specs.controller.providesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 64ms +Duration: 43ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -108,9 +130,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.redirectionSpec +Bundle: wheels.tests.specs.controller.redirectionSpec CFML Engine: Lucee 7.0.1.100 -Duration: 99ms +Duration: 68ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -119,9 +141,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.renderingSpec +Bundle: wheels.tests.specs.controller.renderingSpec CFML Engine: Lucee 7.0.1.100 -Duration: 1126ms +Duration: 955ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -130,9 +152,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.requestSpec +Bundle: wheels.tests.specs.controller.requestSpec CFML Engine: Lucee 7.0.1.100 -Duration: 23ms +Duration: 28ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -141,9 +163,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.sseSpec +Bundle: wheels.tests.specs.controller.sseSpec CFML Engine: Lucee 7.0.1.100 -Duration: 46ms +Duration: 52ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -152,9 +174,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.controller.verifiesSpec +Bundle: wheels.tests.specs.controller.verifiesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 30ms +Duration: 40ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -163,9 +185,20 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.dispatch.createParamsSpec +Bundle: wheels.tests.specs.di.InjectorSpec CFML Engine: Lucee 7.0.1.100 -Duration: 17ms +Duration: 44ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 8 ║ 25 ║ 25 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.dispatch.createParamsSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 19ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -174,9 +207,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.dispatch.findMatchingRouteMegaSpec +Bundle: wheels.tests.specs.dispatch.findMatchingRouteMegaSpec CFML Engine: Lucee 7.0.1.100 -Duration: 741ms +Duration: 859ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -185,9 +218,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.dispatch.findMatchingRouteSpec +Bundle: wheels.tests.specs.dispatch.findMatchingRouteSpec CFML Engine: Lucee 7.0.1.100 -Duration: 35ms +Duration: 25ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -196,7 +229,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.dispatch.getrequestmethodSpec +Bundle: wheels.tests.specs.dispatch.getrequestmethodSpec CFML Engine: Lucee 7.0.1.100 Duration: 5ms Labels: @@ -207,9 +240,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.dispatch.requestSpec +Bundle: wheels.tests.specs.dispatch.requestSpec CFML Engine: Lucee 7.0.1.100 -Duration: 9ms +Duration: 8ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -218,9 +251,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.dispatch.setCorsHeadersSpec +Bundle: wheels.tests.specs.dispatch.setCorsHeadersSpec CFML Engine: Lucee 7.0.1.100 -Duration: 1ms +Duration: 0ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -229,7 +262,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.environment.ipbasedaccessSpec +Bundle: wheels.tests.specs.environment.ipbasedaccessSpec CFML Engine: Lucee 7.0.1.100 Duration: 4ms Labels: @@ -240,9 +273,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.events.onerrorSpec +Bundle: wheels.tests.specs.events.onerrorSpec CFML Engine: Lucee 7.0.1.100 -Duration: 237ms +Duration: 246ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -251,7 +284,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.cachingSpec +Bundle: wheels.tests.specs.global.cachingSpec CFML Engine: Lucee 7.0.1.100 Duration: 5ms Labels: @@ -262,9 +295,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.dbinfoSpec +Bundle: wheels.tests.specs.global.dbinfoSpec CFML Engine: Lucee 7.0.1.100 -Duration: 84ms +Duration: 66ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -273,9 +306,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.internalSpec +Bundle: wheels.tests.specs.global.internalSpec CFML Engine: Lucee 7.0.1.100 -Duration: 60ms +Duration: 62ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -284,9 +317,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.listcleanSpec +Bundle: wheels.tests.specs.global.listcleanSpec CFML Engine: Lucee 7.0.1.100 -Duration: 6ms +Duration: 3ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -295,9 +328,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.publicSpec +Bundle: wheels.tests.specs.global.publicSpec CFML Engine: Lucee 7.0.1.100 -Duration: 42ms +Duration: 46ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -306,9 +339,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.stringsSpec +Bundle: wheels.tests.specs.global.stringsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 28ms +Duration: 17ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -317,9 +350,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.global.urlforSpec +Bundle: wheels.tests.specs.global.urlforSpec CFML Engine: Lucee 7.0.1.100 -Duration: 45ms +Duration: 32ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -328,7 +361,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.internal.model.validationsSpec +Bundle: wheels.tests.specs.internal.model.validationsSpec CFML Engine: Lucee 7.0.1.100 Duration: 31ms Labels: @@ -339,9 +372,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.jobs.JobQueueSpec +Bundle: wheels.tests.specs.jobs.JobQueueSpec CFML Engine: Lucee 7.0.1.100 -Duration: 63ms +Duration: 126ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -350,7 +383,18 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.MapperSpec +Bundle: wheels.tests.specs.jobs.JobWorkerSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 101ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 8 ║ 33 ║ 33 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.mapper.MapperSpec CFML Engine: Lucee 7.0.1.100 Duration: 11ms Labels: @@ -361,9 +405,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.MappingSpec +Bundle: wheels.tests.specs.mapper.MappingSpec CFML Engine: Lucee 7.0.1.100 -Duration: 9ms +Duration: 11ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -372,9 +416,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.MatchingSpec +Bundle: wheels.tests.specs.mapper.MatchingSpec CFML Engine: Lucee 7.0.1.100 -Duration: 39ms +Duration: 47ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -383,9 +427,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.NestedResourcesSpec +Bundle: wheels.tests.specs.mapper.NestedResourcesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 101ms +Duration: 97ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -394,7 +438,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.ResourcesSpec +Bundle: wheels.tests.specs.mapper.ResourcesSpec CFML Engine: Lucee 7.0.1.100 Duration: 31ms Labels: @@ -405,9 +449,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.RootSpec +Bundle: wheels.tests.specs.mapper.RootSpec CFML Engine: Lucee 7.0.1.100 -Duration: 7ms +Duration: 5ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -416,7 +460,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.UtilsSpec +Bundle: wheels.tests.specs.mapper.UtilsSpec CFML Engine: Lucee 7.0.1.100 Duration: 15ms Labels: @@ -427,7 +471,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapper.WildcardSpec +Bundle: wheels.tests.specs.mapper.WildcardSpec CFML Engine: Lucee 7.0.1.100 Duration: 17ms Labels: @@ -438,9 +482,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapperModernSpec +Bundle: wheels.tests.specs.mapperModernSpec CFML Engine: Lucee 7.0.1.100 -Duration: 50ms +Duration: 64ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -449,9 +493,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.mapperSpec +Bundle: wheels.tests.specs.mapperSpec CFML Engine: Lucee 7.0.1.100 -Duration: 125ms +Duration: 124ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -460,9 +504,31 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.migrator.migration.mysqlTextSizesSpec +Bundle: wheels.tests.specs.middleware.MultiTenantIntegrationSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 96ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 1 ║ 9 ║ 9 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.middleware.TenantResolverSpec CFML Engine: Lucee 7.0.1.100 -Duration: 222ms +Duration: 9ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 5 ║ 10 ║ 10 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.migrator.migration.mysqlTextSizesSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 213ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -471,9 +537,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.migrator.migrationSpec +Bundle: wheels.tests.specs.migrator.migrationSpec CFML Engine: Lucee 7.0.1.100 -Duration: 1021ms +Duration: 920ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -482,9 +548,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.migrator.migratorSpec +Bundle: wheels.tests.specs.migrator.migratorSpec CFML Engine: Lucee 7.0.1.100 -Duration: 426ms +Duration: 299ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -493,9 +559,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.associationsSpec +Bundle: wheels.tests.specs.model.associationsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 605ms +Duration: 600ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -504,9 +570,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.calculationsSpec +Bundle: wheels.tests.specs.model.calculationsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 189ms +Duration: 117ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -515,9 +581,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.callbacksSpec +Bundle: wheels.tests.specs.model.callbacksSpec CFML Engine: Lucee 7.0.1.100 -Duration: 429ms +Duration: 297ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -526,9 +592,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.crudSpec +Bundle: wheels.tests.specs.model.crudSpec CFML Engine: Lucee 7.0.1.100 -Duration: 1210ms +Duration: 1082ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -537,9 +603,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.deleteSpec +Bundle: wheels.tests.specs.model.deleteSpec CFML Engine: Lucee 7.0.1.100 -Duration: 139ms +Duration: 170ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -548,9 +614,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.errorsSpec +Bundle: wheels.tests.specs.model.errorsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 86ms +Duration: 111ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -559,9 +625,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.miscellaneousSpec +Bundle: wheels.tests.specs.model.miscellaneousSpec CFML Engine: Lucee 7.0.1.100 -Duration: 74ms +Duration: 107ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -570,9 +636,20 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.nestedpropertiesSpec +Bundle: wheels.tests.specs.model.MultiTenantSpec +CFML Engine: Lucee 7.0.1.100 +Duration: 16ms +Labels: +╔═══════════════════════════════════════════════════════════╗ +║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ +╠═══════════════════════════════════════════════════════════╣ +║ 7 ║ 14 ║ 14 ║ 0 ║ 0 ║ 0 ║ +╚═══════════════════════════════════════════════════════════╝ + + +Bundle: wheels.tests.specs.model.nestedpropertiesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 610ms +Duration: 686ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -581,9 +658,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.onmissingmethod.belongsToSpec +Bundle: wheels.tests.specs.model.onmissingmethod.belongsToSpec CFML Engine: Lucee 7.0.1.100 -Duration: 36ms +Duration: 65ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -592,9 +669,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.onmissingmethod.hasManySpec +Bundle: wheels.tests.specs.model.onmissingmethod.hasManySpec CFML Engine: Lucee 7.0.1.100 -Duration: 163ms +Duration: 224ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -603,9 +680,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.onmissingmethod.hasOneSpec +Bundle: wheels.tests.specs.model.onmissingmethod.hasOneSpec CFML Engine: Lucee 7.0.1.100 -Duration: 111ms +Duration: 125ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -614,9 +691,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.propertiesSpec +Bundle: wheels.tests.specs.model.propertiesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 429ms +Duration: 544ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -625,9 +702,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.raceconditionSpec +Bundle: wheels.tests.specs.model.raceconditionSpec CFML Engine: Lucee 7.0.1.100 -Duration: 133ms +Duration: 162ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -636,20 +713,20 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.raisedErrorsSpec +Bundle: wheels.tests.specs.model.raisedErrorsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 26ms +Duration: 28ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ ╠═══════════════════════════════════════════════════════════╣ -║ 1 ║ 5 ║ 5 ║ 0 ║ 0 ║ 0 ║ +║ 1 ║ 6 ║ 6 ║ 0 ║ 0 ║ 0 ║ ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.readSpec +Bundle: wheels.tests.specs.model.readSpec CFML Engine: Lucee 7.0.1.100 -Duration: 277ms +Duration: 271ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -658,20 +735,20 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.sqlSpec +Bundle: wheels.tests.specs.model.sqlSpec CFML Engine: Lucee 7.0.1.100 -Duration: 74ms +Duration: 49ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ ╠═══════════════════════════════════════════════════════════╣ -║ 1 ║ 10 ║ 10 ║ 0 ║ 0 ║ 0 ║ +║ 1 ║ 11 ║ 11 ║ 0 ║ 0 ║ 0 ║ ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.transactionsSpec +Bundle: wheels.tests.specs.model.transactionsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 477ms +Duration: 408ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -680,9 +757,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.useindexSpec +Bundle: wheels.tests.specs.model.useindexSpec CFML Engine: Lucee 7.0.1.100 -Duration: 70ms +Duration: 59ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -691,9 +768,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.validationsSpec +Bundle: wheels.tests.specs.model.validationsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 1516ms +Duration: 1328ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -702,7 +779,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.model.viewsSpec +Bundle: wheels.tests.specs.model.viewsSpec CFML Engine: Lucee 7.0.1.100 Duration: 74ms Labels: @@ -713,9 +790,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.pluginsSpec +Bundle: wheels.tests.specs.pluginsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 399ms +Duration: 363ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -724,9 +801,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.routingSpec +Bundle: wheels.tests.specs.routingSpec CFML Engine: Lucee 7.0.1.100 -Duration: 36ms +Duration: 21ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -735,9 +812,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.assetsSpec +Bundle: wheels.tests.specs.view.assetsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 788ms +Duration: 705ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -746,7 +823,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.autoLinkSpec +Bundle: wheels.tests.specs.view.autoLinkSpec CFML Engine: Lucee 7.0.1.100 Duration: 8ms Labels: @@ -757,9 +834,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.checkboxSpec +Bundle: wheels.tests.specs.view.checkboxSpec CFML Engine: Lucee 7.0.1.100 -Duration: 30ms +Duration: 27ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -768,9 +845,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.contentSpec +Bundle: wheels.tests.specs.view.contentSpec CFML Engine: Lucee 7.0.1.100 -Duration: 97ms +Duration: 96ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -779,7 +856,7 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.csrfSpec +Bundle: wheels.tests.specs.view.csrfSpec CFML Engine: Lucee 7.0.1.100 Duration: 9ms Labels: @@ -790,9 +867,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.dateselectSpec +Bundle: wheels.tests.specs.view.dateselectSpec CFML Engine: Lucee 7.0.1.100 -Duration: 111ms +Duration: 84ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -801,9 +878,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.datesSpec +Bundle: wheels.tests.specs.view.datesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 51ms +Duration: 44ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -812,9 +889,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.errorsSpec +Bundle: wheels.tests.specs.view.errorsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 56ms +Duration: 38ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -823,9 +900,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.flashMessagesSpec +Bundle: wheels.tests.specs.view.flashMessagesSpec CFML Engine: Lucee 7.0.1.100 -Duration: 10ms +Duration: 15ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -834,9 +911,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.formsdateobjectSpec +Bundle: wheels.tests.specs.view.formsdateobjectSpec CFML Engine: Lucee 7.0.1.100 -Duration: 172ms +Duration: 144ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -845,9 +922,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.formsdateplainSpec +Bundle: wheels.tests.specs.view.formsdateplainSpec CFML Engine: Lucee 7.0.1.100 -Duration: 353ms +Duration: 271ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -856,9 +933,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.formsdateSpec +Bundle: wheels.tests.specs.view.formsdateSpec CFML Engine: Lucee 7.0.1.100 -Duration: 23ms +Duration: 5ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -867,9 +944,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.formsSpec +Bundle: wheels.tests.specs.view.formsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 334ms +Duration: 436ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -878,9 +955,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.html5FormHelpersSpec +Bundle: wheels.tests.specs.view.html5FormHelpersSpec CFML Engine: Lucee 7.0.1.100 -Duration: 53ms +Duration: 46ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -889,9 +966,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.linksSpec +Bundle: wheels.tests.specs.view.linksSpec CFML Engine: Lucee 7.0.1.100 -Duration: 117ms +Duration: 126ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -900,9 +977,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.miscellaneousSpec +Bundle: wheels.tests.specs.view.miscellaneousSpec CFML Engine: Lucee 7.0.1.100 -Duration: 51ms +Duration: 35ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -911,9 +988,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.sanitizeSpec +Bundle: wheels.tests.specs.view.sanitizeSpec CFML Engine: Lucee 7.0.1.100 -Duration: 13ms +Duration: 8ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -922,9 +999,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.textfieldSpec +Bundle: wheels.tests.specs.view.textfieldSpec CFML Engine: Lucee 7.0.1.100 -Duration: 11ms +Duration: 8ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -933,9 +1010,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.textSpec +Bundle: wheels.tests.specs.view.textSpec CFML Engine: Lucee 7.0.1.100 -Duration: 32ms +Duration: 20ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ @@ -944,9 +1021,9 @@ Labels: ╚═══════════════════════════════════════════════════════════╝ -Bundle: wheels.tests_testbox.specs.view.urlsSpec +Bundle: wheels.tests.specs.view.urlsSpec CFML Engine: Lucee 7.0.1.100 -Duration: 100ms +Duration: 84ms Labels: ╔═══════════════════════════════════════════════════════════╗ ║ Suites ║ Specs ║ Passed ║ Failed ║ Errored ║ Skipped ║ diff --git a/.github/workflow-results/test-rustcfml.md b/.github/workflow-results/test-rustcfml.md new file mode 100644 index 0000000000..9e84dbef0c --- /dev/null +++ b/.github/workflow-results/test-rustcfml.md @@ -0,0 +1,22 @@ +# RustCFML Compatibility Report (Experimental) + +**Date:** 2026-05-18 12:36:58 UTC +**Commit:** bc0c04c68ec548a7d3a5cb056869ccf1b389d68c +**Branch:** claude/evaluate-rustcfml-feasibility-40oUw +**Run:** [#1](https://github.com/wheels-dev/wheels/actions/runs/26033864937) + +## Stage Results + +| Stage | Result | +|-------|--------| +| Docker build | success | +| Server startup | skipped | +| Smoke test | skipped | +| Test suite | skipped | + + +## Container Logs + +``` +Error response from daemon: No such container: wheels-rustcfml-1 +``` diff --git a/.github/workflows/test-rustcfml.yml b/.github/workflows/test-rustcfml.yml new file mode 100644 index 0000000000..ee747ecea4 --- /dev/null +++ b/.github/workflows/test-rustcfml.yml @@ -0,0 +1,239 @@ +name: Test RustCFML Compatibility (Experimental) + +on: + push: + branches: + - 'claude/**' + workflow_dispatch: + +permissions: + contents: write + +jobs: + test-rustcfml: + name: RustCFML + SQLite (experimental) + runs-on: ubuntu-latest + continue-on-error: true + env: + PORT: 60100 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Build RustCFML image + id: build + continue-on-error: true + run: | + echo "Building RustCFML Docker image (this may take several minutes on first run)..." + docker compose build rustcfml 2>&1 | tail -20 + echo "build_ok=$?" >> $GITHUB_OUTPUT + + - name: Start RustCFML + if: steps.build.outcome == 'success' + run: docker compose up -d rustcfml + + - name: Wait for RustCFML to be ready + if: steps.build.outcome == 'success' + id: health + continue-on-error: true + run: | + echo "Waiting for RustCFML on port ${PORT}..." + MAX_WAIT=30 + WAIT_COUNT=0 + while [ "$WAIT_COUNT" -lt "$MAX_WAIT" ]; do + WAIT_COUNT=$((WAIT_COUNT + 1)) + HTTP_CODE=$(curl -s -o /dev/null --connect-timeout 2 --max-time 5 \ + -w "%{http_code}" "http://localhost:${PORT}/" 2>/dev/null || echo "000") + echo "Attempt ${WAIT_COUNT}/${MAX_WAIT}: HTTP ${HTTP_CODE}" + if echo "$HTTP_CODE" | grep -q "200\|404\|302\|500"; then + echo "RustCFML is responding (HTTP ${HTTP_CODE})" + echo "ready=true" >> $GITHUB_OUTPUT + exit 0 + fi + sleep 3 + done + echo "RustCFML did not become ready within ${MAX_WAIT} attempts" + echo "ready=false" >> $GITHUB_OUTPUT + + - name: Smoke test - basic CFML execution + if: steps.health.outcome == 'success' && steps.health.outputs.ready == 'true' + id: smoke + continue-on-error: true + run: | + echo "=== Smoke test: basic page load ===" + HTTP_CODE=$(curl -s -o /tmp/smoke-result.txt --max-time 30 \ + -w "%{http_code}" "http://localhost:${PORT}/" || echo "000") + echo "Root page: HTTP ${HTTP_CODE}" + if [ -f /tmp/smoke-result.txt ]; then + head -50 /tmp/smoke-result.txt + fi + + echo "" + echo "=== Smoke test: reload request ===" + HTTP_CODE=$(curl -s -o /tmp/reload-result.txt --max-time 60 \ + -w "%{http_code}" "http://localhost:${PORT}/?reload=true" || echo "000") + echo "Reload: HTTP ${HTTP_CODE}" + if [ -f /tmp/reload-result.txt ]; then + head -50 /tmp/reload-result.txt + fi + + - name: Run test suite + if: steps.health.outcome == 'success' && steps.health.outputs.ready == 'true' + id: run-tests + continue-on-error: true + run: | + TEST_URL="http://localhost:${PORT}/wheels/core/tests?db=sqlite&format=json" + RESULT_FILE="/tmp/rustcfml-sqlite-result.txt" + + echo "Running test suite: ${TEST_URL}" + echo "This may take several minutes..." + + HTTP_CODE=$(curl -s -o "${RESULT_FILE}" \ + --max-time 900 \ + --write-out "%{http_code}" \ + "${TEST_URL}" || echo "000") + + echo "HTTP Code: ${HTTP_CODE}" + echo "http_code=${HTTP_CODE}" >> $GITHUB_OUTPUT + + if [ -f "$RESULT_FILE" ]; then + # Try to parse as JSON for summary stats + python3 -c " + import json, sys + try: + d = json.load(open('$RESULT_FILE')) + total = int(d.get('totalSpecs', 0)) + passed = int(d.get('totalPass', 0)) + failed = int(d.get('totalFail', 0)) + errors = int(d.get('totalError', 0)) + skipped = int(d.get('totalSkipped', 0)) + print(f'Total: {total} | Passed: {passed} | Failed: {failed} | Errors: {errors} | Skipped: {skipped}') + pct = round(passed / total * 100, 1) if total > 0 else 0 + print(f'Pass rate: {pct}%') + except Exception as e: + print(f'Could not parse JSON results: {e}') + # Show first 200 chars of response + with open('$RESULT_FILE') as f: + content = f.read() + print(f'Response preview ({len(content)} bytes):') + print(content[:500]) + " 2>&1 || echo "Result parsing failed" + else + echo "No result file generated" + fi + + - name: Generate compatibility report + if: always() + run: | + RESULTS_DIR=".github/workflow-results" + RESULTS_FILE="${RESULTS_DIR}/test-rustcfml.md" + mkdir -p "$RESULTS_DIR" + + { + echo "# RustCFML Compatibility Report (Experimental)" + echo "" + echo "**Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" + echo "**Commit:** ${{ github.sha }}" + echo "**Branch:** ${{ github.ref_name }}" + echo "**Run:** [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" + echo "" + echo "## Stage Results" + echo "" + echo "| Stage | Result |" + echo "|-------|--------|" + echo "| Docker build | ${{ steps.build.outcome }} |" + echo "| Server startup | ${{ steps.health.outcome }} |" + echo "| Smoke test | ${{ steps.smoke.outcome }} |" + echo "| Test suite | ${{ steps.run-tests.outcome }} |" + echo "" + } > "$RESULTS_FILE" + + # Add test results if available + if [ -f "/tmp/rustcfml-sqlite-result.txt" ]; then + { + echo "## Test Results" + echo "" + python3 -c " + import json, sys + try: + d = json.load(open('/tmp/rustcfml-sqlite-result.txt')) + total = int(d.get('totalSpecs', 0)) + passed = int(d.get('totalPass', 0)) + failed = int(d.get('totalFail', 0)) + errors = int(d.get('totalError', 0)) + skipped = int(d.get('totalSkipped', 0)) + pct = round(passed / total * 100, 1) if total > 0 else 0 + print(f'- **Total specs:** {total}') + print(f'- **Passed:** {passed} ({pct}%)') + print(f'- **Failed:** {failed}') + print(f'- **Errors:** {errors}') + print(f'- **Skipped:** {skipped}') + print() + # List first 20 failures + if failed > 0 or errors > 0: + print('### First failures/errors') + print() + count = 0 + for b in d.get('bundleStats', []): + for s in b.get('suiteStats', []): + for sp in s.get('specStats', []): + if sp.get('status') in ('Failed', 'Error') and count < 20: + print(f'- **{sp.get(\"name\", \"unknown\")}**: {sp.get(\"failMessage\", \"\")}') + count += 1 + if count == 0: + # Check nested suites + for b in d.get('bundleStats', []): + for s in b.get('suiteStats', []): + for child in s.get('suiteStats', []): + for sp in child.get('specStats', []): + if sp.get('status') in ('Failed', 'Error') and count < 20: + print(f'- **{sp.get(\"name\", \"unknown\")}**: {sp.get(\"failMessage\", \"\")}') + count += 1 + except Exception as e: + print(f'Could not parse results: {e}') + " 2>&1 || echo "Parse error" + } >> "$RESULTS_FILE" + fi + + # Add debug info + { + echo "" + echo "## Container Logs" + echo "" + echo '```' + docker logs wheels-rustcfml-1 2>&1 | tail -80 || echo "No container logs available" + echo '```' + } >> "$RESULTS_FILE" + + - name: Debug information + if: always() + run: | + echo "=== Docker Container Status ===" + docker ps -a --filter "name=rustcfml" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" + + echo -e "\n=== RustCFML Container Logs (last 80 lines) ===" + docker logs wheels-rustcfml-1 2>&1 | tail -80 || echo "No logs available" + + - name: Commit compatibility report + if: always() + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add ".github/workflow-results/test-rustcfml.md" + + if git diff --cached --quiet; then + echo "No changes to commit" + else + git commit -m "ci: add RustCFML compatibility report [skip ci]" + git push origin HEAD:${{ github.ref_name }} + fi + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: rustcfml-test-results + path: | + /tmp/rustcfml-sqlite-result.txt + /tmp/smoke-result.txt + /tmp/reload-result.txt diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 228d23d8e4..ea02d658bb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,6 +22,9 @@ jobs: cfengine: ["lucee5", "lucee6", "lucee7", "adobe2018", "adobe2021", "adobe2023", "adobe2025", "boxlang"] experimental: [false] + include: + - cfengine: rustcfml + experimental: true env: PORT_lucee5: 60005 PORT_lucee6: 60006 @@ -31,6 +34,7 @@ jobs: PORT_adobe2023: 62023 PORT_adobe2025: 62025 PORT_boxlang: 60001 + PORT_rustcfml: 60100 steps: - name: Checkout Repository uses: actions/checkout@v5 @@ -50,6 +54,10 @@ jobs: # adobe2018 also excludes sqlite DATABASES="mysql,postgres,sqlserver,oracle" ;; + rustcfml) + # RustCFML uses native Rust drivers, not JDBC — start with SQLite only + DATABASES="sqlite" + ;; esac echo "databases=${DATABASES}" >> $GITHUB_OUTPUT @@ -63,7 +71,13 @@ jobs: -O ./.engine/${{ matrix.cfengine }}/WEB-INF/lib/ojdbc10.jar - name: Start CF engine - run: docker compose build --no-cache ${{ matrix.cfengine }} && docker compose up -d ${{ matrix.cfengine }} + run: | + # RustCFML builds Rust from source — allow Docker layer caching to avoid 15+ min rebuild + if [ "${{ matrix.cfengine }}" = "rustcfml" ]; then + docker compose build ${{ matrix.cfengine }} && docker compose up -d ${{ matrix.cfengine }} + else + docker compose build --no-cache ${{ matrix.cfengine }} && docker compose up -d ${{ matrix.cfengine }} + fi - name: Start all databases run: | @@ -514,7 +528,7 @@ jobs: MATRIX_MD="${MATRIX_MD} |--------|:-----:|:----------:|:----------:|:--:|:------:|:------:|" - for engine in lucee5 lucee6 lucee7 adobe2018 adobe2021 adobe2023 adobe2025 boxlang; do + for engine in lucee5 lucee6 lucee7 adobe2018 adobe2021 adobe2023 adobe2025 boxlang rustcfml; do ROW="| **${engine}** |" for db in mysql postgres sqlserver h2 oracle sqlite; do FILE="results/test-results-${engine}/${engine}-${db}-result.txt" diff --git a/compose.yml b/compose.yml index f83279f205..c55aa61d27 100644 --- a/compose.yml +++ b/compose.yml @@ -259,6 +259,24 @@ services: networks: - wheels-network + rustcfml: + build: + context: ./ + dockerfile: ./tools/docker/rustcfml/Dockerfile + image: wheels-test-rustcfml:v0.1.0 + volumes: + - ./:/wheels-test-suite + - type: bind + source: ./tools/docker/rustcfml/settings.cfm + target: /wheels-test-suite/config/settings.cfm + - type: bind + source: ./tools/docker/rustcfml/app.cfm + target: /wheels-test-suite/config/app.cfm + ports: + - "60100:60100" + networks: + - wheels-network + mysql: image: mysql:9 restart: always diff --git a/docs/plans/rustcfml-feasibility-assessment.md b/docs/plans/rustcfml-feasibility-assessment.md new file mode 100644 index 0000000000..6944da9c31 --- /dev/null +++ b/docs/plans/rustcfml-feasibility-assessment.md @@ -0,0 +1,195 @@ +# RustCFML Feasibility Assessment for Wheels Framework + +**Date:** 2026-05-18 (updated from initial 2026-03-15 evaluation) +**Project:** [pixl8/RustCFML](https://github.com/pixl8/RustCFML) +**Version Evaluated:** 0.9.1 (released May 3, 2026) +**Previous Version Evaluated:** 0.4.0 (March 14, 2026) + +## Executive Summary + +RustCFML is a **complete CFML interpreter written in Rust** — not a library or extension. It replaces Lucee/ACF as a runtime, compiling CFML to bytecode executed on a stack-based VM with no JVM dependency. + +**Updated Verdict: Feasibility has improved significantly. Several previous blockers are now resolved. A proof-of-concept trial is now reasonable.** + +Since the initial evaluation two months ago, RustCFML has gone from v0.4.0 to v0.9.1 (14 releases, 108 commits), addressing three of the four critical blockers identified previously. The project has also grown from 3 to 20 stars and gained its first fork, indicating rising community awareness. + +## Progress Since Initial Evaluation (March 2026) + +### Previously Identified Blockers — Status Update + +| Blocker | March Status | May Status | Impact | +|---------|-------------|------------|--------| +| **`onMissingMethod`** | Unknown/unlikely | **Implemented** | Wheels' dynamic finders (`findAllByEmail()`) may now work | +| **`cflock`** | Unknown | **Implemented** (RwLock-based) | Thread-safe rate limiting, caching, initialization possible | +| **`getMetadata`** | Unknown | **Implemented** | Model configuration, routing, test discovery possible | +| **`CreateObject`** | Not supported | **Implemented** (for components) | Component instantiation works | +| **Java interop (`CreateObject("java", ...)`)** | Not supported | **Still not supported** | Remains a blocker for `ConcurrentHashMap` usage | +| **`cfthread` (true concurrency)** | Sequential only | **Still sequential** | Background jobs would block | +| **Query-of-Queries** | Not supported | **Still not supported** | Low impact for Wheels | + +### New Capabilities Since v0.4.0 + +- **`cflock`** with real named locks using RwLock-based concurrency +- **`onMissingMethod`** for dynamic method dispatch +- **`getMetadata`** for component introspection +- **`createObject`** for component instantiation +- **`cfinvoke`** tag support +- **Session lifecycle** (`onSessionStart`/`onSessionEnd`) +- **`cfthread`** tag (sequential model) +- **`cfzip`** operations +- **`cfexecute`** for OS command execution +- **`cfstoredproc`/`cfprocparam`** for stored procedures +- **Custom tags** with `cf_` prefix +- **`cfimport`** with `.tld` support +- **Bytecode caching** with modification-time tracking (no recompilation for unchanged files) +- **Performance tuning** across VM hot paths (v0.8.0-v0.9.0 focus) +- **CFMX_COMPAT** encryption algorithm support +- **Taffy framework** compatibility (claimed feature-complete) + +### Project Growth Metrics + +| Indicator | March 2026 | May 2026 | Change | +|-----------|-----------|----------|--------| +| Version | 0.4.0 | 0.9.1 | 14 releases in 2 months | +| Stars | 3 | 20 | 7x increase | +| Forks | 0 | 1 | First community fork | +| Commits | 39 | 108 | 69 new commits | +| Test assertions | 1,181 / 89 suites | 1,181+ / 89+ suites | Baseline maintained | +| Release cadence | ~weekly | ~weekly | Consistent | + +## Revised Compatibility Analysis + +### Now Supported (previously blocked or unknown) + +| Wheels Feature | RustCFML Support | Notes | +|---------------|-----------------|-------| +| Dynamic finders (`findAllByEmail`) | `onMissingMethod` implemented | Needs behavioral verification | +| Thread-safe middleware | `cflock` with RwLock | Real concurrency, not just advisory | +| Component metadata inspection | `getMetadata` implemented | Model config, test discovery | +| Component instantiation | `createObject` for components | CFC creation works | +| CSRF tokens | `csrfGenerateToken`/`csrfVerifyToken` | Behavioral compat with Lucee TBD | +| Encrypt/Decrypt | AES, DES, DESEDE, Blowfish, CFMX_COMPAT | Cookie compat needs testing | +| Session management | Full lifecycle with CFID cookie | `onSessionStart`/`onSessionEnd` | +| Transaction management | `cftransaction` | Rollback/savepoint needs testing | +| Named locks | `cflock` (read/write) | RwLock-based, real concurrency | +| Password hashing | bcrypt, scrypt, argon2, PBKDF2 | Better than stock Lucee | +| Stored procedures | `cfstoredproc`/`cfprocparam` | Database-dependent | +| File operations | 23+ file I/O functions | Upload, read, write, directory ops | +| Caching | 8 cache functions | `cachePut`, `cacheGet`, etc. | +| Error context | `cfcatch.tagContext` with stack traces | Line/column/template info | + +### Remaining Blockers + +| Wheels Requirement | Status | Severity | Workaround | +|-------------------|--------|----------|------------| +| **`CreateObject("java", ...)`** | Not supported | **Medium** | Replace `ConcurrentHashMap` with CFML struct + `cflock`. Replace `StringBuilder` with string concatenation or array join. Only 2-3 call sites in Wheels core. | +| **`cfthread` true concurrency** | Sequential only | **Low** | Background jobs (`wheels.Job`) would block, but most Wheels apps don't use in-request threading. Worker processes are typically separate. | +| **Query-of-Queries** | Not supported | **Low** | Wheels rarely uses QoQ. Any instances could be rewritten as database queries. | +| **`GetComponentMetaData`** (as distinct from `getMetadata`) | Unconfirmed | **Low** | `getMetadata` is confirmed; `GetComponentMetaData` may work as an alias or may not be needed. | + +### Critical Behavioral Questions (need testing) + +These features are nominally supported but Wheels depends on specific behavioral contracts: + +1. **`onMissingMethod` argument passing**: Wheels passes `missingMethodName` and `missingMethodArguments` — does RustCFML match this signature exactly? +2. **`getMetadata` depth**: Wheels inspects `functions`, `extends`, `name`, `fullname`, `path` from metadata. How complete is the returned struct? +3. **`Encrypt`/`Decrypt` output format**: CSRF cookies encrypted on Lucee must be decryptable on RustCFML if migrating a running app (probably not a concern for fresh deploys). +4. **Application scope persistence**: Wheels stores extensive config in `application.$wheels`. Does `application` scope persist correctly across requests with the same semantics? +5. **`cflock` timeout behavior**: Wheels uses `timeout=1` on rate limiter locks. Does RustCFML respect lock timeout and fail gracefully? +6. **Scope resolution order**: Wheels depends on specific scope precedence (`local` > `arguments` > `variables`). CFML engines vary subtly here. +7. **`isInstanceOf` behavior**: Wheels uses this for type checking in DI and model resolution. +8. **Interface `implements` enforcement**: Wheels middleware uses `implements="wheels.middleware.MiddlewareInterface"`. + +## Wheels Code Changes Needed + +### Minimal changes (to eliminate remaining blockers) + +``` +vendor/wheels/middleware/RateLimiter.cfc (line 55): + - CreateObject("java", "java.util.concurrent.ConcurrentHashMap").init() + + StructNew() // with cflock protection (already present) + +vendor/wheels/Channel.cfc: + - Same ConcurrentHashMap replacement + +vendor/wheels/model/read.cfc (if StringBuilder used): + - Replace java.lang.StringBuilder with array + ArrayToList +``` + +These are 2-3 small, isolated changes that would make the Wheels core Java-interop-free without affecting Lucee/ACF compatibility (struct + cflock works on all engines). + +### No changes needed for + +- CSRF protection (uses standard `Encrypt`/`Decrypt`/`GenerateSecretKey`/`CsrfGenerateToken`) +- Hash-based cache keys (uses standard `Hash()`) +- Model identification and transactions (uses standard `Hash()`) +- Route matching and dispatch (pure CFML) +- View rendering (pure CFML) +- Migration system (uses `queryExecute` which is supported) +- Validation framework (pure CFML) +- Association/relationship definitions (pure CFML, depends on `onMissingMethod`) + +## Performance Implications for Wheels + +| Scenario | Expected Benefit | Confidence | +|----------|-----------------|------------| +| Cold start (container/serverless) | **Massive** — instant vs ~15s JVM warmup | High | +| Memory per instance | **44x reduction** — 8 MB vs 350 MB | High (trivial workloads verified) | +| Simple page renders | **3x throughput** — 1,949 vs 635 req/s | High | +| ORM-heavy pages | **Unknown** — dynamic method dispatch overhead not benchmarked | Low | +| Complex model graphs | **Unknown** — component instantiation + metadata perf not tested | Low | +| Concurrent requests | **Uncertain** — Axum is async but cfthread is sequential | Medium | + +## Recommendations (Updated) + +### Immediate (now): Proof-of-concept trial + +The resolution of `onMissingMethod`, `cflock`, and `getMetadata` makes a PoC reasonable: + +1. **Build RustCFML from source** and attempt to boot the Wheels demo app (`app/`) +2. **Run the core test suite** against RustCFML to get a compatibility baseline +3. **Document failures** — categorize as (a) missing function, (b) behavioral difference, (c) Java interop dependency +4. **Estimate gap size** — if >80% of tests pass, active pursuit is justified + +### Short-term (1-3 months): Eliminate Java interop in Wheels core + +Regardless of RustCFML adoption, removing `CreateObject("java", ...)` from the framework core is good hygiene: + +- Makes Wheels more portable across all CFML engines (including BoxLang) +- Only 2-3 call sites need changes +- The `cflock`-protected struct pattern already exists alongside the Java calls + +### Medium-term (3-6 months): Engage with Pixl8 + +If the PoC shows >80% compatibility: + +1. **File issues** for specific behavioral gaps discovered during testing +2. **Contribute test cases** from Wheels' test suite that exercise edge cases +3. **Explore adding Wheels/RustCFML to the CI compat matrix** as a soft-fail target (like Oracle) +4. **Document the "Wheels on RustCFML" story** for containerized/edge deployments + +### Long-term (6-12 months): Lightweight deployment target + +Position RustCFML as an optional deployment runtime for: +- **Docker/Kubernetes** — 8 MB image vs 350+ MB +- **Serverless/edge functions** — instant cold start +- **CI/test environments** — faster test cycles +- **API-only Wheels apps** — no view layer complexity + +## Risk Assessment + +| Risk | Likelihood | Impact | Mitigation | +|------|-----------|--------|------------| +| Project abandoned (single maintainer) | Medium | High | MIT license allows forking; Pixl8 is an established CFML shop | +| Behavioral incompatibilities surface at scale | High | Medium | Incremental adoption starting with simple apps | +| Performance gains disappear with complex apps | Medium | Low | Still wins on memory/startup even if throughput is similar | +| Breaking changes in pre-1.0 releases | High | Low | Pin versions; don't depend on internals | +| Community doesn't grow | Medium | Medium | Wheels adoption would itself grow the community | + +## Conclusion + +RustCFML has made remarkable progress in two months. The three most critical Wheels blockers — `onMissingMethod`, `cflock`, and `getMetadata` — are now implemented. The remaining gap (Java interop) affects only 2-3 isolated call sites in Wheels core, and the fix is straightforward and engine-agnostic. + +**The project has moved from "watch and wait" to "try it and see."** A proof-of-concept attempt to boot Wheels on RustCFML is now the right next step. The outcome will determine whether this becomes a real deployment option or needs another 6-12 months of runtime maturation. + +The 44x memory reduction and instant cold start alone would make RustCFML a compelling option for containerized Wheels deployments — if the compatibility gap can be bridged. diff --git a/tools/docker/rustcfml/Dockerfile b/tools/docker/rustcfml/Dockerfile new file mode 100644 index 0000000000..ad5544cd15 --- /dev/null +++ b/tools/docker/rustcfml/Dockerfile @@ -0,0 +1,33 @@ +# Stage 1: Build RustCFML from source +FROM rust:1.78-bookworm AS builder + +ARG RUSTCFML_VERSION=v0.9.1 + +RUN apt-get update && apt-get install -y \ + git pkg-config libssl-dev libsqlite3-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN git clone --depth 1 --branch ${RUSTCFML_VERSION} \ + https://github.com/pixl8/RustCFML.git /build + +WORKDIR /build +RUN cargo build --release --features "database,xml" + +# Stage 2: Minimal runtime image +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y \ + sqlite3 libsqlite3-0 libssl3 curl ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /build/target/release/rustcfml /usr/local/bin/rustcfml + +RUN sqlite3 /app/wheelstestdb.db "SELECT 1;" \ + && sqlite3 /app/wheelstestdb_tenant_b.db "SELECT 1;" + +ENV PORT=60100 +WORKDIR /wheels-test-suite + +EXPOSE ${PORT} + +CMD ["rustcfml", "--serve", "public", "--port", "60100"] diff --git a/tools/docker/rustcfml/app.cfm b/tools/docker/rustcfml/app.cfm new file mode 100644 index 0000000000..c013ca66a7 --- /dev/null +++ b/tools/docker/rustcfml/app.cfm @@ -0,0 +1,17 @@ + + /* + RustCFML datasource configuration. + Overrides config/app.cfm for RustCFML which uses native Rust database + drivers (rusqlite) instead of JDBC. + */ + + this.datasources["wheelstestdb_sqlite"] = { + database: "/app/wheelstestdb.db", + type: "sqlite" + }; + + this.datasources["wheelstestdb_sqlite_tenant_b"] = { + database: "/app/wheelstestdb_tenant_b.db", + type: "sqlite" + }; + diff --git a/tools/docker/rustcfml/settings.cfm b/tools/docker/rustcfml/settings.cfm new file mode 100644 index 0000000000..fe61927c3c --- /dev/null +++ b/tools/docker/rustcfml/settings.cfm @@ -0,0 +1,15 @@ + + /* + RustCFML-specific settings for the Wheels test suite. + Only SQLite is configured — RustCFML uses native Rust database drivers, + not JDBC, so the datasource configuration differs from Lucee/ACF. + */ + + set(coreTestDataSourceName="wheelstestdb_sqlite"); + set(dataSourceName="wheelstestdb_sqlite"); + + set(URLRewriting="On"); + set(reloadPassword=""); + + // CLI-Appends-Here +