diff --git a/.github/workflows/commandbox-install-smoke.yml b/.github/workflows/commandbox-install-smoke.yml index df78ec3430..ac8703a268 100644 --- a/.github/workflows/commandbox-install-smoke.yml +++ b/.github/workflows/commandbox-install-smoke.yml @@ -80,8 +80,27 @@ jobs: # Pin the version the prepare scripts stamp into the artifacts. PKG_VERSION: "0.0.0-cismoke" steps: + # The CommandBox image ships without git, and actions/checkout without git + # falls back to the REST-API tarball — which honors .gitattributes + # export-ignore, and this repo export-ignores tools/ and cli/. That left + # this job's workspace without the very build scripts and templates it + # exists to test (prepare-base.sh: No such file or directory, exit 127, + # on every run since the job was added). Install git BEFORE checkout so + # it performs a real clone. + - name: Ensure git is available (checkout must not fall back to the export-ignored tarball) + run: | + command -v git >/dev/null 2>&1 || { + apt-get update -y && apt-get install -y --no-install-recommends git ca-certificates + } + git --version + - uses: actions/checkout@v5 + - name: Assert the export-ignored paths actually checked out + run: | + test -f tools/build/scripts/prepare-base.sh || { + echo "::error::tools/ missing from workspace — checkout fell back to the export-ignored tarball again"; exit 1; } + # curl + jq are the only host tools the probes need; the CommandBox image # is Debian-based but minimal. Install defensively (no-op if present). - name: Ensure curl is available diff --git a/changelog.d/fix-dead-guide-urls.fixed.md b/changelog.d/fix-dead-guide-urls.fixed.md new file mode 100644 index 0000000000..6ec8a6507e --- /dev/null +++ b/changelog.d/fix-dead-guide-urls.fixed.md @@ -0,0 +1 @@ +- Repointed 16 dead `v4-0-0-snapshot`- and `3.1.0`-era guide URLs at live `guides.wheels.dev/v4-0-0/` pages: the scaffolded app's `config/settings.cfm`/`routes.cfm`/`environment.cfm` comments, three template READMEs (mailers/jobs/plugins), both `ConfigRoutes.txt` templates, two runtime CLI messages (`Module.cfc` install pointer, `Doctor.cfc` remediation), `cli/README.md`, the analyze report footer, and the demo app's config. `ConfigRoutesStaleDocUrlSpec` now structurally guards the template tree and known runtime-message files against reintroducing retired URL shapes. diff --git a/cli/README.md b/cli/README.md index f47e993565..bab58fd7c9 100644 --- a/cli/README.md +++ b/cli/README.md @@ -23,7 +23,7 @@ Both installers depend only on Java 21, which is pulled in automatically. ## Commands -See [the CLI command guides](https://guides.wheels.dev/v4-0-0-snapshot/command-line-tools/) or run `wheels --help` in your terminal. +See [the CLI command guides](https://guides.wheels.dev/v4-0-0/command-line-tools/) or run `wheels --help` in your terminal. ## Template Customization @@ -40,4 +40,4 @@ To customize a template: 2. Modify it to match your needs 3. The CLI will automatically use your custom template -See the [Template System Guide](https://guides.wheels.dev/v4-0-0-snapshot/command-line-tools/) for detailed documentation. +See the [Template System Guide](https://guides.wheels.dev/v4-0-0/command-line-tools/) for detailed documentation. diff --git a/cli/lucli/Module.cfc b/cli/lucli/Module.cfc index 359c329c60..25704db14b 100644 --- a/cli/lucli/Module.cfc +++ b/cli/lucli/Module.cfc @@ -6429,7 +6429,7 @@ component extends="modules.BaseModule" { out(" unzip wheels-core-.zip -d ~/.wheels/modules/wheels/vendor/"); out(" wheels new #appName#"); out(""); - out("See: https://guides.wheels.dev/v4-0-0-snapshot/start-here/installing/"); + out("See: https://guides.wheels.dev/v4-0-0/start-here/installing/"); throw( type="Wheels.FrameworkNotFound", diff --git a/cli/lucli/services/Doctor.cfc b/cli/lucli/services/Doctor.cfc index 46875fb5c2..135d110b24 100644 --- a/cli/lucli/services/Doctor.cfc +++ b/cli/lucli/services/Doctor.cfc @@ -660,7 +660,7 @@ component { recs, "Install or reinstall the Wheels CLI with a complete distribution, " & "or set WHEELS_FRAMEWORK_PATH to a vendor/wheels/ directory. " - & "See: https://guides.wheels.dev/v4-0-0-snapshot/start-here/installing/" + & "See: https://guides.wheels.dev/v4-0-0/start-here/installing/" ); } else if (findNoCase("Missing required directory", combined)) { arrayAppend(recs, "Run 'wheels new' to scaffold a complete project structure"); diff --git a/cli/lucli/templates/app/app/jobs/README.md b/cli/lucli/templates/app/app/jobs/README.md index 69e3c522b9..39ba8ac7e3 100644 --- a/cli/lucli/templates/app/app/jobs/README.md +++ b/cli/lucli/templates/app/app/jobs/README.md @@ -48,4 +48,4 @@ wheels generate migration create_wheels_jobs_table wheels migrate latest ``` -See [Background Jobs](https://wheels.dev/v4-0-0-snapshot/digging-deeper/) in the guides for retries, backoff, priority queues, and the monitoring dashboard. +See [Background Jobs](https://guides.wheels.dev/v4-0-0/digging-deeper/background-jobs/) in the guides for retries, backoff, priority queues, and the monitoring dashboard. diff --git a/cli/lucli/templates/app/app/mailers/README.md b/cli/lucli/templates/app/app/mailers/README.md index 82c52e0bd8..d1bc4c6b07 100644 --- a/cli/lucli/templates/app/app/mailers/README.md +++ b/cli/lucli/templates/app/app/mailers/README.md @@ -31,4 +31,4 @@ set(mailerSettings = { }); ``` -See [Sending Email](https://wheels.dev/v4-0-0-snapshot/digging-deeper/sending-email/) in the guides for the full walkthrough. +See [Sending Email](https://guides.wheels.dev/v4-0-0/digging-deeper/sending-email/) in the guides for the full walkthrough. diff --git a/cli/lucli/templates/app/app/plugins/README.md b/cli/lucli/templates/app/app/plugins/README.md index e158020221..f2183fccae 100644 --- a/cli/lucli/templates/app/app/plugins/README.md +++ b/cli/lucli/templates/app/app/plugins/README.md @@ -17,7 +17,7 @@ wheels stop && wheels start Note: the install verb is `add`, not `install`. -See [Packages](https://wheels.dev/v4-0-0-snapshot/digging-deeper/) in the guides for details. +See [Packages](https://guides.wheels.dev/v4-0-0/digging-deeper/packages/) in the guides for details. ## Migrating from a 3.x plugin diff --git a/cli/lucli/templates/app/app/snippets/ConfigRoutes.txt b/cli/lucli/templates/app/app/snippets/ConfigRoutes.txt index 4522a53d28..7220374991 100644 --- a/cli/lucli/templates/app/app/snippets/ConfigRoutes.txt +++ b/cli/lucli/templates/app/app/snippets/ConfigRoutes.txt @@ -2,7 +2,7 @@ // Use this file to add routes to your application and point the root route to a controller action. // Don't forget to issue a reload request (e.g. reload=true) after making changes. - // See https://guides.wheels.dev/v4-0-0-snapshot/handling-requests-with-controllers/routing for more info. + // See https://guides.wheels.dev/v4-0-0/basics/routing/ for more info. mapper() // CLI-Appends-Here diff --git a/cli/lucli/templates/app/config/environment.cfm b/cli/lucli/templates/app/config/environment.cfm index 222ae78a50..df4174e63b 100644 --- a/cli/lucli/templates/app/config/environment.cfm +++ b/cli/lucli/templates/app/config/environment.cfm @@ -2,7 +2,7 @@ // Use this file to set the current environment for your application. // You can set it to "development", "testing", "maintenance" or "production". // Don't forget to issue a reload request (e.g. reload=true) after making changes. -// See https://guides.wheels.dev/v4-0-0-snapshot/working-with-wheels/switching-environments for more info. +// See https://guides.wheels.dev/v4-0-0/core-concepts/environments-and-configuration/ for more info. // Below, we have set it to "development" for you since that is convenient when you are building your application. // We recommend that you change this to "production" when you're running your application live. diff --git a/cli/lucli/templates/app/config/routes.cfm b/cli/lucli/templates/app/config/routes.cfm index 283b3af077..a55cb64bf5 100644 --- a/cli/lucli/templates/app/config/routes.cfm +++ b/cli/lucli/templates/app/config/routes.cfm @@ -2,7 +2,7 @@ // Use this file to add routes to your application and point the root route to a controller action. // Don't forget to issue a reload request (e.g. reload=true) after making changes. - // See https://guides.wheels.dev/v4-0-0-snapshot/handling-requests-with-controllers/routing for more info. + // See https://guides.wheels.dev/v4-0-0/basics/routing/ for more info. mapper() // CLI-Appends-Here diff --git a/cli/lucli/templates/app/config/settings.cfm b/cli/lucli/templates/app/config/settings.cfm index c13d1d528f..27124f6d5a 100644 --- a/cli/lucli/templates/app/config/settings.cfm +++ b/cli/lucli/templates/app/config/settings.cfm @@ -3,7 +3,7 @@ Use this file to configure your application. You can also use the environment specific files (e.g. /config/production/settings.cfm) to override settings set here. Don't forget to issue a reload request (e.g. reload=true) after making changes. - See https://guides.wheels.dev/v4-0-0-snapshot/working-with-wheels/configuration-and-defaults for more info. + See https://guides.wheels.dev/v4-0-0/core-concepts/environments-and-configuration/ for more info. */ /* diff --git a/cli/src/commands/wheels/analyze/code.cfc b/cli/src/commands/wheels/analyze/code.cfc index 9a09a8a030..cd59f95a91 100644 --- a/cli/src/commands/wheels/analyze/code.cfc +++ b/cli/src/commands/wheels/analyze/code.cfc @@ -661,7 +661,7 @@ component extends="../base" { html &= ' diff --git a/cli/src/templates/ConfigRoutes.txt b/cli/src/templates/ConfigRoutes.txt index 4522a53d28..7220374991 100644 --- a/cli/src/templates/ConfigRoutes.txt +++ b/cli/src/templates/ConfigRoutes.txt @@ -2,7 +2,7 @@ // Use this file to add routes to your application and point the root route to a controller action. // Don't forget to issue a reload request (e.g. reload=true) after making changes. - // See https://guides.wheels.dev/v4-0-0-snapshot/handling-requests-with-controllers/routing for more info. + // See https://guides.wheels.dev/v4-0-0/basics/routing/ for more info. mapper() // CLI-Appends-Here diff --git a/config/environment.cfm b/config/environment.cfm index b1d7e5e97f..cc8cd3d1a0 100644 --- a/config/environment.cfm +++ b/config/environment.cfm @@ -2,7 +2,7 @@ // Use this file to set the current environment for your application. // You can set it to "development", "testing", "maintenance" or "production". // Don't forget to issue a reload request (e.g. reload=true) after making changes. -// See https://wheels.dev/3.1.0/guides/working-with-wheels/switching-environments for more info. +// See https://guides.wheels.dev/v4-0-0/core-concepts/environments-and-configuration/ for more info. // Below, we have set it to "development" for you since that is convenient when you are building your application. // We recommend that you change this to "production" when you're running your application live. diff --git a/config/routes.cfm b/config/routes.cfm index 193361273b..fd7b7faa36 100755 --- a/config/routes.cfm +++ b/config/routes.cfm @@ -1,7 +1,7 @@ // Use this file to add routes to your application and point the root route to a controller action. // Don't forget to issue a reload request (e.g. reload=true) after making changes. -// See https://wheels.dev/3.1.0/guides/handling-requests-with-controllers/routing for more info. +// See https://guides.wheels.dev/v4-0-0/basics/routing/ for more info. mapper() // CLI-Appends-Here diff --git a/config/settings.cfm b/config/settings.cfm index cf7ecb547f..0b3d81020a 100644 --- a/config/settings.cfm +++ b/config/settings.cfm @@ -3,7 +3,7 @@ Use this file to configure your application. You can also use the environment specific files (e.g. /config/production/settings.cfm) to override settings set here. Don't forget to issue a reload request (e.g. reload=true) after making changes. - See https://wheels.dev/3.1.0/guides/working-with-wheels/configuration-and-defaults for more info. + See https://guides.wheels.dev/v4-0-0/core-concepts/environments-and-configuration/ for more info. */ /* diff --git a/vendor/wheels/tests/specs/cli/ConfigRoutesStaleDocUrlSpec.cfc b/vendor/wheels/tests/specs/cli/ConfigRoutesStaleDocUrlSpec.cfc index 9c10d570fc..b226dcc05d 100644 --- a/vendor/wheels/tests/specs/cli/ConfigRoutesStaleDocUrlSpec.cfc +++ b/vendor/wheels/tests/specs/cli/ConfigRoutesStaleDocUrlSpec.cfc @@ -1,21 +1,22 @@ /** - * Regression: scaffolded config/routes.cfm shipped a `// See https://...` doc - * URL pointing at `https://guides.wheels.dev/docs/routing` — a path that - * doesn't exist on the current docs site. The lucli scaffolder's active - * `config/routes.cfm` template was already updated to the canonical - * `/v4-0-0-snapshot/handling-requests-with-controllers/routing` URL, but two - * sibling templates that produce the same comment for older code paths still - * had the broken link: + * Regression: scaffolded files shipped `See https://...` doc URLs pointing at + * guide paths that no longer exist on the docs site. * - * - cli/src/templates/ConfigRoutes.txt - * - cli/lucli/templates/app/app/snippets/ConfigRoutes.txt + * Round 1 (issue ##2635): config/routes.cfm templates pointed at the retired + * `guides.wheels.dev/docs/routing` path. * - * Both are user-facing on freshly scaffolded apps. Issue ##2635. + * Round 2 (2026-07): the pre-GA `v4-0-0-snapshot` slug was retired when the + * 4.0 docs consolidated onto `v4-0-0`, which killed every templated URL still + * carrying it — including the `working-with-wheels/*` paths that only ever + * existed in the v3 tree. The scaffolded settings.cfm/routes.cfm/environment.cfm, + * three template READMEs, two runtime CLI messages (Module.cfc, Doctor.cfc), + * and the demo app's config all linked 404s. All were repointed at live + * `guides.wheels.dev/v4-0-0/...` pages. * - * Also guards against any reintroduction of `cfwheels.org`, `cfwheels.com`, - * or `docs.cfwheels.org` URLs in these template files, since those domains - * were retired at the 3.0 rebrand and only `wheels.dev` / `guides.wheels.dev` - * remain canonical. + * This spec pins the canonical routing URL in the routes templates AND scans + * the scaffold template tree plus the known runtime-message files for any + * reintroduction of retired URL shapes: `v4-0-0-snapshot`, `wheels.dev/3.1.0`, + * and the rebrand-retired cfwheels.org / cfwheels.com / docs.cfwheels.org hosts. */ component extends="wheels.WheelsTest" { @@ -31,7 +32,7 @@ component extends="wheels.WheelsTest" { "cli/lucli/templates/app/app/snippets/ConfigRoutes.txt", "cli/lucli/templates/app/config/routes.cfm" ]; - var canonical = "https://guides.wheels.dev/v4-0-0-snapshot/handling-requests-with-controllers/routing"; + var canonical = "https://guides.wheels.dev/v4-0-0/basics/routing/"; for (var rel in targets) { // Capture the loop variable so the closure body binds the @@ -45,26 +46,72 @@ component extends="wheels.WheelsTest" { expect(content contains canonical).toBeTrue( relPath & " should reference " & canonical - & " — the same URL used by cli/lucli/templates/app/config/routes.cfm." + & " — the live v4 routing guide." ); expect(content contains "guides.wheels.dev/docs/routing").toBeFalse( relPath & " still references the stale /docs/routing path on guides.wheels.dev." ); - - expect(content contains "docs.cfwheels.org").toBeFalse( - relPath & " still references the retired docs.cfwheels.org host." - ); - - expect(reFindNoCase("cfwheels\.(org|com)", content) > 0).toBeFalse( - relPath & " still references a retired cfwheels.org / cfwheels.com URL." - ); }); })(rel); } }); + describe("Retired guide URL shapes", () => { + + var repoRoot = expandPath("/wheels/../.."); + + // Files outside the template tree that print or ship guide URLs. + var extraFiles = [ + "cli/README.md", + "cli/lucli/Module.cfc", + "cli/lucli/services/Doctor.cfc", + "cli/src/templates/ConfigRoutes.txt", + "cli/src/commands/wheels/analyze/code.cfc", + "config/settings.cfm", + "config/environment.cfm", + "config/routes.cfm" + ]; + + it("no retired guide URLs under cli/lucli/templates/ or the known runtime-message files", () => { + var scanned = []; + var templateRoot = repoRoot & "/cli/lucli/templates"; + var templateFiles = directoryList(templateRoot, true, "path"); + for (var path in templateFiles) { + if (reFindNoCase("\.(cfm|cfc|txt|md|json)$", path)) { + arrayAppend(scanned, path); + } + } + for (var rel in extraFiles) { + arrayAppend(scanned, repoRoot & "/" & rel); + } + + var offenders = []; + for (var path in scanned) { + if (!fileExists(path)) { + continue; + } + var content = fileRead(path); + if ( + findNoCase("v4-0-0-snapshot", content) + || findNoCase("wheels.dev/3.1.0", content) + || findNoCase("docs.cfwheels.org", content) + || reFindNoCase("cfwheels\.(org|com)", content) + ) { + arrayAppend(offenders, path); + } + } + + expect(arrayLen(offenders) == 0).toBeTrue( + "Retired guide URL shape (v4-0-0-snapshot, wheels.dev/3.1.0, or a cfwheels.org-era host) found in: " + & arrayToList(offenders, "; ") + & ". Point these at live guides.wheels.dev/v4-0-0/ pages instead." + ); + }); + + }); + } }