Repository navigation
Commit 9921598
authored
chore(deps): update dependency org.mock-server:mockserver-netty-no-dependencies to v8 (#2475)
> ℹ️ **Note**
>
> This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[org.mock-server:mockserver-netty-no-dependencies](https://www.mock-server.com)
([source](https://redirect.github.com/mock-server/mockserver-monorepo))
| `7.6.0` → `8.0.0` |

|

|
---
### Release Notes
<details>
<summary>mock-server/mockserver-monorepo
(org.mock-server:mockserver-netty-no-dependencies)</summary>
###
[`v8.0.0`](https://redirect.github.com/mock-server/mockserver-monorepo/blob/HEAD/changelog.md#800---2026-09-15)
##### Added
- Test port allocation can opt into a fixed port band instead of the OS
ephemeral range.
`org.mockserver.socket.PortFactory` normally finds a free port with
`bind(0)`, which draws from the same
ephemeral range (on macOS `net.inet.ip.portrange.hifirst`..`hilast`,
typically 49152-65535) that every other
`bind(0)` on the machine uses — including unrelated applications, IDE
helpers, and other JVMs. On a busy
developer machine that causes two kinds of test flake: a foreign process
can occupy a number a test is about to
choose, and a test can momentarily connect to that foreign listener
instead of the server under test. Setting
both `mockserver.testPortRangeStart` and `mockserver.testPortRangeEnd`
(for example
`-Dmockserver.testPortRangeStart=20000
-Dmockserver.testPortRangeEnd=40000`) makes `PortFactory` choose ports
by
explicitly binding inside that band — which the OS does not itself hand
out to `bind(0)` — retrying past any
number already in use. Both properties are unset by default, so
continuous integration and any machine that does
not set them keep the exact `bind(0)` behaviour as before. This affects
only test port selection; it does not
change how MockServer binds its own ports at runtime (starting on port
`0` and reading back the assigned port
remains the fully race-free option and is unchanged). In a
surefire/failsafe fork the two properties must reach
the fork, e.g. via
`-Dmockserver.testArgLine="-Dmockserver.testPortRangeStart=20000
-Dmockserver.testPortRangeEnd=40000"`.
##### Changed
- HTTP/2 now gives every request stream its own channel. MockServer's
HTTP/2 server — both `h2` (over TLS) and
cleartext `h2c` — now uses Netty's stream-multiplexing model for every
connection, replacing the previous
shared-connection HTTP/2 pipeline. Each HTTP/2 stream is processed on
its own isolated child channel. This
removes a class of cross-stream interference on busy connections:
concurrent streaming responses (Server-Sent
Events, NDJSON, AWS Bedrock event-stream, and therefore all streaming
LLM responses) can no longer have a later
chunk of one stream mis-routed onto another, and each stream's
end-of-stream is delivered independently, so a
slow or streaming response on one stream cannot stall another. This
model was previously used only when
`grpcBidiStreamingEnabled` was set; it is now the standard HTTP/2
pipeline and needs no configuration — so the
HTTP/2 correctness fixes listed below apply to all HTTP/2 traffic, not
only when that flag is enabled. There is
no change to the REST/Java API, to how expectations are written, or to
HTTP/1.1 and HTTP/3 traffic, and HTTP/2
clients receive the same responses. Users driving very large numbers of
concurrent streams over a single
connection may notice different memory and throughput characteristics,
since each stream now has its own
lightweight channel. (GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
- **Behaviour change — over HTTP/2, `closeSocket` now ends the stream,
not the connection.** A per-expectation
`ConnectionOptions.closeSocket` / `closeChannel` (and the
`slowCloseDelay` connection-lifecycle chaos) applied
to an HTTP/2 request now closes only *that* request's stream; other
requests in flight on the same connection
continue and complete normally. Previously it tore down the whole TCP
connection, killing every concurrent
stream on it — so one expectation could destroy unrelated clients'
in-flight requests. Ending a single stream
is the correct HTTP/2 semantic and is what the same expectation already
did over HTTP/1.1, where a connection
carries one request at a time. **If you rely on `closeSocket` to tear
down an HTTP/2 connection** — for example
to test how your client recovers from a dropped connection — use the
`resetMidResponse` connection-lifecycle
chaos fault instead, which still aborts the whole TCP connection (that
is its purpose, and it now does so
properly rather than degrading into a single-stream reset). HTTP/1.1 and
HTTP/3 behaviour is unchanged.
(GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
- **BREAKING: `mockserver-bom` now manages only MockServer's own
`org.mock-server` modules — it no longer pins
the third-party libraries MockServer uses internally.** The published
BOM previously baked in MockServer's
entire parent `dependencyManagement` (\~190 third-party entries —
Jackson, Netty, Guava, Nimbus, Velocity, and
more), four of them at `test` scope. Because a BOM's managed versions
and scopes apply to whoever imports it,
this silently overrode a consumer's **own** versions *and* scopes for
those shared libraries. For example, a
project that declared `com.nimbusds:oauth2-oidc-sdk` without a scope had
it forced onto the **test** classpath
by MockServer's internal test-scoped pin, so the dependency disappeared
from compile/runtime and the
consumer's production code failed to build against it (GitHub issue
[#​2684](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2684)).
The published BOM now contains
only the MockServer module entries (24, down from 221), so importing it
never changes any third-party version
or scope in your build. **What you need to do:** if you imported
`mockserver-bom` to align MockServer's
*transitive* third-party versions — for instance to satisfy the Maven
Enforcer `dependencyConvergence` rule —
those pins are gone and convergence errors may reappear; manage the
affected third-party versions yourself in
your own `dependencyManagement`, or import each upstream project's own
BOM. Aligning the MockServer modules
themselves is unchanged: keep importing the BOM and declare MockServer
artifacts without a version.
(GitHub issue
[#​2684](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2684)).
##### Fixed
- A **SOCKS4a** client (for example `curl -x socks4a://…`) proxying
through MockServer no longer hangs.
SOCKS4a is the SOCKS4 extension where the client sends the destination
as a **hostname** instead of an
IPv4 address. MockServer decoded the request correctly but then echoed
that hostname back into the
`DSTIP` field of the SOCKS4 grant reply, which must be an IPv4 literal;
the resulting error was thrown
while writing the reply, so the client never received one and blocked
until it timed out (curl exit 28,
0 bytes) — for cleartext HTTP as well as for TLS. The reply's
`DSTIP`/`DSTPORT` are ignored by clients,
so a SOCKS4a grant now carries `0.0.0.0:0`; a classic SOCKS4 request
(IPv4 literal) still echoes its
destination back unchanged. Plain SOCKS4 and SOCKS5 (`socks5h://`) were
unaffected.
- The command-line server now exits with a non-zero status code when it
fails to start. Previously, if
MockServer could not start — most commonly because the requested port
was already in use — the CLI logged
the error but still exited `0`, so a shell script or CI job that started
MockServer got no failure signal
and carried on as though the server was up (typically failing later with
a confusing connection error).
`mockserver run` / `-serverPort` (and the `ui`, `demo`, `proxy`, and
`openapi` subcommands, which start a
server the same way) now exit `1` on a failed start. Usage errors that
were already handled — an invalid or
missing port, an invalid host or log level — keep their existing exit
code, so only the previously-silent
startup-failure case changes.
- An HTTPS request that negotiates HTTP/2 (ALPN `h2`) through
MockServer's **SOCKS proxy** now works.
Previously, using MockServer as a SOCKS4/SOCKS5 proxy for an `https://`
request that upgraded to HTTP/2
failed completely — the client received nothing (curl reported
`CURLE_HTTP2`, 0 bytes) — because MockServer
provisioned its internal relay for HTTP/1.1 before the tunnelled TLS
connection had negotiated its protocol,
so the forwarded HTTP/2 frames were unparseable. SOCKS over HTTP/1.1,
SOCKS over cleartext, and the HTTP
`CONNECT` proxy over HTTP/2 were unaffected and continue to work.
MockServer now terminates the tunnelled TLS
in the relay and waits for its ALPN result before wiring up the
connection, exactly as the `CONNECT` proxy
already did. This works on **any port**: rather than guessing from the
destination port number (the earlier
fix inferred TLS only for ports ending in `443`, so `h2` to a TLS port
such as `993`, `465`, or `9999` was
still mis-provisioned as HTTP/1.1), MockServer now classifies the first
bytes the client sends through the
tunnel — a TLS record versus a cleartext HTTP request — and provisions
the connection to match. As a result,
HTTP/2 over TLS through a SOCKS tunnel succeeds on any port, and a
cleartext tunnel to a port that happens to
end in `443` is no longer mistaken for TLS. **Cleartext HTTP/2 with
prior knowledge (`h2c`) through a SOCKS
tunnel now works too** — the last case left as HTTP/1.1 by the earlier
fixes. The same first-bytes
classification now also recognises the HTTP/2 connection preface (`PRI *
HTTP/2.0…`) after ruling out a TLS
record, and provisions cleartext HTTP/2 on both relay legs so the mocked
response is served over `h2c`
(a curl `--http2-prior-knowledge` request through a `socks5h://` proxy,
for example); anything that is not a
preface is still provisioned as HTTP/1.1, and when HTTP/2 is disabled
(`http2Enabled=false`) the preface is
ignored and the tunnel falls back to HTTP/1.1, exactly as MockServer's
own listener does. The HTTP `CONNECT`
proxy is unchanged, so cleartext HTTP/2 with prior knowledge through
`CONNECT` is still served as HTTP/1.1 —
that was never a working case and is unaffected either way. (GitHub
issue
[#​2685](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2685)).
- Starting the command-line server with port `0` now reports and uses
the actual OS-assigned
ephemeral port instead of `0`. Previously `mockserver run -p 0` (or
`-serverPort 0`) bound a real
ephemeral port but recorded the requested `0`, so the port a caller
needs to reach the server was
not discoverable, and `ui -p 0` / `demo -p 0` printed a
dashboard/getting-started URL pointing at
`localhost:0`. MockServer now records the real bound port after startup
and uses it for the
dashboard and demo URLs. Starting on an explicit, non-zero port is
unaffected.
- HTTP/2 responses larger than the client's initial flow-control window
no longer hang when fetched
through MockServer's HTTPS forward proxy (HTTP `CONNECT`). On the
CONNECT-tunnel path several handlers
ahead of the HTTP/2 codec overrode Netty's `channelReadComplete` to only
flush, without propagating the
event down the pipeline. Netty's HTTP/2 connection handler relies on
`channelReadComplete` to flush
flow-control-pending writes (it is where a peer's `WINDOW_UPDATE` is
acted on), so swallowing the event
stalled any h2 response bigger than the peer's initial window (65,535
bytes by default) at exactly one
window until the client timed out. Direct HTTP/2 (`h2c` and TLS+ALPN)
and HTTP/1.1-through-`CONNECT`
were unaffected. The affected handlers now propagate the event. (GitHub
issue
[#​2683](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2683)).
- The S3 blob-store tests pull MinIO from quay.io instead of Docker Hub.
`minio/minio` is no longer
pullable from Docker Hub, which broke these tests — and therefore the
build — with a container-fetch
error unrelated to any code change. quay.io is MinIO's other official
registry and serves the same
image and tag. Test-only; nothing MockServer ships is affected.
- The Python client and the Python Testcontainers module now ship a PEP
561 `py.typed` marker, so type
checkers use their annotations instead of ignoring them. Both packages
are almost fully annotated, but
without the marker `mypy` reported `Skipping analyzing "mockserver":
module is installed, but missing
library stubs or py.typed marker` and treated every import as `Any`, so
no call into the client was
checked at all. Nothing about the packages' behaviour changes — `mypy`
(and any PEP 561 checker) will now
type-check your calls, which may surface genuine mistakes in existing
code that were previously
invisible. (GitHub issue
[#​2680](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2680)).
- With gRPC bidi-streaming enabled (`grpcBidiStreamingEnabled`),
streaming responses over HTTP/2 — Server-Sent
Events, NDJSON, AWS Bedrock event-stream, and therefore all streaming
LLM responses — now terminate correctly
instead of leaving the client hanging. Enabling that mode routes every
HTTP/2 stream (not just gRPC) through
Netty's multiplex model, where each stream is a separate child channel.
On that path MockServer's terminal
end-of-stream marker was being silently dropped by Netty's stream-frame
codec, which hard-codes streaming data
frames as "not the end of the stream". The client received every event
and then waited — receiving no
end-of-stream — until it timed out, with nothing failing or logged
server-side. MockServer now translates the
terminal frame so the codec emits it with the end-of-stream flag set,
closing the stream as expected. Streaming
over HTTP/1.1 and over the default (non-multiplex) HTTP/2 pipeline was
already correct and is unaffected. (GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
- With gRPC bidi-streaming enabled (`grpcBidiStreamingEnabled`), plain
HTTP requests sharing the same HTTP/2
connection are no longer mis-handled. Enabling that mode switches the
HTTP/2 pipeline to Netty's multiplex
model, giving every stream its own child channel — but those child
channels do not inherit the parent
connection's attributes, and MockServer had only been copying one of
them across. As a result, on any
non-gRPC request arriving over such a connection: it was not recognised
as HTTP/2 (so `withProtocol(HTTP_2)`
matching failed and the protocol was mis-reported in the request log and
HAR export); a request to the
dashboard or callback WebSocket endpoint tried to perform a WebSocket
handshake over the HTTP/2 stream — which
is unsupported — instead of cleanly returning `501 Not Implemented`; a
client certificate presented on the
connection was not visible to control-plane authentication for MCP
requests on that stream; and a proxied
request (SOCKS/CONNECT/transparent/port-forward) was mis-routed —
treated as a direct request, or forwarded to
its `Host` header instead of the proxy's actual remote target. The
connection-scoped state a request depends on
(negotiated protocol, TLS/client-certificate details, the proxying flag,
the proxy remote-target address, and
the local-host set) is now propagated onto each HTTP/2 stream child
channel, so these requests behave exactly as
they do on HTTP/1.1 and on the default (non-multiplex) HTTP/2 pipeline.
HTTP/1.1 traffic is unaffected. (GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
- With gRPC bidi-streaming enabled (`grpcBidiStreamingEnabled`), a plain
HTTP request sent over HTTP/2 with a
compressed body (`content-encoding: gzip`, `deflate`, and so on) is now
decompressed before matching. Enabling
that mode routes every HTTP/2 stream — ordinary requests included, not
just gRPC — through Netty's multiplex
model, and on that path the request body was left compressed: a
`withBody(...)` expectation then silently
failed to match (MockServer answered `404 Not Found`) and the recorded
request showed unreadable compressed
bytes. Compressed request bodies are now decompressed on this path
exactly as they are on HTTP/1.1 and on the
default (non-multiplex) HTTP/2 pipeline. gRPC's own message compression
(carried by `grpc-encoding`) is a
separate mechanism and is unaffected. (GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
Matching on the `content-encoding` header itself still works: the header
is preserved for matching before
decompression removes it, exactly as on HTTP/1.1. (An expectation
written against `content-encoding: gzip`
briefly stopped matching on this pipeline once decompression was added;
that is fixed here.)
- With gRPC bidi-streaming enabled (`grpcBidiStreamingEnabled`), a plain
HTTP request sent over HTTP/2 with an
unusual header value — a leading space, an embedded `DEL` (0x7F), or
another control character — is now
received and matchable instead of being silently rejected. Enabling that
mode routes every HTTP/2 stream
through Netty's multiplex model, where such a request was reset with
`RST_STREAM(PROTOCOL_ERROR)` before it
ever reached the matchers, so nothing matched and nothing was logged as
received. Because MockServer is a mock
server that users deliberately drive with malformed traffic to test
their own clients, these requests are now
accepted and recorded, matching the behaviour on HTTP/1.1 and on the
default (non-multiplex) HTTP/2 pipeline.
This leniency applies to inbound requests only: response header *names*
MockServer sends are still validated
as before, exactly as on the default HTTP/2 pipeline, so a malformed
response header name is rejected rather
than put on the wire. (GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
- Over HTTP/2 the two ways of ending a connection now behave distinctly
instead of collapsing into a single
stream reset (see the behaviour-change note above). Every HTTP/2 stream
is its own child of the shared TCP
connection.
A per-expectation `closeSocket` / `closeChannel` (and the
`slowCloseDelay` connection-lifecycle chaos) now
correctly ends only *that* request's stream, leaving other concurrent
requests on the same connection to
complete normally — whereas the `resetMidResponse` connection-lifecycle
chaos fault, whose purpose is to
simulate a real server socket abort, now resets the whole TCP connection
(aborting every concurrent stream on
it) rather than quietly degrading into a single-stream reset. Previously
`resetMidResponse` over multiplex
HTTP/2 emitted only an ordinary stream reset — a fault meant to simulate
a crashed socket silently became
something weaker. Behaviour over HTTP/1.1 and over the default
(non-multiplex) HTTP/2 pipeline is unchanged.
(GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
- The MockServer dashboard is no longer unreachable over HTTP/2 — a
browser (or any client) requesting
`/mockserver/dashboard` and its assets over HTTP/2 hung indefinitely and
never received a response. The
dashboard handler writes its response straight to the channel (it does
not go through the normal response
writer), and it never copied the request's HTTP/2 stream id onto that
response. On the shared HTTP/2
connection Netty then routed the response head onto a fresh
server-initiated stream instead of the client's
own stream, so the response was never delivered and the client waited
until it timed out. Nothing failed or
was logged server-side, which is why it went unnoticed. The handler now
stamps the request's stream id onto
every response it writes (matching the metrics endpoint, which shares
the same direct-write pattern); this is
a no-op on HTTP/1.1, where the dashboard already worked.
- `MockServerContainer` (the Testcontainers integration) now waits until
MockServer is actually *serving*
before `start()` returns, so a request issued immediately afterwards is
no longer reset. The container waited
with a listening-port strategy, which is satisfied the instant the
mapped port accepts a TCP connection — but
MockServer's Netty listener binds the port early and then
accepts-then-resets connections until initialisation
finishes. `start()` therefore returned inside that window (measured at
\~0.2–0.3s wide against the released
image, and wider on a loaded host), and the first request could fail
with `SocketConnectionException: Channel
handler removed before valid response has been received`. The wait is
now an HTTP readiness probe against
`PUT /mockserver/status` returning 200, which only happens once the
request pipeline is fully initialised, so
`start()` returning now means "ready to serve". This most affects
callers on busy/CI hosts, where CPU
contention widens the race. (`withServerPort(...)` re-targets the probe
at the chosen port.)
- A streaming `httpLlmResponse` expectation that sets
`completion.streamingPhysics.timeToFirstToken` is no
longer rejected with an HTTP 400 and a confusing error naming
`org.mockserver.model.Delay` — a type the user
never wrote. The expectation serialised cleanly on the client (a raw
`Delay` serialises to exactly the same
bytes its `DelayDTO` produces), so the invalid JSON was only rejected
server-side on deserialisation, where
Jackson tried to construct a raw `Delay` (which has no default
constructor and no creator) instead of going
through `DelayDTO`. This serialise-succeeds / deserialise-fails
asymmetry is why it was invisible in
client-side tests. `timeToFirstToken` now crosses the wire through the
DTO layer like every other `Delay`
(via new `CompletionDTO`/`StreamingPhysicsDTO` boundaries wrapping it in
`DelayDTO`); the serialised JSON is
byte-for-byte unchanged, so existing stored expectations and clients
keep working. (GitHub issue
[#​2668](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2668)).
- Two (or more) concurrent streaming responses (`httpSseResponse`, and
streaming `httpLlmResponse` with
`completion.streaming:true`) over a single HTTP/2 connection no longer
cause one stream to hang forever. All
non-gRPC HTTP/2 traffic is multiplexed over one shared
`HttpToHttp2ConnectionHandler`, which picked the
outbound target stream from a single mutable field updated only when a
response *head* was written; a bare
data chunk carries no stream id, so once a second stream wrote its head
every later chunk of the first
stream was mis-routed onto the second (by then often already-closed)
stream — the server logged
`IllegalArgumentException: Stream no longer exists`, the terminal frame
never reached the first stream, and
its client waited on a stream that would never end. Streaming data
frames now carry their originating stream
id out-of-band (a `StreamAddressedHttpContent` wrapper) so each frame is
written onto its own stream, and
interleaved concurrent streams each receive their full body and their
own `END_STREAM`; a streaming write
that fails for any reason now still ends its own stream so a client is
never left hanging. `httpLlmResponse` streaming, which is served through
the same handler, was
equally affected and is fixed by the same change. (GitHub issue
[#​2667](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2667)).
- A JSON body expectation built through a client (e.g.
`json("{\"amount\":275.0}", MatchType.ONLY_MATCHING_FIELDS)`)
no longer fails to match a byte-identical request. A whole-number double
such as `275.0` was silently corrupted
to the bare integer `275` when the expectation was serialised, before
any request even arrived: the JSON body
serializers parsed the value with `USE_BIG_DECIMAL_FOR_FLOATS` into a
`BigDecimal`, and Jackson's
`STRIP_TRAILING_BIGDECIMAL_ZEROES` (on by default since 2.15) stripped
the trailing zero at node construction,
so re-serialisation emitted an integer literal. The server then parsed
`275` as an integer while the request's
`275.0` stayed a double, and json-unit correctly reports those as
different — so the expectation never matched
the very request it was created for. The serializers now keep
`BigDecimal`s exact
(`JsonNodeFactory.withExactBigDecimals(true)`), so `275.0` survives as
`275.0` and genuine integers such as `1`
are left untouched. This also completes the original intent of the
earlier `USE_BIG_DECIMAL_FOR_FLOATS` fix
([#​1740](https://redirect.github.com/mock-server/mockserver-monorepo/issues/1740)),
which was meant to preserve decimals such as `0.00` but — because the
same stripping was already active
at that time — had never actually done so. (GitHub issue
[#​2658](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2658)).
- Streaming responses (`httpSseResponse`, and streaming
`httpLlmResponse` with `completion.streaming:true`)
no longer wrongly close the connection at end of stream. `finishStream`
always closed by default —
`closeConnection` defaults to null and the old `null || true` test made
"unset" mean "always close" — while
the response head unconditionally advertised `Connection: keep-alive`.
So an HTTP/1.1 client that reused the
connection the response had promised it could keep got a
`RemoteDisconnected` on its next request, and on
HTTP/2 (where every non-gRPC stream is multiplexed onto one connection
channel) the `ctx.close()` emitted
GOAWAY and tore down the whole connection, killing sibling streams. The
end-of-stream decision now mirrors
the non-streaming path: an explicit `closeConnection` still wins on
HTTP/1.1, otherwise the request's
keep-alive intent decides and `alwaysCloseSocketConnections` still
forces a close; an HTTP/2 request never
closes the shared parent connection (its terminal frame ends only that
stream); and the `Connection` header
now reports the decision that is actually taken instead of always
claiming keep-alive. (GitHub issue
[#​2641](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2641)).
Note: fully-interleaved *concurrent* HTTP/2 streaming over the
single-connection HTTP/2 path was a separate
limitation (bare content frames were routed by a single current stream
id) and is now fixed too — see
[#​2667](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2667).
- Request bodies sent as `application/yaml`, `application/x-yaml` or
`application/graphql` are no longer
corrupted. None of those subtypes were in `MediaType.isString()`, so the
body was stored as a `BinaryBody`
and `getBodyAsString()` handed back **base64** — silently mangling every
YAML specification and GraphQL SDL
document sent with its natural content type, on the control plane (`PUT
/mockserver/graphql` rejected its
own documented example this way, and `PUT /mockserver/openapi` did the
same for a YAML spec) and in user
request matchers alike. `application/yaml` is the media type registered
by RFC 9512; all three are UTF-8
text with neither a `text` type nor a `+json`/`+xml` suffix to fall back
on.
- `PUT /mockserver/contractTest` no longer reports success for a run
that verified nothing. `allPassed` was
computed as `passed == results.size()`, which is vacuously true for an
empty result set, so a contract test
whose `operationId` filter was mistyped or had gone stale against a
renamed operation returned
`{"totalOperations": 0, "allPassed": true}`. An empty run is now
`allPassed: false` and carries an `error`
naming why nothing ran.
- The published OpenAPI examples for `PUT /mockserver/asyncapi/http`,
`PUT /mockserver/loadScenario/generateFromOpenAPI`
and `PUT /mockserver/contractTest` now work as published. The AsyncAPI
endpoint declared no request-body
example at all (so the generated Postman/Bruno collections sent an empty
body and the endpoint rejected it),
and the other two fetched their specification from a remote URL, so the
example failed anywhere without
egress. Both now carry an inline specification.
- With gRPC bidi-streaming enabled (`grpcBidiStreamingEnabled`), the
HTTP/2 `GOAWAY` drain signal now actually
reaches the client. Enabling that mode switches the HTTP/2 pipeline to
Netty's multiplex model, where each
stream is handled on its own child channel. The code that emits a
connection-level `GOAWAY` looked for the
HTTP/2 connection handler only on the local channel — but on a multiplex
child channel that handler lives on
the parent connection channel, so the lookup found nothing and the
`GOAWAY` was silently dropped. Two
"tell the client to drain" signals stopped working as a result: the
graceful drain `GOAWAY` sent while the
server is preempting/shutting down (so HTTP/2 clients stop opening new
streams and retry elsewhere), and the
`http2GoAway` chaos experiment. In both cases the server believed it had
signalled while the client never
learned, with nothing logged. The emitter now walks up to the parent
connection channel when needed, so the
`GOAWAY` is written on the connection where it belongs. The default
(non-multiplex) HTTP/2 path and HTTP/1.1
are unaffected. (GitHub issue
[#​2669](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2669)).
##### Changed
- `PUT /mockserver/loadScenario/generateFromRecording` answers **409**
rather than 400 when there is no
recorded traffic to convert; 400 now means only that the request is
malformed (missing `name`, an invalid
`mode`, or a scenario that fails validation). The body was always
well-formed in the no-traffic case — only
the state was missing — so 400 told callers their request was wrong and
gave them no way to tell that apart
from "record some traffic through the proxy first". The core throws a
dedicated
`LoadScenarioFromRecording.NoRecordedTrafficException`, which extends
`IllegalArgumentException` so existing
callers that catch it keep working. This was the last entry in the
collection gate's `KNOWN_FAILING`
ratchet, which is now empty: every example the published Postman/Bruno
collections carry is accepted by a
default container.
- `PUT /mockserver/verifySLO` answers **403** rather than 400 when SLO
tracking is disabled
(`sloTrackingEnabled=false`); 400 now means only that the criteria are
malformed. The two cases previously
shared 400, so a caller could not tell a typo in its criteria from a
server with the feature switched off —
every client library papered over it with a combined "invalid criteria
(or SLO tracking disabled)" message.
403 matches `PUT /mockserver/loadScenario/start`, which is the same
situation, and the feature-disabled
error the clients already model. All nine clients now distinguish the
two: Go returns `FeatureDisabledError`
on 403 and a criteria error on 400, PHP throws
`FeatureNotEnabledException` on 403, Java throws
`IllegalStateException` on 403 and keeps `IllegalArgumentException` for
400, and the Python, Ruby, Node,
Rust, .NET and dashboard clients give distinct messages for each.
##### Added
- **The initialization-file watch poll interval is now configurable**
via the new
`watchInitializationJsonPollPeriodMillis` property (system property
`-Dmockserver.watchInitializationJsonPollPeriodMillis`,
env var `MOCKSERVER_WATCH_INITIALIZATION_JSON_POLL_PERIOD_MILLIS`,
properties-file key, `Configuration`
instance setter, and `PUT /mockserver/configuration`). It controls how
often a watched
`initializationJsonPath` / `initializationOpenAPIPath` file (when
`watchInitializationJson=true`) is polled
for changes; default `5000` (5 seconds) — unchanged from the previously
hard-coded value — lower it for
faster live reloads or raise it to reduce polling overhead. Previously
this interval was a process-wide
mutable static with no supported configuration route, only reachable
through internal test-only setters.
Those four accessors (`FileWatcher.get/setPollPeriod` and
`get/setPollPeriodUnits`) are removed — they were
`public static` on an internal persistence class, were never a
documented configuration route, and had no
consumers outside MockServer's own tests; the property above replaces
them. The shared mutable static was
also a real defect: two test classes shortened it and restored it
concurrently, so whichever finished first
reinstated the 5-second default under the other, which is what reddened
master builds 6914/6918 and PR
[#​2655](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2655).
- **`ORCAROUTER` is now a supported LLM provider.** OrcaRouter
(`api.orcarouter.ai`) is an OpenAI-chat-compatible
AI gateway that fronts many upstream models with vendor-prefixed model
ids, so it is wired exactly like
`OPENROUTER`: it produces the OpenAI Chat Completions wire format, is
detected from its host on proxied
traffic, and prices vendor-prefixed model ids through the underlying
vendor's table. This completes community
contribution
[#​2545](https://redirect.github.com/mock-server/mockserver-monorepo/pull/2545)
by adding `ORCAROUTER` to
the two consumer-facing published contracts the server-side change had
left out — the published OpenAPI
specification's `httpLlmResponse.provider` enum and the Node client's
`LlmProvider` type union — so the
provider is reachable from generated tooling and the TypeScript client,
and by documenting it on the LLM
response mocking page.
- `PUT /mockserver/retrieve` now accepts an expectation id (`{"id":
"..."}`) in the request body instead of a request
matcher, matching what `PUT /mockserver/clear` and `PUT
/mockserver/verify` have always accepted (GitHub issue
[#​2591](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2591)).
For `?type=active_expectations` this returns only the expectation with
that id — filtering on the id itself, not on
the request definition it resolves to, so it neither returns every other
expectation whose matcher matches the same
request nor misses expectations (OpenAPI, schema or regex matchers)
whose own definition does not match their own
matcher. For `requests`, `request_responses`, `recorded_expectations`
and `logs` it returns the entries matching that
expectation's request, exactly as verify by expectation id matches them.
An unknown id is rejected with
`400 No expectation found with id ...` rather than silently matching
everything. The expectation-id body and the
request-matcher body are unambiguous — both JSON schemas set
`additionalProperties: false` and only the expectation
id schema allows (and requires) an `id` property — so existing
request-matcher and empty bodies are unaffected. All
nine clients gained the corresponding calls: Java `retrieve*ById(...)`,
Node `retrieve*ById(...)`, Python/Ruby
`retrieve_*_by_id(...)`, Go `Retrieve*ByID(...)`, Rust
`retrieve_*_by_id(...)`, PHP `retrieve*ById(...)` and
.NET `Retrieve*ById(...)`.
- The LLM provider list in the two consumer-facing published contracts —
the OpenAPI specification
(`jekyll-www.mock-server.com/mockserver-openapi.yaml`, schema
`HttpLlmResponse.provider`) and the Node client's
`LlmProvider` type union (`mockserver-client-node/mockServer.d.ts`) — is
now pinned to the server's `Provider` enum
by `ProviderConsumerContractEnumParityTest`. Previously a new provider
could be added to `Provider` and every
server-side registration point while both published contracts were left
behind, and nothing failed: the existing
internal-schema parity test does not read these files, and the Node
drift test compares the `.d.ts` only against the
OpenAPI spec, so the two consumer copies could drift from the server in
lock-step yet still agree with each other.
Both consumer artefacts are now driven from the one authority (the
compiled `Provider` enum), in both directions, and
each failure message names the missing provider, the exact file, and how
to fix it.
- Pull requests from third-party forks now get an automated test signal,
via a new GitHub Actions workflow
(`.github/workflows/pr-tests.yml`). Buildkite — the primary CI —
deliberately does not build fork PRs
(`build_pull_request_forks: false`) because its EC2 agents carry the
signing key and every publish credential, so
community PRs previously got no test feedback at all. The new workflow
runs the full Maven reactor `clean install`
(Surefire unit tests and Failsafe integration tests, including the
Docker-gated Testcontainers suites, which execute
against local emulator containers on the Docker-enabled hosted runner —
no cloud credentials) plus the standalone
examples build, and uploads the failing tests' reports as an artifact so
the contributor can see which test failed
and why. It is secret-free by construction — `on: pull_request` (never
`pull_request_target`), no `secrets.*`
reference, workflow-level `permissions: {}` with the one job granted
only `contents: read`, and GitHub-owned
SHA-pinned actions only — so it is useless to an attacker who controls
the code it runs. It runs only on fork PRs
(where Buildkite adds nothing) and on manual `workflow_dispatch`;
in-repo branches keep their full Buildkite
pipeline. The three privileged transparent-proxy end-to-end suites are
excluded explicitly here — by name, via
`-Dfailsafe.excludesFile`, which preserves the POM includes and drops
only those classes — because they build
`--cap-add=NET_ADMIN`/`--privileged` sibling containers a hosted runner
cannot be relied on to support, and their
only code-level gate (`DockerCliTestSupport.isDockerAvailable()`) is
true on `ubuntu-latest` (Maven has no
`RUN_TRANSPARENT_PROXY_E2E` gate — that is a Buildkite shell-step switch
only); they, and the client-language/UI/Helm
pipelines, remain Buildkite's responsibility. The Docker-gated
Testcontainers suites that do run are paired with a
fail-closed `assert-suite-ran.sh` check, so a runner without a usable
Docker daemon reds the job rather than passing
green on skipped coverage.
- Dependabot minor/patch pull requests are now merged automatically once
**every** check that actually exists on the
PR head commit has genuinely passed, via a new GitHub Actions workflow
(`.github/workflows/dependabot-auto-merge.yml`).
It was chosen deliberately over GitHub's native auto-merge: native
auto-merge waits only on the branch-protection
*required-status-check list*, and in this repo Buildkite and both Snyk
scans are **not** required checks, so native
auto-merge would merge the instant the *required* checks were green
while the build or the vulnerability scanner was
still pending or red — and a newly-added check stays invisible to it
until someone edits the list. Instead the workflow
reads the checks that actually exist by aggregating **both** GitHub APIs
— the Check Runs API
(`/commits/{sha}/check-runs`, which on a Dependabot head carries CodeQL
and the language `Analyze` runs) **and** the
legacy Commit Status API (`/commits/{sha}/status`, which carries
`buildkite/mockserver` and both Snyk scans) — and
requires them to pass. Commit statuses must be `success` — the legacy
status API has only `error`/`failure`/`pending`/
`success`, so the security-critical contexts cannot report a
non-blocking state. Check runs may be `skipped` or
`neutral` without blocking (the fork-only test workflow is always
skipped on an in-repo PR, so requiring literal
success from every run would merge nothing), but at least one genuine
success is still required. It fails closed on
every other ambiguity: any pending, failed, cancelled or unrecognised
result, **zero** checks found (the empty-set
trap), an API error, or unknown mergeability all refuse the merge with a
logged reason. It merges only PRs authored by `dependabot[bot]` whose
head branch is in this
repository (not a fork), and only two branch classes: **minor/patch**
group updates and Docker **digest** bumps. For
the first, `.github/dependabot.yml` groups minor+patch into
`*-minor-and-patch` groups and excludes majors, so a major
arrives as an ungrouped single-dependency branch that fails the
group-branch check — a structural, spoof-resistant
signal because only Dependabot creates those in-repo branches. For the
second, a Docker image-digest bump (a new SHA
on an *unchanged* tag) carries no semver and so joins no group; it is
now accepted directly, but **only** for the
distroless runtime bases — the one image class that, being pinned on
non-semver tags, has only ever moved by digest in
this repo's entire Dependabot history — and only when **two**
independent Dependabot-generated signals agree: the
branch is a `.../distroless/<image>-<hex-sha>` path **and** the PR title
is Dependabot's digest-bump shape (`bump … from <hex-sha> to
<hex-sha>`). A version or tag bump matches neither (its branch and title
carry bare versions, not hex
shas), and the two-signal AND fails closed, so a major or tag change can
never be auto-merged. The semver-tagged
images (`alpine`, `ubuntu`, `eclipse-temurin`, `grafana/k6`) are
deliberately excluded from the digest path — safety
over completeness. `.github/dependabot.yml` is unchanged.
The workflow runs on a `schedule` sweep plus `workflow_dispatch` (never
`pull_request`/`pull_request_target`), checks
out no PR code, uses no third-party actions and no `secrets.*`, and
holds only job-level `contents: write` +
`pull-requests: write` under a workflow-level `permissions: {}`. It
ships with `dry_run` defaulting **ON** so it can be
trialled — logging each decision without merging — until the schedule
default is flipped to live.
##### Changed
- The Dependabot auto-merge workflow
(`.github/workflows/dependabot-auto-merge.yml`) is now **live on the
schedule**:
`DEFAULT_DRY_RUN` was flipped from `'true'` to `'false'`, so the
scheduled sweep actually merges eligible PRs rather
than only logging its decisions. The `workflow_dispatch` `dry_run` input
still defaults to `true`, so a manual run
stays a safe dry-run probe unless the operator explicitly sets it false.
Arming it is backed by a new standing guard
(Rule 6 in `.buildkite/scripts/steps/check-false-green-guards.sh`) that
fails the build if any of the four
load-bearing properties keeping majors and version bumps out of
auto-merge is quietly weakened: it parses the three
acceptance regexes out of the workflow and asserts the digest-branch
regex stays anchored, confined to
`dependabot/docker/`, keeps its literal `/distroless/` scope and a
trailing hex-run floor of at least 7 (without the
scope a date-tagged bump such as `bump ubuntu from 202401151200 to
202402201200`, whose date tokens are all hex, would match
the title regex); the digest-title regex requires a `[0-9a-f]{7,}` run
on both the from and to sides; path B still
cross-checks the title as a conjunct of the branch shape and fails
closed on mismatch; and every group in
`.github/dependabot.yml` whose branch name path A accepts declares
`update-types` within `{minor, patch}`, so a major
can never ride a branch literally named `*-minor-and-patch`. The guard
fails closed if the workflow is missing, a
regex cannot be extracted, path B cannot be located, or no group is
accepted by path A.
- Dependabot no longer proposes TypeScript 7.x for the Node/UI packages.
`typescript-eslint`'s peer range is
`typescript >=4.8.4 <6.1.0`, so a TypeScript 7 bump fails `npm ci` with
`ERESOLVE` before lint or typecheck can run,
and nothing else in the tree raises that ceiling — the upgrade is
unmergeable until `typescript-eslint` ships
support for the new major. The `ignore` carries the reason and an
explicit revisit condition, so it is a recorded
decision rather than silent suppression.
- Dependabot version-ceiling ignores that guard a dependency declared in
the reactor parent `mockserver/pom.xml`
are now mirrored into every Dependabot block whose module inherits that
parent — `/examples/java` and
`/mockserver/mockserver-maven-plugin`. Because those child directories
resolve *up* into the parent pom, Dependabot
scanning them could bump a parent-declared dependency and brand the PR
with the child scope, sidestepping an ignore
that existed only in the `/mockserver` block. That is exactly how the
un-passable `checkstyle 12.3.1 -> 13.10.0`
PR
[#​2554](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2554)
was generated from `/examples/java` (checkstyle 13 ships Java 21
bytecode; the project floor is Java 17).
The `checkstyle >= 13.0.0` and `graphql-java` ceilings are now present
in all three parent-reaching blocks;
the module-only `infinispan-core` ignore is deliberately not mirrored
because it is unreachable from those scopes.
Each block carries a `SYNC-WITH-PARENT` note so future ignores are added
in every parent-reaching block.
- Corrected a second, freshly-introduced ceiling suppression of the same
class. The `typescript >= 7.0.0` ignore
added on 2026-08-17 was placed on the npm block **shared** by
`/mockserver-ui`, `/mockserver-client-node` and
`/mockserver-node`, but its rationale (a `typescript-eslint` peer
conflict) applies only to the UI.
`mockserver-client-node` was already on typescript `~7.0.2` — above the
ceiling — and carries no
`typescript-eslint`, so the ignore silently froze every typescript
update for that published package.
`/mockserver-ui` now has its own block carrying the ignore, mirroring
how `/mockserver-vscode` was already
split for the same reason: a directory-specific constraint must not leak
onto directories it does not apply to.
- Corrected a Dependabot ceiling that had been suppressing every
`graphql-java` update, including security patches.
The ignore read `>= 25.0.0` while `mockserver/pom.xml` had already moved
to `26.0`, so the in-use version was itself
above the ceiling and no candidate could ever be proposed. This was
found while mirroring the ignore into the two
parent-reaching blocks — the mirror would have propagated the fault
rather than the control. Raised to `>= 27.0.0`
in all three blocks and documented the invariant inline: **a ceiling
must stay above the version in use**, because
one at or below it is indistinguishable from a working ceiling — no pull
requests appear either way. The stale
"22.x line" comments in `mockserver/pom.xml` and the `< 25.0.0` row in
`docs/operations/security.md` are corrected
to match the 26.x reality.
- A managed `org.jspecify:jspecify` version (`1.0.1`) is now pinned in
`mockserver/pom.xml` `<dependencyManagement>`
so `maven-enforcer`'s `DependencyConvergence` stays green across Guava
and graphql-java bumps. Guava `33.7.0-jre`
pulls jspecify `1.0.1` while `graphql-java -> java-dataloader:6.0.0`
pulls `1.0.0`; with no managed version the two
transitive paths diverge the moment Guava moves, which is why Dependabot
PR
[#​2555](https://redirect.github.com/mock-server/mockserver-monorepo/issues/2555)
(`guava 33.6.0 -> 33.7.0`) failed
the enforcer. jspecify is an annotation-only artifact and `1.0.1` is a
backward-compatible patch that neither
consumer rejects, so the higher line is pinned.
##### Removed
- **BREAKING BEHAVIOUR: `org.mock-server:mockserver-examples` is no
longer published to Maven Central, and the
`org.mockserver.examples` JPMS automatic module is no longer
resolvable.** This artifact was only ever sample code
demonstrating client and proxy usage — not a supported consumer
dependency — but it had been GPG-signed and deployed
to Maven Central on every release (it was a `<module>` of the
`mockserver` reactor, and the release deploy runs
`mvn deploy -P release` over that whole reactor with no `-pl`
restriction). It has now been removed from the `mockserver`
reactor, so the release deploy no longer reaches it and no new versions
will appear on Central
(`skipPublishing=true` in its POM guards against a future re-add).
**Previously published versions (7.6.0 and earlier)
remain available and resolvable forever** — only new releases are
affected. Anyone who declared a dependency on
`mockserver-examples` or `requires org.mockserver.examples` should pin
the last published version or, preferably,
copy the sample code (`examples/java/`) into their own project. This is
marked `BREAKING BEHAVIOUR` rather than plain
`BREAKING` because it does not force a major version bump: the artifact
was never a supported dependency, no shipped
MockServer artifact depends on it, and every previously published
version stays available.
##### Fixed
- Fixed an order-dependent failure in the blob-store registrar tests,
surfaced by running the suite on hardware
with a different class ordering. `S3ExpectationPersistenceReloadTest`
starts a real server with
`blobStoreType("s3")`, which makes `StateBackendFactory` discover and
register the s3 factory in its JVM-global
registry, and its teardown stopped the server and the MinIO container
without resetting that registry. Every test
class in the module shares one reused fork under surefire's default
`filesystem` run order, which is not stable
across machines — so whenever that class happened to run first,
`S3BlobStoreRegistrarTest`'s "s3 should not be
registered before register()" precondition saw inherited state and
failed. The leak is now cleaned up on
teardown, and all three registrar tests (s3, gcs, azure) scrub the
registry on **entry** as well as exit, so the
precondition holds regardless of what ran before them. The gcs and azure
tests had the identical latent shape and
passed only because their modules contain no equivalent leaker.
Reproduced by forcing the losing order
(`-Dsurefire.runOrder=reversealphabetical`) and confirmed fixed under
it.
- The new fork-PR test workflow (`.github/workflows/pr-tests.yml`) now
reports one red per real failure instead of
three. A latent race in
`ThirdPartyStreamingClientConformanceIntegrationTest` surfaced on the
slower
`ubuntu-latest` runner:
`shouldDeliverMessageThenCloseWhenCloseConnectionIsSet` is the one case
whose server is
configured `withCloseConnection(true)` (it delivers `"bye"` and closes
immediately, by design), yet it asserted on
Java-WebSocket's `connectBlocking()` boolean, which returns
`connectLatch.await(...) && engine.isOpen()` — and that
latch is counted down by both `onWebsocketOpen` and `onWebsocketClose`,
so the deliberate close races the
`isOpen()` read and the bare assert fails in \~12 ms. It now asserts the
observable handshake outcome via the
client's `opened` latch (`onOpen` always precedes any close on a
successful handshake); the close, the `"bye"`
payload, and the orderly close code were already verified race-free and
are preserved. The product is unchanged —
`withCloseConnection(true)` did exactly what it promises. Two derivative
reds in the same workflow are gone too:
the standalone-examples step and the "assert Docker-gated suites
actually ran" step are now gated on the reactor
step succeeding (`steps.reactor.outcome == 'success'`) rather than
merely `!cancelled()`, so a reactor failure no
longer makes the examples build die with "Could not resolve dependencies
for … mockserver-examples" (the reactor's
`install` never completed) or makes the suite-ran check red on
`mockserver-blob-s3` with "the suite did not run"
(S3 was only skipped because of its test-scope reactor dependency on the
failed `mockserver-netty`, two modules
away). The suite-ran check stays fail-closed for the case it exists for:
a runner without Docker `assumeTrue`-skips
the suites, Maven still exits 0, so the reactor step succeeds, the check
runs, finds no report, and reds loudly.
- Dependabot now proposes grouped Maven updates for the core
`mockserver` reactor again. The reactor's
`mockserver/pom.xml` declared `<module>../examples/java</module>`, a
path that escaped Dependabot's
`directory: "/mockserver"` scope; with no repository-root `pom.xml`,
Dependabot re-parsed a scoped file subset,
found no top-level pom and aborted every grouped-update run for the
reactor with `No pom.xml!`. As a result **no**
grouped Maven PR was ever created for the core modules (broken since the
examples were unified in `d3cfa9aaf`),
while the self-contained `mockserver-maven-plugin` sibling kept working,
and `examples/java`'s own dependencies had
no coverage at all. `examples/java` is now removed from the reactor so
`/mockserver` is a self-contained Maven
directory; the examples are kept compiled and tested by a second
standalone Maven invocation in CI immediately after
the reactor `install` (`scripts/buildkite_quick_build.sh`), and their
own dependencies are covered by a new
`/examples/java` block in `.github/dependabot.yml`. (Vulnerability
*alerts* were never affected — those come from the
submitted dependency graph, not update proposal.)
- The release pipeline can no longer silently overwrite the previous
version's archived documentation site. Whether a
release creates a new versioned subdomain (`X-Y.mock-server.com`) is
fully determined by whether it is a major/minor
release, but it was a free operator dropdown (`create-versioned-site`)
defaulting to `no`. On the 7.6.0 release that
default was left in place, so terraform's `latest_version` still pointed
`main` at the previous version's bucket and
the docs publish (`aws s3 sync --delete`) destroyed the
`7-5.mock-server.com` archive. The value is now **derived**
from `RELEASE_VERSION` vs the previous tag in `require_release_inputs`
(the single input-validation chokepoint every
release script runs, before `prepare.sh` tags or pushes); the Buildkite
input defaults to `auto`, and an explicit
`yes`/`no` is honoured only as a confirmation that must agree with the
derived value or the run **fails closed**.
This makes both destructive mistakes impossible: a major/minor release
with `no` (overwrites the previous archive)
and a patch release with `yes` (spurious subdomain).
- Removed a live-internet dependency from the `mockserver-core` unit
tests. `ExpectationSerializerTest`
(`shouldAllowSingleOpenAPIObjectForArray` and
`shouldAllowMixedExpectationTypesForArray`) referenced the bundled
petstore OpenAPI spec via a `https://raw.githubusercontent.com/...` URL;
because `deserializeArray()` actually loads
the spec to generate example bodies, every ordinary build fetched that
URL over the internet. A transient HTTP 429
(rate limit) from `raw.githubusercontent.com` failed the test — and took
down the 7.6.0 release build after it had
already tagged and pushed. Both tests now resolve the byte-identical
copy from the test classpath
(`org/mockserver/openapi/openapi_petstore_example.json`, the same local
reference the sibling `HttpStateTest` and
`JsonSchemaExpectationValidatorTest` already use), so the suite no
longer depends on GitHub being reachable or
un-rate-limited. The behaviour under test (a single OpenAPI object
deserialising into an array of expectations with
the correct generated bodies) is unchanged and still fully asserted.
- The Rust client's `cargo clippy` gate no longer fails the build on an
unchanged source tree. The
`mockserver-rust` pipeline lints inside a container pulled from the
**floating** `rust:1` tag, and that tag moved to
clippy 1.98.0, whose `clippy::needless_late_init` now also flags
late-initialised `let` chains assigned across an
`if`/`else if` sequence. `resolve_platform()` in
`mockserver-client-rust/src/launcher.rs` had two such chains
(`os_name`/`ext`, and `arch`), so with `-D warnings` the lint became a
hard error and the crate stopped compiling —
on code nobody had touched. Master build
[#​638](https://redirect.github.com/mock-server/mockserver-monorepo/issues/638)
passed this exact source; build
[#​639](https://redirect.github.com/mock-server/mockserver-monorepo/issues/639),
fifteen hours later on a newer
`rust:1`, failed it, which also red-herring-failed an unrelated
Dependabot pull request whose only change was to a
Java dependency. Both chains are now initialising `if`/`else`
expressions (a tuple for the jointly-assigned
`os_name`/`ext` pair), exactly the rewrite clippy itself suggests; the
diverging `else` arms still `return Err(...)`
and coerce as `!`. Behaviour is byte-for-byte identical — same platform
tokens, same error messages, same `Platform`
— and was confirmed by running the fix under the real clippy 1.98.
> ❗ **Important**
>
> ✂ PR body was truncated to here.
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/prometheus/client_java).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC45MC4zIiwidXBkYXRlZEluVmVyIjoiNDQuOTAuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>1 parent 1ff0baa commit 9921598
1 file changed
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| |||
0 commit comments