Skip to content

chore: back-merge main into develop - #6

Merged
lorem-dev merged 4 commits into
developfrom
main
Aug 3, 2026
Merged

chore: back-merge main into develop#6
lorem-dev merged 4 commits into
developfrom
main

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Automated back-merge of main into develop.

Latest commit on main: b4a4009 -- fix: decide a mock before the faults, and collapse leading slashes

Opened by Back-merge main -> develop, run 30796973595.

Merge this (or turn on auto-merge) to keep develop in step with
main. Resolve any conflicts here rather than on develop.

Two divergences between what the configuration says and what the pipeline
did.

`replace` was the share of matching requests that survived the loss roll,
not the share of matching requests. The pipeline decided loss and latency
first, so `loss: 0.5` with `replace: 0.5` answered a quarter of matching
requests from the mock rather than half, and no configuration could ask
for half while any loss was set. Mock matching now comes first, and the
proxy's `loss` and `latency` no longer touch a request a mock answered --
they describe the real backend, and a mock replaces it. Measured against
a running server, 600 requests: 292 mocked, 161 dropped, 147 forwarded,
where the old order gave a quarter mocked.

A run of slashes at the start of the path is collapsed to one before
matching, so `//api/v1/index/` matches a mock declared
`^/api/v1/index/$`. A base URL ending in `/` joined to a path beginning
with `/` produces that form constantly, it is legal HTTP so nothing
rejected it, and an unanchored pattern matched it anyway -- the extra
slash falls outside the substring being looked for. Only an anchored
pattern failed, silently. Empty segments elsewhere are left alone:
whether `/a//b` and `/a/b` name one resource is the upstream's to decide,
and answering it here would disagree with the path that gets forwarded.

Both verified by mutation. Removing the normalisation fails three tests;
restoring the old order fails the mock-beats-loss test. The end-to-end
slash test uses an anchored pattern deliberately -- with an unanchored one
it passed under the mutation and pinned nothing.

Also documents that a mock's `proxy.loss` and `proxy.latency` are parsed,
validated and compiled, and then never read. Only `proxy.replace` is
applied per mock. The documentation claimed all three were.
An injected delay was added to whatever the upstream took, so the number
written in the configuration was never the number a client saw and moved
with whatever the backend happened to be doing: `min: 0.5` in front of a
backend answering in 120ms produced 620ms. The delay is now a target --
the upstream's real time is subtracted and only the remainder is waited
out. Measured against a running server: 503ms total, 375ms of it injected,
124ms of it real.

The wait therefore moves to after the response is produced, which is the
only place the real time is known. Loss still short-circuits it: a dropped
request returns from the loss branch and is never delayed, so refusing a
request and then holding the connection open cannot happen.

An upstream slower than the target leaves no remainder and is passed
straight through -- 900ms upstream under a 500ms target gives 908ms, not
1.4s. The setting is a floor, never a ceiling; Doppel does not make a slow
backend look fast. `latency_injected_ms` is the wait actually taken and
reads 0 there, while `doppel_latency_injected_total` still counts the
request, because the roll did fire.

A mock now inherits `latency` from its proxy and overrides rather than adds
to it, since the configured latency says how slow this proxy is to answer
and that holds whatever answers. Verified live: a mock under a 500ms proxy
answers in 503ms, and one overriding with 150ms answers in 153ms rather
than 653ms. `loss` remains the one setting a mock does not inherit --
inheriting it would put back the coupling between `loss` and `replace`
removed in b4a4009.

Both the subtraction and the latency inheritance are pinned by mutation:
dropping `saturating_sub` fails two tests, and removing the fallback to the
proxy's latency fails a third. The padding arithmetic is unit-tested
directly, since the interesting cases are exact numbers and asserting those
on wall clock would be a claim about the scheduler.
The site was a single unversioned build, so publishing 0.2.0 replaced
0.1.0's documentation outright and a reader running 0.1.0 had nowhere to
find the pages describing what they were running. That matters more than
usual for this release: 0.2.0 changes what `replace` means and what an
injected `latency` does, so 0.1.0's pages are not merely older, they
describe different behaviour.

mike keeps one built copy per version on a `gh-pages` branch it owns,
alongside the `versions.json` that fills the switcher in the header. The
Pages source moves from "GitHub Actions" to that branch, and the workflow
drops `pages: write` and `id-token: write` -- nothing talks to the
deployment API any more.

What gets published now depends on the ref: a push to `main` becomes `dev`,
a final tag becomes its bare version number and moves `latest`, and a
pre-release tag publishes nothing. The site root redirects to `latest`, so
the bare URL lands on the newest release rather than on unreleased
documentation. Pre-releases are excluded twice over -- the tag filter and a
check in the script -- because `workflow_dispatch` can be pointed at any
ref and the filter alone would not stop it.

0.1.0 and 0.2.0 were built and pushed from a checkout of each, so the
switcher has both from the start rather than only from the next release
onwards. The 0.1.0 build needed `extra.version.provider` added to its
`mkdocs.yml` in a throwaway worktree, since that tag predates this commit;
the tag itself is untouched and the pages are the ones 0.1.0 shipped.
@lorem-dev
lorem-dev merged commit 890b8bc into develop Aug 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant