Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ All historical references to "CFWheels" in this changelog have been preserved fo

### Fixed

- `paginationLinks()` now emits a one-time per-request `WriteLog(type="warning", ...)` deprecation notice pointing 3.x → 4.x upgraders at `paginationNav()` (the all-in-one helper) and the individual `firstPageLink`/`previousPageLink`/`pageNumberLinks`/`nextPageLink`/`lastPageLink` composables. `wheels upgrade check --to=4.0.0` now also greps `app/views/` for `paginationLinks(` and flags every hit with a remediation pointer, closing the silent-rot gap surfaced by titan Phase 2.4 (#2714)
- `wheels` `.deb` / `.rpm` Linux packages now ship the lucli-native `wheels-module` artifact, version + channel stamps, and a wrapper that routes through the bundled module — fixing the three v4.0.0 rpm regressions that broke `wheels start` on Rocky Linux during the titan production cutover. (1) `build-linux-packages.sh` now untars `wheels-module-${WHEELS_VERSION}.tar.gz` into `/opt/wheels/module/` instead of unzipping the CommandBox-shaped `wheels-cli-${WHEELS_VERSION}.zip`. (2) The LuCLI binary is staged as `/opt/wheels/wheels` so `basename(argv[0])` is `wheels` when the wrapper execs it — mirroring the brew formula and making LuCLI's module dispatcher resolve `wheels start` against the bundled module. (3) `nfpm-wheels.yaml` and `nfpm-wheels-be.yaml` now declare `/opt/wheels/.version` and `/opt/wheels/.channel` under `contents:` so `wheels --version` no longer returns `unknown (stable)`. (4) `tar` is declared as an rpm + deb runtime dependency since Rocky Linux 10 minimal cloud images do not ship it and any role that unpacks a tarball payload fails silently without it (#2700)
- `wheels.middleware.RateLimiter` now validates `windowSeconds > 0` and `maxRequests >= 0` at construction. Previously, `windowSeconds = 0` leaked a generic CFML `You cannot divide by zero` exception out of the `fixedWindow` and `tokenBucket` strategies (and let every request through on `slidingWindow`), with no pointer back to the misconfigured `set(middleware = [...])` line. The constructor now throws `Wheels.RateLimiter.InvalidConfiguration` with a message naming the bad parameter — matching the pattern already used for `strategy`, `storage`, and `proxyStrategy`. `maxRequests = 0` remains legal (kill-switch idiom for "block every request") (#2693)
- `wheels deploy --version=v1.2.3` (the form documented in the Kamal migration guide) no longer fails with `Invalid value for option '--version': 'v1.2.3' is not a boolean`. picocli treats `--version` as a `versionHelp = true` root flag and absorbs it during arg parsing before `Module.cfc` ever sees the subcommand, so the literal Kamal form was unreachable. The deploy parser now accepts `--release` as a picocli-safe alias (extracted into `cli/lucli/services/deploy/cli/DeployArgsParser.cfc` for unit-testability), and the brew/scoop wrappers rewrite `--version[=val]` → `--release[=val]` when `deploy` is the first positional — so the documented `--version` form keeps working on a current-channel wrapper, and users on an older wrapper can pass `--release` directly (#2674)
Expand Down
9 changes: 9 additions & 0 deletions cli/lucli/Module.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -3733,6 +3733,15 @@ component extends="modules.BaseModule" {
extensions: "cfm,cfc",
fix: "Missing manifest entries throw Wheels.ViteAssetNotFound in production. Rebuild assets during deploy (npm run build) or set(viteStrictManifest=false) to restore 3.x silent fallback."
});
// paginationLinks() deprecation grep (#2714, replacement: paginationNav() per #1930).
arrayAppend(checks, {
description: "Deprecated paginationLinks() helper (renamed to paginationNav() in 4.0)",
pattern: "paginationLinks\s*\(",
checkType: "grep",
scanDir: "app/views",
extensions: "cfm,cfc",
fix: "Replace paginationLinks() with paginationNav() (the all-in-one nav helper) or compose firstPageLink/previousPageLink/pageNumberLinks/nextPageLink/lastPageLink directly. See https://github.com/wheels-dev/wheels/issues/1930."
});
}

// Run checks
Expand Down
6 changes: 6 additions & 0 deletions vendor/wheels/tests/specs/cli/UpgradeCheckCoverageSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ component extends="wheels.WheelsTest" {
);
});

it("scans for deprecated paginationLinks() helper", () => {
expect(findNoCase("paginationLinks", block) > 0).toBeTrue(
"3.x -> 4.x checks should grep views for paginationLinks( (renamed to paginationNav(), CHANGELOG ##2714)."
);
});

});

}
Expand Down
41 changes: 41 additions & 0 deletions vendor/wheels/tests/specs/view/paginationLinksDeprecationSpec.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
component extends="wheels.WheelsTest" {

function run() {

g = application.wo

describe("paginationLinks deprecation warning (##2714)", () => {

beforeEach(() => {
_params = {controller = "dummy", action = "dummy"}
_controller = g.controller("dummy", _params)
g.set(functionName = "paginationLinks", encode = false)
structDelete(request.wheels, "$paginationLinksDeprecationLogged")
})

afterEach(() => {
g.set(functionName = "paginationLinks", encode = true)
structDelete(request.wheels, "$paginationLinksDeprecationLogged")
})

it("sets a request-scoped guard flag on first call", () => {
g.model("author").findAll(page = 2, perPage = 3, order = "lastName")
expect(structKeyExists(request.wheels, "$paginationLinksDeprecationLogged")).toBeFalse()
_controller.paginationLinks()
expect(structKeyExists(request.wheels, "$paginationLinksDeprecationLogged")).toBeTrue()
expect(request.wheels.$paginationLinksDeprecationLogged).toBeTrue()
})

it("does not re-log when called multiple times in the same request", () => {
g.model("author").findAll(page = 2, perPage = 3, order = "lastName")
_controller.paginationLinks()
request.wheels.$paginationLinksDeprecationLogged = "first"
_controller.paginationLinks()
expect(request.wheels.$paginationLinksDeprecationLogged).toBe("first")
})

})

}

}
9 changes: 9 additions & 0 deletions vendor/wheels/view/links.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@ component {
boolean pageNumberAsParam,
any encode
) {
// One-time per-request deprecation warning (#2714) — mirrors $checkPluginsDeprecation() in Plugins.cfc.
if (!StructKeyExists(request.wheels, "$paginationLinksDeprecationLogged")) {
request.wheels.$paginationLinksDeprecationLogged = true;
WriteLog(
type = "warning",
text = "[Wheels] paginationLinks() is deprecated and will be removed in a future release. Use paginationNav() instead (or compose the individual helpers: firstPageLink/previousPageLink/pageNumberLinks/nextPageLink/lastPageLink). See https://github.com/wheels-dev/wheels/issues/1930"
);
}

/* To fix the bug below:
https://github.com/wheels-dev/wheels/issues/942

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ See [Packages](/v4-0-0/digging-deeper/packages/) for manifest fields, per-method

### Monolithic `paginationLinks()`

**CHANGELOG:** composable pagination helpers added (#1930). The 3.x `paginationLinks()` is retained. New code should use `paginationNav()` or compose the individual helpers (`paginationInfo`, `firstPageLink`, `previousPageLink`, `pageNumberLinks`, `nextPageLink`, `lastPageLink`).
**CHANGELOG:** composable pagination helpers added (#1930). The 3.x `paginationLinks()` is retained but deprecated. As of #2727, calling `paginationLinks()` emits a one-time per-request `WriteLog(type="warning")` pointing at the replacement so apps see the signal without flooding the log. `wheels upgrade check --to=4.0.0` also greps `app/views/` for `paginationLinks(` and flags every hit with a remediation pointer. New code should use `paginationNav()` or compose the individual helpers (`paginationInfo`, `firstPageLink`, `previousPageLink`, `pageNumberLinks`, `nextPageLink`, `lastPageLink`).

### RocketUnit test style

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ See [Packages](/v4-0-1-snapshot/digging-deeper/packages/) for manifest fields, p

### Monolithic `paginationLinks()`

**CHANGELOG:** composable pagination helpers added (#1930). The 3.x `paginationLinks()` is retained. New code should use `paginationNav()` or compose the individual helpers (`paginationInfo`, `firstPageLink`, `previousPageLink`, `pageNumberLinks`, `nextPageLink`, `lastPageLink`).
**CHANGELOG:** composable pagination helpers added (#1930). The 3.x `paginationLinks()` is retained but deprecated. As of #2727, calling `paginationLinks()` emits a one-time per-request `WriteLog(type="warning")` pointing at the replacement so apps see the signal without flooding the log. `wheels upgrade check --to=4.0.0` also greps `app/views/` for `paginationLinks(` and flags every hit with a remediation pointer. New code should use `paginationNav()` or compose the individual helpers (`paginationInfo`, `firstPageLink`, `previousPageLink`, `pageNumberLinks`, `nextPageLink`, `lastPageLink`).

### RocketUnit test style

Expand Down
Binary file modified web/tests/visual-baselines/blog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading