<feed xmlns='http://www.w3.org/2005/Atom'>
<title>vyos-documentation.git/scripts, branch claude/datatables-2x-upgrade</title>
<subtitle>VyOS readthedocs (mirror of https://github.com/vyos/vyos-documentation.git)
</subtitle>
<id>https://git.amelek.net/vyos/vyos-documentation.git/atom?h=claude%2Fdatatables-2x-upgrade</id>
<link rel='self' href='https://git.amelek.net/vyos/vyos-documentation.git/atom?h=claude%2Fdatatables-2x-upgrade'/>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/'/>
<updated>2026-07-22T15:53:45+00:00</updated>
<entry>
<title>docs-gates: hard-bound the smoke deadline (cap probe timeout + inter-round sleep to remaining budget)</title>
<updated>2026-07-22T15:53:45+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-07-22T15:53:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=cef13a0cd6aa64ab2a9b30fe1199d60939846357'/>
<id>urn:sha1:cef13a0cd6aa64ab2a9b30fe1199d60939846357</id>
<content type='text'>
Codex adversarial finding: DEADLINE_SECONDS was only checked BEFORE each op, so a
probe or sleep starting at 479s could overshoot to ~510s — 480 was a soft target,
not a hard bound.

Make it hard: run() now computes an absolute deadline = start + DEADLINE_SECONDS
plus a _remaining() helper. The per-probe socket timeout is capped to
min(PROBE_TIMEOUT_SECONDS, max(1, remaining)) — the previously hardcoded 30 is now
the PROBE_TIMEOUT_SECONDS constant; a probe with &lt; 1s of budget is skipped and
counted unresolved. The inter-round sleep is capped to
min(RETRY_SLEEP_SECONDS, remaining) and is skipped entirely when the budget is
exhausted (falling into the existing deadline path). No body-read-level deadline is
added — pages are small, so the socket-op timeout bounds reads adequately.

Deadline-path failure accounting is unchanged. Tests: the probe timeout is capped
to the remaining budget (fake opener records the timeout it was opened with); the
inter-round sleep is capped to the remaining budget (sleep spy); the existing suite
stays green.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
<entry>
<title>docs-gates: widen smoke retry envelope for worker-version propagation (5 rounds x 30s)</title>
<updated>2026-07-22T15:39:42+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-07-22T15:30:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=95b8a4115439826e7dff767bf3515684535d0783'/>
<id>urn:sha1:95b8a4115439826e7dff767bf3515684535d0783</id>
<content type='text'>
The merge-triggered smoke run for the round-based retry work failed on a
worker-version propagation race that outlasted the 3-round x 20s envelope: all
probes were served the previous SHA through rounds 1-2 and one path (cli.html)
was still stale at round 3 (2 sleeps x 20s = 40s insufficient).

Widen to MAX_ROUNDS=5 / RETRY_SLEEP_SECONDS=30 -&gt; 4 inter-round sleeps x 30s =
2 min, covering the observed 1-2+ min propagation waves. The green path is
unaffected (no retries -&gt; zero added time); DEADLINE_SECONDS=480 still bounds the
worst case. Tests read the constants dynamically (monkeypatch), so none pin the
old literals.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
<entry>
<title>docs-gates: close HTTPError response; name failed assertion in smoke logs (CR round 2)</title>
<updated>2026-07-22T15:29:29+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-07-22T15:13:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=6ae607d4c37f2c61a5b06fc5649e46dac63eaac8'/>
<id>urn:sha1:6ae607d4c37f2c61a5b06fc5649e46dac63eaac8</id>
<content type='text'>
Two accepted GitHub-side CodeRabbit findings on the smoke gate:

Close the HTTPError response stream: _probe_once read the non-2xx body via
e.read() but never closed the HTTPError, which is file-like and owns the
response socket — leaking it / raising ResourceWarning on the expected-404 path
every run. The read is now wrapped in "with e:" INSIDE the crash-containment
nesting, so the stream is closed even if the read raises (still yielding the
retryable transport-error result, never a traceback).

Name the failed assertion in retry/fail logs: _probe_once now returns a compact
`detail` naming which check failed ("status" / "docs-build" / "apex-build" /
"search-mount", multiple joined by "+", or the transport error text; None when
ok) instead of a bare transport-only field. SMOKE-RETRY / SMOKE-FAIL lines gain
`detail=&lt;...&gt;` alongside the existing status / docs-build fields, so an apex-build
or search-mount failure no longer logs an opaque "status=200 docs-build=&lt;sha&gt;".
ok-path behavior and the JSON / exit contract are unchanged.

Tests: HTTPError stream is closed on the happy-404 path and when the read raises
(RecordingBody close recorder); apex-build-only and search-mount-only failures
name their detail in the logs; _probe_once joins multiple failed checks with "+".
Removed the now-unused _http_error helper.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
<entry>
<title>docs-gates: round-based smoke retries + deadline; contain HTTPError read crash; dedup index probe (review round 1)</title>
<updated>2026-07-22T14:27:20+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-07-22T14:27:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=f1dcd5ac53decfb3b11c7eb281ddfb3ea4c94d12'/>
<id>urn:sha1:f1dcd5ac53decfb3b11c7eb281ddfb3ea4c94d12</id>
<content type='text'>
Adversarial round (Codex + agy, both REQUEST CHANGES) on the per-probe retry
model shipped in the prior commit — reworked:

Round-based retries (both providers' critical): probe the whole plan once, then
re-probe ONLY the still-failing probes each round (up to MAX_ROUNDS=3, one
RETRY_SLEEP_SECONDS=20 gap between rounds). A probe passing in any round passes.
This keeps the full per-probe failure enumeration (diagnostic value) that a
fail-fast retry would lose, while bounding added time to at most 2 sleeps.
DEADLINE_SECONDS=480 (time.monotonic from run() start, checked before each probe
AND before each inter-round sleep) caps total wall-clock; on breach a single
SMOKE-DEADLINE line is logged and every unresolved probe counts as failed.
Intermediate not-ok logs "SMOKE-RETRY &lt;path&gt;: round &lt;n&gt; ..."; the JSON
{"failures": n} summary and exit contract are unchanged.

Contain HTTPError read crash (agy critical): a transport error DURING e.read()
inside the HTTPError branch previously escaped the outer catch and crashed the
gate. _probe_once now nests the open/HTTPError handling so ANY exception on the
open OR body-read path yields a retryable transport-error result, never a
traceback.

Dedup index probe (agy): critical-pages.txt lists index.html, so
/en/&lt;slug&gt;/index.html was probed twice. probe_plan now filters index.html out of
the critical list; plan[0] stays the single index (and sole search-mount) probe.

ua-policy.json intentionally left unchanged (pushback recorded: fail-open plus
block-precedence make an allow entry non-protective).

Tests reworked for round semantics: transport-error recovery across rounds,
HTTPError-read containment, one-sleep-per-inter-round-gap spy, round scoping
(only the failed path re-probed), run() JSON + exit contract, zero-deadline
path, and index-probe dedup.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
<entry>
<title>docs-gates: smoke per-probe retry + explicit UA; workers: broaden asset-ext classification</title>
<updated>2026-07-22T14:06:27+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-07-22T14:06:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=2c696df25168c654cf6af657e4407ac7fae27c75'/>
<id>urn:sha1:2c696df25168c654cf6af657e4407ac7fae27c75</id>
<content type='text'>
smoke.py — BIC independence: probe requests now send an explicit User-Agent
(vyos-docs-smoke/1.0) so the gate no longer depends on a Cloudflare Browser
Integrity Check UA-skip rule surviving. The default Python-urllib UA was blocked
by BIC until that exemption was added; a silent dependency on it is a latent gate
failure the moment the rule is touched.

smoke.py — propagation-race tolerance: each probe now retries up to 3 attempts
(20s apart; MAX_ATTEMPTS + RETRY_SLEEP_SECONDS are module-level so tests can shrink
them) and only fails after the final attempt. A freshly deployed worker version
loses a brief propagation race in which a single probe is served by the PREVIOUS
version (observed: status 307 + stale X-Docs-Build minutes after deploy), which
previously failed the entire gate. Intermediate attempts log SMOKE-RETRY; only
exhaustion logs SMOKE-FAIL and counts a failure. Retry fires only on a not-ok
outcome (wrong status, wrong/missing build header, missing search mount, or a
transport exception); a legitimately-expected 404 passes on the first attempt.

workers/branch — broaden asset classification (CodeRabbit post-merge nit): fold
.pdf into the case-insensitive ASSET_EXT_RE and add webp + otf, so uppercase .PDF
and modern image/font assets get the longer asset cache class. /_static/ and
/_images/ path checks unchanged.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
<entry>
<title>docs: Cloudflare Workers hosting pipeline (apex, content workers, CI, previews) (#2140)</title>
<updated>2026-07-10T14:14:13+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-07-10T14:14:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=21689ef59b0eb34b1a29eda739dc10d33d25b44a'/>
<id>urn:sha1:21689ef59b0eb34b1a29eda739dc10d33d25b44a</id>
<content type='text'>
* docs-infra: scaffold Cloudflare workers workspace (versions.json v2, matrix, toolchain)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: record full Phase-0 plan decision in workers/PLAN.md

🤖 Generated by [robots](https://vyos.io)

* docs-infra: shared content worker — asset serving, cache classes, X-Docs-Build, canary no-store

🤖 Generated by [robots](https://vyos.io)

* docs-infra: run worker script before assets; test fetch entrypoint

🤖 Generated by [robots](https://vyos.io)

* docs-infra: apex manifest loader + dispatch map + runtime binding guard (TDD)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: apex redirects (aliases, PDF, trailing-slash) + special paths (TDD)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: PDF redirect honors pdf:null and preserves query

🤖 Generated by [robots](https://vyos.io)

* docs-infra: apex UA gate — allowlist-wins, log-only AI crawlers, empty block list at launch

🤖 Generated by [robots](https://vyos.io)

* docs-infra: apex router (pipeline §3.2), themed 404/503, /kb seam, env configs + congruence test

🤖 Generated by [robots](https://vyos.io)

* docs-infra: add missing-User-Agent regression test for apex UA gate

🤖 Generated by [robots](https://vyos.io)

* docs-infra: R2-streaming preview worker — MIME map, noindex, no-store (TDD)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: preview 404 no-store + fetch handler tests

🤖 Generated by [robots](https://vyos.io)

* docs-infra: bootstrap script — binding-target workers must exist before apex deploys

🤖 Generated by [robots](https://vyos.io)

* docs-infra: apex run_worker_first, lockfile for npm ci, PDF Location from manifest

🤖 Generated by [robots](https://vyos.io)

* docs-infra: derive html_baseurl from DOCS_VERSION_SLUG with RTD fallback (canonical gate prereq)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: version picker + status banner + language scaffold (vanilla JS, TDD pure core)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: picker preserves query+hash across switch; valid breadcrumb markup

🤖 Generated by [robots](https://vyos.io)

* docs-infra: Pagefind search wrapper with runtime base-path + preview prefix handling (TDD)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: pagefind wrapper — asset-failure notice + UI stylesheet load

🤖 Generated by [robots](https://vyos.io)

* docs-infra: gate Pagefind searchbox to CF builds (RTD keeps stock search until cutover)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: deploy sanity gates — limits, critical pages, count-delta, canonical (TDD)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: hermetic gate tests via fixture versions.json

🤖 Generated by [robots](https://vyos.io)

* docs-infra: docs-build workflow — candidate/smoke/promote two-stage deploy + registry + rollback

Two-stage CF Workers pipeline: build in pinned container, assemble artifact,
sanity gates, deploy candidate, scoped pre-traffic smoke via canary apex,
promote (rollback-id capture, hostname purge, registry upload), post-promote
probe + auto-rollback. DOCS_CF_LIVE repo variable gates every docs.vyos.io
production interaction pre-cutover.

scripts/docs_gates/smoke.py adds one authorized check beyond the spec: the
version's index.html probe asserts the #vyos-search mount div is present in
the response body, guarding CI silently forgetting DOCS_VERSION_SLUG (which
would otherwise ship stock RTD search without the Pagefind gate noticing).

🤖 Generated by [robots](https://vyos.io)

* docs-infra: build docs image in-workflow with buildx cache (v4.1 — digest pin dropped)

Plan v4.1 amendment: the ghcr.io digest-pinned image does not exist (workflow
would hard-fail at the first docker step on every push). Replace the BUILD_IMAGE
env placeholder with an in-workflow docker build from docker/Dockerfile via
docker/setup-buildx-action@v3 + docker/build-push-action@v6 (context: docker/,
load: true, tags: docs-build:local, GHA cache from/to). The checked-out commit
is the pin; buildx GHA cache keeps repeat builds cheap. Sphinx-build step swaps
to docs-build:local; inner script unchanged.

🤖 Generated by [robots](https://vyos.io)

* docs-infra: apex/preview deploy workflow — canary auto, production behind environment approval

* docs-infra: apex-deploy concurrency guard (per-ref, cancel-in-progress)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: fork-safe PR preview pipeline — approval record, R2 prefixes, label consumption, cleanup

* docs-infra: nightly preview sweep — pipefail + per-prefix failure isolation

🤖 Generated by [robots](https://vyos.io)

* docs-infra: nightly canary QA — per-entry sweep + URL-parity corpus vs RTD

🤖 Generated by [robots](https://vyos.io)

* docs-infra: parity sweep scoped to CF-built versions; transport-error resilience

🤖 Generated by [robots](https://vyos.io)

* docs-infra: one-off bootstrap workflow (binding targets — runs once on this push)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: remove one-off bootstrap workflow (bootstrap complete)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: one-off canary apex + preview deploy (route targets for Task 3.6 step 2c)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: remove one-off canary deploy workflow (targets live)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: address Phase-0 CodeRabbit findings (canonical gate, error caching, registry pointer, validation)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: strengthen manifest tests (full dispatch iteration, mutation-free validate)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: address GitHub CodeRabbit review (pointer-after-probe, fail-closed sweeps, block-precedence UA gate, preview hardening)

🤖 Generated by [robots](https://vyos.io)

* docs-infra: adversarial review fixes — error no-store, probe retry, PR-list membership, preview dotted-segment

🤖 Generated by [robots](https://vyos.io)

* docs-infra: serve oversized legacy PDF from R2 via apex (spec §5 fallback)

The 1.3 PDF (29.2 MiB) exceeds the 25 MiB static-asset cap and is absent
from the legacy content Worker's build, so /_/downloads/en/1.3/pdf/ (and
the picker's PDF link) 301'd into a dead-end 404 post-cutover. Add the R2
object fallback spec §5 already documented but never implemented: a
DOCS_PDFS R2 bucket binding on the apex Worker, a manifest pdf_r2_key
field (1.3 only), and a router step ahead of version dispatch that streams
the object with its own cache class (canary/error still force no-store).

🤖 Generated by [robots](https://vyos.io)

* docs-infra: PDF R2 fallback honors Range + If-None-Match, preserves ETag

🤖 Generated by [robots](https://vyos.io)</content>
</entry>
<entry>
<title>ci(doc-linter): anchor .. code-block:: detection + drop debug print</title>
<updated>2026-05-14T04:45:25+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-05-14T04:45:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=e87278ef35660a6257b55f4585274a52d3124583'/>
<id>urn:sha1:e87278ef35660a6257b55f4585274a52d3124583</id>
<content type='text'>
Addresses Copilot review on PR #2023:

1. .. code-block:: tracking was triggered by a plain substring check, which
   matched mid-line occurrences too. In MD prose like ``.. code-block::``
   (docs/documentation.md:222) this set in_rst_codeblock=True spuriously and
   could suppress line-length checks downstream. Replace with a leading-whitespace-
   anchored regex and gate on file_ext in ('.rst', '.txt') or an open {eval-rst}
   MyST fence so the directive opener is only recognized where it can actually
   occur.

2. print('start') in main() was leftover debug noise — remove it.
</content>
</entry>
<entry>
<title>ci(doc-linter): fix \b regression in compressed-IPv6 regex — replace bare removal with word-boundary prefix</title>
<updated>2026-05-13T21:55:52+00:00</updated>
<author>
<name>copilot-swe-agent[bot]</name>
<email>198982749+Copilot@users.noreply.github.com</email>
</author>
<published>2026-05-13T21:55:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=be8090a3a09adb950557c2887c9a27c017ffd31d'/>
<id>urn:sha1:be8090a3a09adb950557c2887c9a27c017ffd31d</id>
<content type='text'>
Agent-Logs-Url: https://github.com/vyos/vyos-documentation/sessions/cdefcaf2-e89e-4090-b39a-15b385b774df

Co-authored-by: andamasov &lt;12631358+andamasov@users.noreply.github.com&gt;
</content>
</entry>
<entry>
<title>ci(doc-linter): lint added + renamed files, not only modified</title>
<updated>2026-05-13T21:49:50+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-05-13T21:49:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=1ef5684729646ca3a24aff83ab8edd0aa57914c7'/>
<id>urn:sha1:1ef5684729646ca3a24aff83ab8edd0aa57914c7</id>
<content type='text'>
Previous workflow:

    env:
      FILES_MODIFIED: ${{ steps.file_changes.outputs.files_modified }}
    run: python scripts/doc-linter.py "$FILES_MODIFIED"

`trilom/file-changes-action`'s `files_modified` output is
modifications-only. A PR adding a new `.md`/`.rst` doc page passed
`files_added`, never `files_modified`, so a brand-new page with long
lines or real public IPs slipped past the linter entirely.

Workflow: also pass `files_added` and `files_renamed` as separate
positional args. Each output is a JSON array (action v1.2.4) and is
passed via env to avoid shell-quoting issues.

Linter: `main()` now accepts one OR multiple positional argv entries,
each a JSON array of paths. Arrays are merged and deduplicated before
linting. Single-arg invocations remain backward-compatible. Switched
from `ast.literal_eval` to `json.loads` — the action's outputs are
JSON, and `json.loads` is the right tool (and dodges
literal_eval-via-`eval`-substring linter warnings).

Test coverage:
- Two JSON arrays merge -&gt; single linter run on union.
- Empty-string argv entry skipped (no `files_renamed` in many PRs).
- Malformed JSON -&gt; falls back to walking DOCS_ROOT.
- No argv -&gt; walks DOCS_ROOT.
- Single-arg invocation -&gt; backward-compat preserved.

Tracked as item 7 of the rolling-side cleanup backlog from PR #2014 /
#2019 / #2020 reviews.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
<entry>
<title>ci(doc-linter): exclude docs/_rst_legacy/ and docs/_build/ from lint scope</title>
<updated>2026-05-13T21:48:16+00:00</updated>
<author>
<name>Yuriy Andamasov</name>
<email>yuriy@vyos.io</email>
</author>
<published>2026-05-13T21:48:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.amelek.net/vyos/vyos-documentation.git/commit/?id=379ed4757b62a7c1df965a59bc4f1fd0cef2d3e8'/>
<id>urn:sha1:379ed4757b62a7c1df965a59bc4f1fd0cef2d3e8</id>
<content type='text'>
`is_docs_path()` returned True for any path under `docs/`, including
the archived RST shadows under `docs/_rst_legacy/` and the build
output under `docs/_build/`. Sphinx excludes both from the build
(per `docs/conf.py`'s exclude_patterns) and AGENTS marks
`_rst_legacy` as reference-only. The linter shouldn't process either.

Add a `DOCS_EXCLUDED_SUBDIRS = ('_build', '_rst_legacy')` constant.
After confirming a path is under `docs/`, walk each excluded subtree
and reject the path if it's contained.

Also unify the auto-discover walk fallback to call `is_docs_path()`
for the filter — previously it had its own hand-rolled `"_build"
not in path` check that didn't handle `_rst_legacy` at all and would
have walked the entire legacy archive. Prune `dirs[:]` in-place at
each walk level so we don't descend into the excluded subtrees in
the first place — optimization on top of correctness. Reverted the
`_dirs` -&gt; `dirs` rename here because we now mutate it.

Test coverage: 10 hand-coded `is_docs_path()` cases — all pass:
- `docs/configuration/foo.md` -&gt; True
- `docs/_rst_legacy/foo.rst` -&gt; False (was True)
- `docs/_rst_legacy/subdir/rst-foo.rst` -&gt; False (was True)
- `docs/_build/html/index.html` -&gt; False (was True)
- `docs/_include/foo.txt` -&gt; True (live snippets stay in scope)
- `docs` -&gt; True
- `AGENTS.md`, `README.md`, `.github/copilot-instructions.md`,
  `scripts/doc-linter.py` -&gt; False (already correct)

Tracked as item 4 of the rolling-side cleanup backlog from PR #2014
/ #2019 / #2020 reviews.

🤖 Generated by [robots](https://vyos.io)
</content>
</entry>
</feed>
