Skip to content

🐛 Restore the default for --retries - #20

Merged
taras merged 1 commit into
mainfrom
retries-default
Sep 27, 2026
Merged

taras merged 1 commit into
mainfrom
retries-default

Conversation

@taras

@taras taras commented Sep 26, 2026

Copy link
Copy Markdown
Member

Motivation

Closes #19.

--retries was documented as optional and required in practice, so every invocation that left it off failed:

staticalize --site=http://127.0.0.1:8000 --output=www/built --base=https://frontside.com/effection
→ retries: Invalid input: expected number, received undefined

0.2.6 accepts that command; 0.3.0 rejects it, which blocked adopting 0.3.0 without editing every caller — including this project's own deploy workflow.

Approach

configliere derives requiredness from the schema: required: !!validate(schema, undefined).issues. A field is required exactly when its schema rejects undefined, and z.number() does.

The fix is not a field.default, because the default depends on --strict — 0 when strict, 3 otherwise — and a field cannot see a sibling. main.ts already computes it once both are parsed:

let retries = retriesRaw ?? (strict ? 0 : 3);

So the schema only has to admit the absent value: z.number().optional(). The help text now names both defaults instead of mentioning only the strict one, and --help renders the flag as [RETRIES] rather than <RETRIES>.

Verification

Every row of the table in the issue, against the three-page test site, stdin closed:

invocation before after
--site … --output … --base … received undefined crawls
… --retries=3 crawls crawls
… --concurrency=75 --retries=3 crawls crawls
… --strict received undefined crawls

New test/config.test.ts covers the deploy invocation parsing, retries staying unset so the --strict-dependent default still applies, --retries being honored when passed, the concurrency and strict defaults, and --base still being required. With the one-word fix reverted, 4 of its 6 steps fail, so it does guard the regression rather than merely passing. Suite is 30 green.

Two things found on the way, not fixed here

The received string variant in the issue is env, not stdin. Config values are read from the environment under bare keys — RETRIES, CONCURRENCY — with no program prefix, since main.ts hands Deno.env.toObject() to the parser. With the bug, an ambient RETRIES decided which failure you got:

env before after
none received undefined retries=undefined
RETRIES=7 retries=7 retries=7
RETRIES=banana received string retries=undefined (invalid source ignored)

Argument parsing also finishes before initStdin is ever reached, so stdin cannot affect it. Worth deciding separately whether bare env keys are wanted, or whether they should be prefixed.

A bad invocation exits 0. main.ts prints the parse error and falls through without exit(1), so a misconfigured run looks like success to CI and leaves an empty output directory. That is what made this regression dangerous in a deploy workflow rather than merely annoying. Happy to fix in a follow-up.

`retries` was declared with a schema that rejects `undefined`, which makes
the field required: every invocation that left the flag off failed with
`retries: Invalid input: expected number, received undefined`, including the
one this project's deploy workflow has always used. 0.2.6 accepted it, so
0.3.0 could not be adopted without editing every caller.

The default cannot be a `field.default`, because it depends on `--strict`,
which a field cannot see. `main.ts` already computes it once both are
parsed; the schema just has to admit the absent value, so it is now
`z.number().optional()` and the help text names both defaults.

Closes #19
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.

--retries has no default, so the CLI cannot run without it

2 participants