Conversation
commit: |
Contributor
|
🚀 Deploy Preview Ready!
|
taras
force-pushed
the
tm/smoke-tests-own-server
branch
from
October 2, 2026 03:52
0dbb0bc to
f4e62bd
Compare
taras
force-pushed
the
tm/smoke-tests-own-server
branch
from
October 2, 2026 03:56
f4e62bd to
b7b4e0e
Compare
The markdown smoke tests asserted against a site someone else had started. The workflow backgrounded `deno run -A main.tsx &`, polled with curl until the port answered, and handed the address over in SMOKE_URL. Nothing said so at the call site, `deno task smoke` on its own produced a wall of connection errors, and CI leaned on a background process surviving between steps. They start their own now. `serve` is split so the part that builds and starts the site is a resource, `useSite`, and `serve` is that plus the suspend that keeps the process alive. The suite takes that resource in a `beforeAll` from `@effectionx/bdd`, which holds it on the suite's scope: the site is up for every case and goes away with the suite. There is nothing to poll for and nothing to shut down by hand — `start()` resolves from `Deno.serve`'s `onListen`, and `revolution` closes the server in the resource's `finally`. One site for the suite rather than one per case is also forced: `initImageStore` can only initialize resvg's wasm once in a process. The options come from the Configliere command, so the defaults stay declared in one place, with four changed: port 0, so a dev server on 8000 is left alone, and clones, worktrees and tailwind output under build/smoke, because the site empties all three at boot and would otherwise pull them out from under a server already running. `deno task smoke` gains `-A`: booting the site runs git, shells out to tailwind and writes build directories. The workflow no longer passes a url, and the smoke step moves above the one that serves the site to show it no longer waits on it. That step stays, because staticalize still crawls it.
taras
force-pushed
the
tm/smoke-tests-own-server
branch
from
October 2, 2026 04:03
b7b4e0e to
f733b3f
Compare
`www/testing.ts` and `www/testing/adapter.ts` were a copy of `@effectionx/bdd` and the test adapter underneath it, and had not been touched since a lint sweep in January. The published package does the same thing — `describe` and `it` with operation bodies, a scope per suite — and keeps up with effection. The two files that used it import `describe` and `it` with the same signatures, so only the specifier changes. `@std/testing` leaves the import map with the harness that was its only consumer; the package resolves its own copy. `beforeAll` is the reason to move: the local fork never had it, and holding a resource for a whole suite is what the smoke tests need.
The helper the cases call wrapped a promise chain in `until` to turn a
response and its body into one operation. `@effectionx/fetch` is that
already — the request is an operation and so is reading the body:
function* get(path: string) {
let response = yield* fetch(new URL(path, site));
return [response, yield* response.text()] as const;
}
No promise to adapt, and nothing in the file is `async` any more.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The markdown smoke tests added in #1247 assert against a site that someone else
has already started. The workflow backgrounds
deno run -A main.tsx &, pollswith
curluntil the port answers, and hands the address over inSMOKE_URL:Nothing at the call site says so.
deno task smokeon its own produces a wallof connection errors, the file carries a comment explaining it is deliberately
not named
*.test.tsbecause "there is no server to talk to", and CI leans on abackground process surviving between workflow steps.
Approach
useSite, a resourceserveis split so the part that builds and starts the site is a resource, andserveis that plus the suspend that keeps the process alive:Teardown needed no new code —
revolution'suseServeris already a resourcewhose
finallycallsserver.shutdown(), so ending the scope is enough. Nor isthere anything to poll for:
start()resolves fromDeno.serve'sonListen, soholding the
ServerInfomeans the socket is bound.The suite takes the site in a
beforeAll@effectionx/bddis effection-native:itbodies are generators, andbeforeAlltakes an operation whose resources are held on the suite's scope —it runs the setup in a spawned task that then suspends, and the suite's
afterAllhalts it. That is exactly the lifetime wanted here, already writtenand maintained:
Nothing bridges a value out of effection, nothing is halted by hand, and there
is nothing to poll for:
start()resolves fromDeno.serve'sonListen, andrevolutioncloses the server in the resource'sfinally.One site for all seven cases rather than one each, which is also forced:
initImageStorecan only initialize resvg's wasm once in a process.(Earlier revisions of this branch reached for
createScope, then forrunplusa parked task and a promise to carry the url out. Both were hand-rolled versions
of what
beforeAllalready does.)Options, and staying out of the way
The options come from the Configliere command, so the defaults stay declared in
one place and
GITHUB_TOKEN/JSR_APIare still picked up when present. Fourare overridden:
port: 0— the OS picks, so a dev server on 8000 is left aloneclonesDir,worktreesDir,tailwindOutdirunderbuild/smoke/— the siterm -rfs the first two andemptyDirs the third at boot, so sharingbuild/means whichever process starts second pulls the directories out from under the
other
deno task smokegains-A: booting the site runs git, shells out to theTailwind CLI, and writes build directories, where before it only needed net and
env.
The file keeps its name.
www/deno.jsonhas no testexclude, so not being*.test.tsis the only thing keeping it out ofdeno task test— and out of thehundreds of
*.test.tsfiles that appear underbuild/once clones exist. Theheader comment now gives the real reason: it is slow and needs the network.
The workflow
Both jobs lose
SMOKE_URLand gain the two secrets on the smoke step, and thestep moves above
Serve Websiteso the ordering shows it no longer waits onanything.
Serve Websitestays — staticalize still crawls it.Tests
with nothing else running, which is the whole point — that command fails today.
Checks that mattered:
The site really does go away with the suite. Not something to take on
trust: Deno's sanitizers do not watch a
Deno.servelistener here, so anearlier revision of this branch passed just as happily with its teardown
deleted. Proved it directly instead, with a second suite that asks the first
one's port after it has been destroyed:
which also confirms
port: 0is taking effect.The suite can actually fail.
t.stepresolves a boolean rather thanthrowing, so I checked that a broken assertion still fails the run rather than
being swallowed:
The directory overrides actually apply —
build/smoke/ends up with itsown
clones/thefrontside/effectionx,worktrees/{v3,effection-v4.1.1,…}andtailwind/main.css, so the server really is building its own copies.No collision with a dev server. With
deno run -A main.tsxlive on 8000,deno task smokepasses, and afterwards the dev server still answers 200 on/,/blog,/guides/v4/operationsand/x/task-bufferand still serves itsown
/tailwind/main.css. Before the directory overrides this is exactly whatwould have broken.
The split is invisible to the app.
deno run -A main.tsxstill logswww -> http://localhost:8000/, anddeno task staticalizeagainst it stillproduces a full build — 719 pages, 21 assets, canonical links intact.
deno fmt --check,deno lint,deno check, and the 10 unit tests pass, anddeno task teststill does not pick the smoke file up.Note
CI now starts the site twice per job, about +18s, since the smoke tests no longer
share the one staticalize uses. That is the cost of the tests being runnable on
their own.
Also: the http helper is an operation
Third commit. The helper the cases call wrapped a promise chain in
untiltoturn a response and its body into one operation.
@effectionx/fetchis thatalready — the request is an operation and so is reading the body:
markdown()takes itsFetchResponse, which carriesstatusandheadersthe same way. Nothing in the file is
asyncany more.It is an
npm:specifier because the package is not on JSR. Its own dependencyon
@effectionx/context-api@0.6is the versionwwwalready has.Also: the local bdd harness goes
Second commit.
www/testing.tsandwww/testing/adapter.tswere a copy of@effectionx/bddand the adapter underneath it, untouched since a lint sweep inJanuary. Now that this branch depends on the package anyway, the fork has no
reason to stay:
hooks/use-markdown.test.tsandlib/command-parser.test.ts— takedescribeanditwith identicalsignatures, so only the specifier changes
@std/testingleaves the import map with the harness that was its only directconsumer; the package resolves its own copy
beforeAllis what prompted it: the local fork never had one, and holding aresource for a whole suite is exactly what these smoke tests need. Keeping a
fork that is missing the hook we want, next to the package that has it, is the
worse of the two options.
199 lines deleted, 2 changed.
deno task testis unchanged at 10 passed,29 steps, and both migrated files still run every case.
Left alone
www/testing/temp-dir.ts,logging.tsandhelpers.tsstay. They are testutilities rather than a bdd harness, so the package does not replace them —
but it is worth saying that nothing imports any of the three, and nothing has
since January. Removing them is a separate call, not this one.