diff --git a/.github/workflows/docs-verify.yml b/.github/workflows/docs-verify.yml index 89e1c1d1fe..f7fa3f92dc 100644 --- a/.github/workflows/docs-verify.yml +++ b/.github/workflows/docs-verify.yml @@ -140,10 +140,8 @@ jobs: # lets `wheels new` succeed, which makes fixture cwds real. See # #2178 for the full root-cause write-up. # - # Still soft-fail: surfaces the remaining tutorial-driver fixture - # issues (e.g., blog-tutorial's lucee.json emission). Drop - # continue-on-error once those are fixed. - continue-on-error: true + # Blocking: the last known failure, the mini-tutorial reloading before + # any server was started, is fixed (#4426). env: WHEELS_FRAMEWORK_PATH: ${{ github.workspace }}/vendor/wheels run: | diff --git a/web/sites/guides/scripts/verify-docs/drivers/tutorial.mjs b/web/sites/guides/scripts/verify-docs/drivers/tutorial.mjs index 3e6b789228..d6795f134a 100644 --- a/web/sites/guides/scripts/verify-docs/drivers/tutorial.mjs +++ b/web/sites/guides/scripts/verify-docs/drivers/tutorial.mjs @@ -160,10 +160,24 @@ export class TutorialSession { async applyCliExample(ex) { await this.ensureInitialised(); + // A reader following the tutorial has the dev server running by the time a step reloads, + // lists live routes, migrates or runs tests, and those commands refuse without this + // project's own server (#4426). Start the fixture's server first, as for HTTP asserts. + if (needsServer(ex.attrs.cmd)) { + await this.ensureServer(); + } return await runCliInFixture(ex); } } +// `wheels` commands that talk to the project's running dev server. +const SERVER_COMMANDS = new Set(['reload', 'routes', 'test', 'migrate', 'seed', 'console']); + +export function needsServer(cmd) { + const [program, verb] = String(cmd ?? '').trim().split(/\s+/); + return program === 'wheels' && SERVER_COMMANDS.has(verb); +} + async function runCliInFixture(ex) { const cmd = ex.attrs.cmd; if (!cmd) return { ok: false, message: 'missing required attr: cmd' }; diff --git a/web/sites/guides/scripts/verify-docs/test/tutorial.test.mjs b/web/sites/guides/scripts/verify-docs/test/tutorial.test.mjs index ddb5dadee0..6985d95e76 100644 --- a/web/sites/guides/scripts/verify-docs/test/tutorial.test.mjs +++ b/web/sites/guides/scripts/verify-docs/test/tutorial.test.mjs @@ -91,3 +91,13 @@ test('tutorial driver walks mini-tutorial end to end', { timeout: 300_000 }, asy await session.stopServer(); } }); + +test('cli steps that need the dev server start it first', async () => { + const { needsServer } = await import('../drivers/tutorial.mjs'); + for (const cmd of ['wheels reload', 'wheels routes', 'wheels test', 'wheels migrate latest', 'wheels seed', 'wheels console']) { + assert.equal(needsServer(cmd), true, cmd); + } + for (const cmd of ['wheels generate model Post', 'wheels start', 'wheels stop', 'wheels new app', 'npm test', '']) { + assert.equal(needsServer(cmd), false, cmd); + } +});