| Age | Commit message (Collapse) | Author |
|
User direction: GitHub-hosted ubuntu-latest is not available in this
environment. The runner pool is Debian 12 self-hosted (web-runner-01,
web-runner-02). prepare must run there too.
Pushing back on Copilot's defense-in-depth finding (line 35) with
explicit threat-model reasoning documented in the workflow comment:
- prepare does not execute fork code. Only git fetch / git diff /
git show / file reads. No pip install, no npm install, no build,
no test. Adding any of these would require a deliberate code
change in this file that a reviewer must approve.
- No secrets are referenced in prepare. Even a presence-check would
leak the value into the runner environment.
- persist-credentials: false on the merge-ref checkout keeps the
default GITHUB_TOKEN out of fork-readable .git/config.
- The atos-actions/clean-self-hosted-runner step (`if: always()`)
wipes the workspace after every job regardless of exit state.
The split-job artifact still bridges the trust boundary to validate.
validate remains the only place where secrets are referenced.
The skip-notice `gh pr comment` step from a22df7d is preserved —
that's an independent discoverability improvement.
🤖 Generated by [robots](https://vyos.io)
|
|
Tag VyOS-Networks/vyos-docs-opus-reviewer/reviewer-v1.0.1 was
published after PR #13 merged on the reviewer side. v1.0.1 brings:
- Self-hosted runner workspace cleanup
- setup-uv (Debian 12 + Python 3.12 compat)
The branches.json map and Python source consumed via REVIEWER_REF
are unchanged from v1.0.0, so this bump is a no-op functionally
for the validate job — but it ensures the deployed workflow pulls
from a stable, post-cleanup-merge state of main rather than the
older v1.0.0 tag.
🤖 Generated by [robots](https://vyos.io)
|
|
If CONTEXT7_API_KEY is unset or empty (e.g. secret not yet configured),
emit a clear error message rather than letting curl fail with a generic
auth error. The `:-` guard is needed because `set -u` would otherwise
abort before the `-z` test when the variable is truly unset.
🤖 Generated by [robots](https://vyos.io)
|
|
Two more Copilot findings on b0fdd07:
1. line 35 — defense in depth: prepare on self-hosted is risky.
Even though the prepare job doesn't execute fork code (it only does
git diff / git show / file reads — never pip install, npm install,
build, or tests), Copilot's right that running fork content on a
self-hosted runner with internal-network access is the wrong
default. A future maintainer who innocently adds a "run linter"
step to prepare could turn it into an attack vector against the
VyOS internal network or a persistence mechanism on the host.
Moved prepare to runs-on: ubuntu-latest. GitHub-hosted runners are
ephemeral, isolated, and have no path to internal services. The
trusted validate job stays on [self-hosted, web]; the split-job
artifact bridges the trust boundary as before.
Side benefit: removes the runner-side dependency on jq/gh/git
for the prepare job (those are pre-installed on ubuntu-latest).
2. line 149 — skip-notice discoverability.
When secrets are missing the workflow only emits ::notice:: in
the run logs. Contributors checking the PR timeline have no
reason to click through to the run page. Added a new step that
posts an actual PR comment via gh pr comment when skip=true,
running with GH_TOKEN: ${{ github.token }} (the validate job
already has pull-requests: write).
The ::notice:: annotation is preserved alongside.
🤖 Generated by [robots](https://vyos.io)
|
|
CR finally got credits and posted three substantive findings on b0fdd07.
1. CRITICAL — line 281, model: input is silently ignored.
anthropics/claude-code-action@v1 removed the top-level `model`
input; the migration guide says model selection now travels via
`claude_args: --model <name>`. With the old form, the action used
its DEFAULT model on every run instead of the pinned claude-opus-4-7,
defeating the version pin entirely. CR even ran a web query and
actionlint to verify (actionlint output: "input 'model' is not
defined in action 'anthropics/claude-code-action@v1'"). Moved
--model claude-opus-4-7 into claude_args.
2. MAJOR — line 135, secrets template-expanded into shell text.
`[ -z "${{ secrets.VYOS_APP_ID }}" ]` lets GH Actions do
${{ ... }} expansion BEFORE bash parses the script. A secret
containing a single quote, backtick, or $ would either break the
test syntactically or be evaluated by the shell. The same hygiene
that justifies the prepare/validate split applies here. Moved
the three secrets to an env: mapping; the script now reads
"$VYOS_APP_ID" etc., handed to bash as already-quoted env vars.
3. NIT — line 7, concurrency group brittle outside PR events.
`github.event.pull_request.number` is empty on workflow_dispatch
or schedule; the group would collapse to "ai-validation-" and
unrelated runs cancel each other. Defensive fix: fallback to
`github.ref`. Today the workflow only fires on
pull_request_target so this is purely future-proofing.
Same changes being synced to canonical scripts/ai-validation.yml
in vyos-docs-opus-reviewer PR #13.
🤖 Generated by [robots](https://vyos.io)
|
|
Refreshes Context7's index of the VyOS documentation library on
completion of 'Update version tags', mapping rolling/circinus/sagitta to
Context7 variants rolling/1.5/1.4 respectively.
Triggered via workflow_run because GITHUB_TOKEN-driven tag pushes from
update-version-tags.yml do not fan out to downstream workflows.
workflow_dispatch added for ad-hoc and bootstrap refreshes.
Spec: ~/.claude/specs/2026-05-10-context7-github-actions-integration-design.md
🤖 Generated by [robots](https://vyos.io)
|
|
Copilot finding on .github/workflows/ai-validation.yml:86:
The bundling loop currently *skips* non-regular tree entries
(symlinks mode 120000, submodules 160000) with a `::warning::` and
continues. A PR that converts a regular docs/**/*.md into a symlink
effectively bypasses both Pass 1 (no file copied into _changed_md/)
and Pass 2 (LLM Read/Glob/Grep sees no content) — reducing
validation coverage on exactly the kind of change that warrants
closer review.
Replaced the `continue` with `exit 1` on non-regular mode. The error
message instructs the PR author to convert the file back to a regular
.md (or get explicit maintainer waiver). Maintainers can still land
non-regular doc entries by adjusting the workflow, but the decision
becomes visible rather than silent.
Combined with the symlink-exfil mitigation (commit 1ea164ff): we no
longer copy symlink target content into the artifact AND we no longer
silently skip the change. Either it's a regular file we can validate,
or the workflow fails loudly.
Same change being applied to the canonical reference copy in
VyOS-Networks/vyos-docs-opus-reviewer PR #13.
Suppressed-by-Copilot finding (line 110, id-token: write):
Same pushback as previous rounds. claude-code-action@v1 uses OIDC
internally (verified via this repo's commit b18a399c). Keeping.
🤖 Generated by [robots](https://vyos.io)
|
|
Two new findings on PR #1947:
1. Copilot — line 59, mkdir collision after cancellation:
`mkdir _changed_md` fails with EEXIST if the directory was left
behind by a previous run that concurrency.cancel-in-progress
killed before the post-job cleanup step could execute. On a
busy PR with rapid synchronize events this is a real
non-determinism. Replaced with `rm -rf _changed_md && mkdir -p`
so the bundling step is idempotent.
2. CodeRabbit — Major, scripts/ai-validation.yml:244 (mirrored
here on the deployed copy):
`uv pip install "git+https://x-access-token:${TOKEN}@..."` puts
the App token in process argv. On a self-hosted runner anyone
able to read /proc/<pid>/cmdline (any user with the same UID,
any root tool, any LSM audit log) sees the secret while uv/git
is running. This undercuts the persist-credentials:false
hardening on the surrounding checkouts.
Replaced the install with a two-step checkout + local-path
install:
- actions/checkout@v6 with persist-credentials:false fetches
the reviewer source into ./reviewer-src using the App token
as a transient http extraheader (not argv).
- `uv pip install ./reviewer-src` then installs from the local
path — no token anywhere on the command line.
Net trust boundary: same security posture as the existing
sparse-checkout of branches.json (line 100-110); no new attack
surface.
🤖 Generated by [robots](https://vyos.io)
|
|
Mirrors VyOS-Networks/vyos-docs-opus-reviewer PR #13 commit 116a4bc.
Adds workflow-level env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
GitHub's documented escape hatch from the Node 20 deprecation notice;
forces every JavaScript action in the workflow to run on Node 24
without per-action version churn (covers upload-artifact@v4,
download-artifact@v4, etc.).
Bumps actions/create-github-app-token to SHA-pinned v2.2.2
(fee1f7d63c2ff003460e3d139729b119787bc349).
🤖 Generated by [robots](https://vyos.io)
|
|
actions/setup-python's prebuilt manifest at actions/python-versions
ships 3.12 for Ubuntu but not for Debian 12. The vyos web- runner
pool runs Debian 12, so the previous setup-python@v6 step failed
with: "##[error]The version '3.12' with architecture 'x64' was not
found for Debian 12."
Replacing the step with astral-sh/setup-uv@v8.1.0 (SHA-pinned). uv
provisions Python from Astral's cross-platform standalone builds,
which work on Debian. Setting `python-version: '3.12'` triggers
`uv python install`; `activate-environment: true` creates a venv
at $GITHUB_WORKSPACE/.venv and prepends its bin/ to PATH so the
`vyos-doc-review` CLI installed by uv pip install is callable
without further configuration.
Replaces `pip install` with `uv pip install` to use the venv that
setup-uv activated.
Same change being applied to .github/workflows/rebuild-reference.yml
and .github/workflows/full-scan.yml in vyos-docs-opus-reviewer PR #13
(canonical scripts/ai-validation.yml will re-sync from this file).
🤖 Generated by [robots](https://vyos.io)
|
|
Copilot finding on .github/workflows/ai-validation.yml:64 — defense
in depth:
Even though git's tree machinery generally rejects `..` segments
and absolute paths at commit time, treat fork-controlled diff
input as untrusted. A path like `docs/../../outside.md` would
let `git show HEAD:<path>` write to `_changed_md/../../outside.md`,
which resolves to a sibling of `_changed_md/` — escaping the
artifact directory and writing into the runner workspace.
Mitigation: validate each path before any mkdir/redirect. Reject:
- absolute paths (`/foo`)
- interior `..` segments (`foo/../bar`)
- leading `..` (`../foo`)
- trailing `..` (`foo/..`)
- bare `..`
Combined with the existing symlink/submodule mode check, the
prepare job now refuses to bundle any tree entry whose path or
type could escape the artifact boundary.
Suppressed-by-Copilot finding (line 68, id-token: write):
Same pushback as previous rounds. claude-code-action@v1 uses OIDC
internally (verified via vyos/vyos-documentation commit b18a399c).
Keeping as-is.
🤖 Generated by [robots](https://vyos.io)
|
|
Self-hosted runners don't auto-clean their workspace between jobs, so
PR fork content + cloned vyos-1x source + downloaded reference DB +
the App-token-bearing pip install cache all linger on the runner host
until the next job overwrites them. That's a leak surface for both
secret material and disk space.
Adds atos-actions/clean-self-hosted-runner@v1.4.34 (SHA-pinned) as the
LAST step in both prepare and validate jobs, gated with `if: always()`
so it runs after success, failure, or cancellation.
The action is from atos-actions, a verified GitHub Marketplace partner.
Composite action — no Node 20/24 deprecation. Logic is auditable
(rm -rf ./* ./.[!.]*). Has a DISABLE_RUNNER_CLEANUP env var kill-switch
for debugging if a job needs to leave residual state for inspection.
🤖 Generated by [robots](https://vyos.io)
|
|
Copilot finding on .github/workflows/ai-validation.yml:50 — high severity:
A fork PR can commit a symlink at docs/x.md (mode 120000) pointing to an
absolute path on the self-hosted runner. The previous `xargs cp` would
follow the symlink and copy the *target's* content (/etc/passwd, runner
secrets, ssh keys, the App's PEM if accessible) into the pr-input
artifact. The validate job downloads that artifact and exposes it to the
Pass 2 claude-code-action step (which has Read,Glob,Grep tools), so a
prompt-injection attempt could exfiltrate runner state via inline review
comments.
Mitigation: replace the cp loop with `git show HEAD:<path>` extraction.
This pulls bytes directly from the merge commit's tree blob. For a symlink
entry, git show returns the textual target path (a string like
"/etc/passwd"), NOT the target's filesystem content. The artifact's
worst-case is a text file containing a path string, which has no
exfiltration value.
Implementation:
- Read NUL-delimited paths from changed-md.z (preserves filename safety).
- For each path, check ls-tree mode: 100644/100755 = normal file, accept;
120000 = symlink, skip with ::warning::; 160000 = submodule, skip;
anything else, skip.
- Use `git show HEAD:<path>` to write blob content into _changed_md/.
- All variable expansions are within double-quotes (no word-splitting,
no glob, no recursive parse of $() in the substituted value).
The xargs cp option-injection defense (`-- ` end-of-options) is no longer
needed since cp is gone. The --diff-filter=ACMRT and persist-credentials
fixes from edd903d remain.
Suppressed-by-Copilot finding (line 68, id-token: write):
Same as previous round — pushback. claude-code-action@v1 uses OIDC
internally (verified via vyos/vyos-documentation commit b18a399c, where
the permission was removed and immediately restored after the action
broke). Keeping as-is.
🤖 Generated by [robots](https://vyos.io)
|
|
Three Copilot findings on the AI Validation workflow:
1. line 46 (cp loop on deleted files):
`git diff --name-only` with no filter includes Deleted entries, so
the subsequent `xargs -0 ... cp --parents` would fail when a PR
deletes (or renames) a `.md`/`.rst` file. Added
`--diff-filter=ACMRT` to both name-only diffs so deletions are
excluded from the cp source list. Deletions still appear in
diff-md.patch (which uses the unfiltered full diff) so Pass 1's
--pr-diff input still sees them via the patch hunk.
2. line 103 (reviewer sparse-checkout):
The App token was being persisted into reviewer/.git/config as
an http extraheader by default. The Pass 2 claude-code-action
step has Read/Glob/Grep allowed, so a prompt-injection attempt
could exfiltrate the token from the workspace. Added
`persist-credentials: false`. The sparse-checkout fetched only
branches.json which is a one-shot read, no further git ops
needed in this job.
3. line 127 (vyos-1x checkout):
Same persist-credentials concern. The vyos-1x clone is read by
claude-code-action for Pass 2 source inspection — exactly the
step where filesystem read tools are exposed to LLM-driven
shell behavior. Added `persist-credentials: false`. The vyos-1x
tree is only read after this checkout (`Read,Glob,Grep` over
`.vyos-1x/`); we don't run any git commands against it that
would need the token.
Suppressed-by-Copilot finding (line 64, id-token: write):
Pushback. claude-code-action@v1 uses OIDC internally (verified by
commit b18a399c on the previously-deployed workflow). Removing
this permission breaks the action. Keeping as-is.
🤖 Generated by [robots](https://vyos.io)
|
|
Rewrites .github/workflows/ai-validation.yml to align with the docs
current→rolling rename and the RST→MyST migration. The body is a
byte-for-byte copy of the canonical reference at
VyOS-Networks/vyos-docs-opus-reviewer/scripts/ai-validation.yml at
tag reviewer-v1.0.0 (header stripped on copy).
Key changes vs the previously deployed (and currently disabled)
workflow:
- Trigger pull_request → pull_request_target (required for fork PRs
to access secrets) with a split prepare/validate job pattern that
preserves the trust boundary.
- prepare job: NO secrets referenced; checks out the PR merge ref
with persist-credentials:false; emits NUL-delimited diffs +
bundles changed .md files into _changed_md/ via xargs cp.
- validate job: secrets-availability check; sparse-checkout of
branches.json from the reviewer repo (pinned via REVIEWER_REF
env var, default reviewer-v1.0.0); fail-fast resolution of
docs branch → vyos-1x branch via jq lookup; mapped vyos-1x
checkout; reference-DB download (best-effort); fail-closed
gate when MyST files are in the diff but the DB is missing;
Pass 1 runs from inside _changed_md/ so diff-relative paths
resolve; Pass 2 via claude-code-action with hardened prompt
(untrusted-content ringfence, narrow tool allowlist).
- Concurrency: PR-scoped concurrency cancels superseded runs.
- Runners: [self-hosted, web] (org-level VyOS runner pool).
- Action versions bumped for Node-24 compat:
- actions/create-github-app-token@v2
- actions/setup-python@v6
- robinraju/release-downloader@<v1.13 SHA-pin>
Required secrets in vyos/vyos-documentation:
ANTHROPIC_API_KEY, VYOS_APP_ID, VYOS_APP_PRIVATE_KEY
Implements:
- VyOS-Networks/vyos-docs-opus-reviewer
docs/superpowers/specs/2026-05-10-myst-parser-and-workflow-fix-design.md
Workflow remains disabled_manually while this PR is in review.
After merge, re-enable via:
gh api repos/vyos/vyos-documentation/actions/workflows/259251949/enable -X PUT
🤖 Generated by [robots](https://vyos.io)
|
|
The caller workflow referenced `vyos/.github/.github/workflows/check-open-prs-conflict.yml@current`,
but that file does not exist in `vyos/.github`. The workflow was renamed
to `check-pr-conflict.yml` (without "open") at some point after the
caller was added in 86a282ec (#1638, 2025-05-26). Result: every push
to a watched branch since at least 2026-05-07 has produced a
"workflow file issue" failure. Verified via `gh api repos/vyos/.github/contents/.github/workflows`.
The called workflow is `workflow_call`-callable with no inputs, so this
is a one-line ref fix. No behavior change to the caller's trigger list.
🤖 Generated by [robots](https://vyos.io)
|
|
Cosmetic only — fixes "Github" → "GitHub" in three places that were left
behind by the rename cleanup in #1938 (which fixed only the lines it
already touched, to keep scope tight).
- submodules.yml update_sagitta job: commit-message + title
- submodules.yml update_equuleus job: commit-message + title
- update-translations.yml: commit-message + title
These strings appear in the titles/messages of bot-created PRs only;
no functional impact.
🤖 Generated by [robots](https://vyos.io)
|
|
The reusable lint-doc workflow at vyos/.github checks out vyos/.github
on the consumer's PR base.ref to source doc-linter.py — designed for
per-release-train linter rules. With this repo's default renamed
current → rolling and vyos/.github still on current, the checkout
errors with "fetch +refs/heads/rolling*: exit code 1".
Rather than chase branch parity across repos, move the linter where it
belongs: doc-linter.py is doc-specific and only consumed here. Inlining
removes the cross-repo coupling permanently and unblocks any future
branch renames in this repo without touching vyos/.github.
- scripts/doc-linter.py: copied byte-for-byte from
vyos/.github@current:.github/doc-linter.py (sha
3dc7c2fc16242e62b0ea7107f767577e999ca417 — identical across all four
release-train branches in vyos/.github, so no behavioral change).
- .github/workflows/lint-doc.yml: replaces `uses:
vyos/.github/.github/workflows/lint-doc.yml@current` with the inlined
steps. Same actions (bullfrogsec/bullfrog, trilom/file-changes-action,
setup-python) and the same final invocation, just sourcing the script
from this repo. Adds explicit minimal permissions (contents/pull-requests
read) and passes the file list via env var to follow the workflow-
injection guidance.
Follow-up: vyos/.github still hosts the now-orphaned doc-linter.py and
its reusable workflow — separate cleanup PR can delete them once any
other consumers migrate (none observed today; this repo was the only
caller).
🤖 Generated by [robots](https://vyos.io)
|
|
In response to Copilot review on #1938 — the commit-message and title
strings I touched while renaming current→rolling also had a "Github"
typo. Same lines are already in this PR's diff, so corrected here.
The same typo exists in update_sagitta and update_equuleus jobs and in
update-translations.yml, but those lines are not in this PR's diff;
folding them in would expand scope beyond the rename cleanup. They
warrant a separate consistency PR.
🤖 Generated by [robots](https://vyos.io)
|
|
Cleanup PR following the current→rolling default-branch rename. Drops
the now-stale current branch from workflow triggers, flips remaining
defaults, and updates documentation/templates.
Workflows:
- pr-mirror-repo-sync.yml: branches narrowed to [rolling]; workflow_dispatch
default and choice list now rolling-only; sync_branch fallback flipped
from 'current' to 'rolling'.
- check-open-prs-conflict.yml: dropped current from push.branches.
- update-version-tags.yml: dropped current from push.branches and from
the case statement (now bare 'rolling) TAG=rolling').
- submodules.yml: renamed update_current job, branch
update-dependencies-current, and the related commit/title strings to
rolling.
- update-translations.yml: PR branch update-translations-current renamed
to update-translations-rolling.
- ai-validation.yml: prompt example updated.
Docs/templates:
- docs/conf.py: READTHEDOCS_GIT_IDENTIFIER fallback flipped to 'rolling';
comment block updated to describe the rolling branch (the user-facing
"(current)" suffix is release-channel terminology and remains).
- README.md: branching-scheme section now describes rolling as the
default branch, with a note about the rename date.
- .github/PULL_REQUEST_TEMPLATE.md: CONTRIBUTING link points at
blob/rolling.
External @current refs to vyos/.github and vyos/vyos-cla-signatures are
left untouched — they reference those repos' default branches and are
unaffected by this repo's rename.
🤖 Generated by [robots](https://vyos.io)
|
|
Agent-Logs-Url: https://github.com/vyos/vyos-documentation/sessions/13538647-bbfb-438c-bec8-30f9ee0aa923
Co-authored-by: andamasov <12631358+andamasov@users.noreply.github.com>
|
|
Defensive pre-flight for the planned rename of the default branch from
current to rolling. Adds rolling alongside current to push/pull-request
triggers and to the manual dispatch choice list so workflows continue to
fire across the rename atomically.
Workflow input defaults remain on current — they will be flipped, and
current dropped, in the post-rename cleanup PR. Cosmetic naming
(submodules.yml job/branch names, conf.py fallback, README, PR template
link) is intentionally deferred to that cleanup PR to avoid documenting
a branch that does not yet exist.
🤖 Generated by [robots](https://vyos.io)
|
|
- Use ${{ github.token }} for GH_TOKEN to match the convention in
ai-validation.yml.
- Existence check now uses the singular `git/ref/tags/$TAG` endpoint,
which 404s when the tag is missing. The plural `git/refs/tags/$TAG`
returns 200 with an array even when no exact match exists, which
would route every run through the PATCH path and fail with 404 on
any tag that has been deleted.
🤖 Generated by [robots](https://vyos.io)
|
|
Agent-Logs-Url: https://github.com/vyos/vyos-documentation/sessions/49d35e98-ac39-4556-824a-e129c23f768e
Co-authored-by: andamasov <12631358+andamasov@users.noreply.github.com>
|
|
Maps branches to floating version tags so RTD can build canonical
versioned URLs from a single ref name regardless of branch renames:
- current -> rolling
- circinus -> 1.5
- sagitta -> 1.4
The workflow force-moves the matching tag to the pushed SHA on every
push to one of the three branches. Initial seed tags were created
manually; subsequent updates are automatic.
🤖 Generated by [robots](https://vyos.io)
|
|
|
|
* ci: add AI documentation validation workflow
* fix: address Copilot review — fork PR safety, least-privilege, DB fallback
- Add secrets availability check; skip workflow gracefully for fork PRs
where secrets are unavailable (instead of hard-failing)
- Remove unused id-token: write permission (no OIDC in this workflow)
- Add continue-on-error on reference DB download; skip Pass 1 with
warning when artifact is missing for the target branch
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore id-token: write — required by claude-code-action OIDC
claude-code-action@v1 uses OIDC internally to authenticate. The
Copilot suggestion to remove it was incorrect.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: include ANTHROPIC_API_KEY in secrets check, update prompt for DB skip
- Add ANTHROPIC_API_KEY to the secrets availability gate so the
workflow skips cleanly when any required secret is missing
- Update Claude prompt to handle the case where reference DB download
failed and Pass 1 was skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
|
|
|
|
Co-authored-by: kumvijaya <kuvmijaya@gmail.com>
|
|
|
|
|
|
|
|
|
|
|
|
add PAT secret for the PR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|