summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuriy Andamasov <yuriy@vyos.io>2026-05-10 15:51:43 +0300
committerGitHub <noreply@github.com>2026-05-10 15:51:43 +0300
commit739043c260645d507adb756ca27e952bdfbad858 (patch)
tree1d805b4c748e12c084e63356015016ee513008f8
parent1a1aacfe67699ab468fbb5672d9610af80dabc76 (diff)
parent1bf386e2ce6e4039f9adbef868ef54758e4204c0 (diff)
downloadvyos-documentation-739043c260645d507adb756ca27e952bdfbad858.tar.gz
vyos-documentation-739043c260645d507adb756ca27e952bdfbad858.zip
Merge pull request #1938 from vyos/yuriy/cleanup-rolling-references
ci/docs: drop current branch references after rename to rolling
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md2
-rw-r--r--.github/workflows/ai-validation.yml2
-rw-r--r--.github/workflows/check-open-prs-conflict.yml1
-rw-r--r--.github/workflows/lint-doc.yml34
-rw-r--r--.github/workflows/pr-mirror-repo-sync.yml11
-rw-r--r--.github/workflows/submodules.yml8
-rw-r--r--.github/workflows/update-translations.yml2
-rw-r--r--.github/workflows/update-version-tags.yml3
-rw-r--r--README.md6
-rw-r--r--docs/conf.py10
-rw-r--r--scripts/doc-linter.py177
11 files changed, 228 insertions, 28 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 2c1dd640..61a1c45e 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -19,4 +19,4 @@
## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
-- [ ] I have read the [**CONTRIBUTING**](https://github.com/vyos/vyos-documentation/blob/current/CONTRIBUTING.md) document \ No newline at end of file
+- [ ] I have read the [**CONTRIBUTING**](https://github.com/vyos/vyos-documentation/blob/rolling/CONTRIBUTING.md) document \ No newline at end of file
diff --git a/.github/workflows/ai-validation.yml b/.github/workflows/ai-validation.yml
index a5d120e7..60964396 100644
--- a/.github/workflows/ai-validation.yml
+++ b/.github/workflows/ai-validation.yml
@@ -150,7 +150,7 @@ jobs:
IMPORTANT: This PR targets the **${{ steps.branch.outputs.target }}** branch.
The vyos-1x checkout matches this branch. Features may differ between branches
- (e.g., a command exists in `current` but not in `sagitta`). Only flag issues
+ (e.g., a command exists in `rolling` but not in `sagitta`). Only flag issues
relevant to this specific branch.
## Pass 1 Findings
diff --git a/.github/workflows/check-open-prs-conflict.yml b/.github/workflows/check-open-prs-conflict.yml
index 3aa9ce05..9667fd62 100644
--- a/.github/workflows/check-open-prs-conflict.yml
+++ b/.github/workflows/check-open-prs-conflict.yml
@@ -2,7 +2,6 @@ name: "Open PRs Conflicts checker"
on:
push:
branches:
- - current
- rolling
- sagitta
- circinus
diff --git a/.github/workflows/lint-doc.yml b/.github/workflows/lint-doc.yml
index b5ba4688..d7f25f38 100644
--- a/.github/workflows/lint-doc.yml
+++ b/.github/workflows/lint-doc.yml
@@ -2,9 +2,33 @@ name: Lint Doc
on:
pull_request:
+permissions:
+ contents: read
+ pull-requests: read
+
jobs:
- lint-doc:
- uses: vyos/.github/.github/workflows/lint-doc.yml@current
- secrets: inherit
-
-
+ doc-lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Bullfrog Secure Runner
+ continue-on-error: true
+ uses: bullfrogsec/bullfrog@v0.8.4
+ with:
+ egress-policy: audit
+
+ - name: Get File Changes
+ id: file_changes
+ uses: trilom/file-changes-action@v1.2.4
+
+ - name: Set up Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: '3.x'
+
+ - name: run doc linter
+ env:
+ FILES_MODIFIED: ${{ steps.file_changes.outputs.files_modified }}
+ run: python scripts/doc-linter.py "$FILES_MODIFIED"
diff --git a/.github/workflows/pr-mirror-repo-sync.yml b/.github/workflows/pr-mirror-repo-sync.yml
index 1f01bd02..5c944971 100644
--- a/.github/workflows/pr-mirror-repo-sync.yml
+++ b/.github/workflows/pr-mirror-repo-sync.yml
@@ -3,16 +3,15 @@ name: PR Mirror and Repo Sync
on:
pull_request_target:
types: [closed]
- branches: [current, rolling]
+ branches: [rolling]
workflow_dispatch:
inputs:
sync_branch:
description: 'Branch to mirror'
required: true
- default: 'current'
+ default: 'rolling'
type: choice
options:
- - current
- rolling
permissions:
@@ -28,9 +27,9 @@ jobs:
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request_target' && github.event.pull_request.merged == true)
)
- uses: vyos/.github/.github/workflows/pr-mirror-repo-sync.yml@current
- with:
- sync_branch: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.ref || github.event.inputs.sync_branch || 'current' }}
+ uses: vyos/.github/.github/workflows/pr-mirror-repo-sync.yml@current
+ with:
+ sync_branch: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.ref || github.event.inputs.sync_branch || 'rolling' }}
secrets:
PAT: ${{ secrets.PAT }}
REMOTE_OWNER: ${{ secrets.REMOTE_OWNER }}
diff --git a/.github/workflows/submodules.yml b/.github/workflows/submodules.yml
index 24b6c505..16ba1ab5 100644
--- a/.github/workflows/submodules.yml
+++ b/.github/workflows/submodules.yml
@@ -5,7 +5,7 @@ on:
# 06:00 UTC on Monday
- cron: '0 6 * * 1'
jobs:
- update_current:
+ update_rolling:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@@ -31,12 +31,12 @@ jobs:
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.PR_ACTION_DOCUMENTATION_SUBMODULE_UPDATE }}
- commit-message: "Github: update current branch"
- title: "Github: update current branch"
+ commit-message: "GitHub: update rolling branch"
+ title: "GitHub: update rolling branch"
body: |
Autoupdate vyos-1x submodule
update releasenotes
- branch: update-dependencies-current
+ branch: update-dependencies-rolling
delete-branch: true
update_sagitta:
diff --git a/.github/workflows/update-translations.yml b/.github/workflows/update-translations.yml
index 6ab53323..4b0bafa1 100644
--- a/.github/workflows/update-translations.yml
+++ b/.github/workflows/update-translations.yml
@@ -57,6 +57,6 @@ jobs:
title: "Github: update translations"
body: |
Generate, upload new and download translation files
- branch: update-translations-current
+ branch: update-translations-rolling
delete-branch: true
diff --git a/.github/workflows/update-version-tags.yml b/.github/workflows/update-version-tags.yml
index c7c372a3..7f179586 100644
--- a/.github/workflows/update-version-tags.yml
+++ b/.github/workflows/update-version-tags.yml
@@ -3,7 +3,6 @@ name: Update version tags
on:
push:
branches:
- - current
- rolling
- circinus
- sagitta
@@ -28,7 +27,7 @@ jobs:
run: |
set -euo pipefail
case "$BRANCH" in
- current|rolling) TAG=rolling ;;
+ rolling) TAG=rolling ;;
circinus) TAG=1.5 ;;
sagitta) TAG=1.4 ;;
*) echo "Unexpected branch: $BRANCH" >&2; exit 1 ;;
diff --git a/README.md b/README.md
index 46f0b20d..8f8bb674 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,10 @@ Our old wiki with documentation from the VyOS 1.1.x and early 1.2.0 era can stil
Our documentation repository follows the same branching scheme as the VyOS source itself.
We maintain one documentation branch per VyOS release.
-The default branch that contains the most recent VyOS documentation is called `current`
-and matches the latest VyOS rolling release.
+The default branch that contains the most recent VyOS documentation is called `rolling`
+(renamed from `current` on 2026-05-10) and matches the latest VyOS rolling release.
-All new documentation enhancements go to the `current` branch. If those changes
+All new documentation enhancements go to the `rolling` branch. If those changes
are beneficial for previous VyOS documentation versions they will be
cherry-picked to the appropriate branch(es).
diff --git a/docs/conf.py b/docs/conf.py
index 083482a8..ea3c5b61 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -29,12 +29,14 @@ author = u'VyOS maintainers and contributors'
# The short X.Y version (rolling — next major; bumped at branch cut)
version = u'rolling'
-# The full version, including alpha/beta/rc tags. The `current` branch
+# The full version, including alpha/beta/rc tags. The `rolling` branch
# is the rolling tip and serves at /en/rolling/ on RTD; the literal
# below is exposed in the page footer ("v: rolling (current)") and is
# interpolated into _templates/llms.txt.j2 ("This documentation covers
# {{ release }}."). Pin this to a value that names what the rolling
-# docs actually serve, not a stale LTS codename.
+# docs actually serve, not a stale LTS codename. The "(current)" suffix
+# is release-channel terminology for the current rolling release; it is
+# unrelated to the former branch name.
release = u'rolling (current)'
# -- General configuration ---------------------------------------------------
@@ -136,9 +138,9 @@ html_baseurl = 'https://docs.vyos.io/en/rolling/'
_rtd_version_type = os.environ.get('READTHEDOCS_VERSION_TYPE', '')
_github_version = (
- os.environ.get('READTHEDOCS_GIT_COMMIT_HASH', 'current')
+ os.environ.get('READTHEDOCS_GIT_COMMIT_HASH', 'rolling')
if _rtd_version_type == 'external'
- else os.environ.get('READTHEDOCS_GIT_IDENTIFIER', 'current')
+ else os.environ.get('READTHEDOCS_GIT_IDENTIFIER', 'rolling')
)
html_context = {
diff --git a/scripts/doc-linter.py b/scripts/doc-linter.py
new file mode 100644
index 00000000..3dc7c2fc
--- /dev/null
+++ b/scripts/doc-linter.py
@@ -0,0 +1,177 @@
+import os
+import re
+import ipaddress
+import sys
+import ast
+
+IPV4SEG = r'(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])'
+IPV4ADDR = r'\b(?:(?:' + IPV4SEG + r'\.){3,3}' + IPV4SEG + r')\b'
+IPV6SEG = r'(?:(?:[0-9a-fA-F]){1,4})'
+IPV6GROUPS = (
+ r'(?:' + IPV6SEG + r':){7,7}' + IPV6SEG, # 1:2:3:4:5:6:7:8
+ r'(?:\s' + IPV6SEG + r':){1,7}:', # 1:: 1:2:3:4:5:6:7::
+ r'(?:' + IPV6SEG + r':){1,6}:' + IPV6SEG, # 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
+ r'(?:' + IPV6SEG + r':){1,5}(?::' + IPV6SEG + r'){1,2}', # 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
+ r'(?:' + IPV6SEG + r':){1,4}(?::' + IPV6SEG + r'){1,3}', # 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
+ r'(?:' + IPV6SEG + r':){1,3}(?::' + IPV6SEG + r'){1,4}', # 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
+ r'(?:' + IPV6SEG + r':){1,2}(?::' + IPV6SEG + r'){1,5}', # 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
+ IPV6SEG + r':(?:(?::' + IPV6SEG + r'){1,6})', # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
+ r':(?:(?::' + IPV6SEG + r'){1,7}|:)', # ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
+ r'fe80:(?::' + IPV6SEG + r'){0,4}%[0-9a-zA-Z]{1,}', # fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index)
+ r'::(?:ffff(?::0{1,4}){0,1}:){0,1}[^\s:]' + IPV4ADDR, # ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
+ r'(?:' + IPV6SEG + r':){1,4}:[^\s:]' + IPV4ADDR, # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
+)
+IPV6ADDR = '|'.join(['(?:{})'.format(g) for g in IPV6GROUPS[::-1]]) # Reverse rows for greedy match
+
+MAC = r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
+
+NUMBER = r"([\s']\d+[\s'])"
+
+
+def lint_mac(cnt, line):
+ mac = re.search(MAC, line, re.I)
+ if mac is not None:
+ mac = mac.group()
+ u_mac = re.search(r'((00)[:-](53)([:-][0-9A-F]{2}){4})', mac, re.I)
+ m_mac = re.search(r'((90)[:-](10)([:-][0-9A-F]{2}){4})', mac, re.I)
+ if u_mac is None and m_mac is None:
+ return (f"Use MAC reserved for Documentation (RFC7042): {mac}", cnt, 'error')
+
+
+def lint_ipv4(cnt, line):
+ ip = re.search(IPV4ADDR, line, re.I)
+ if ip is not None:
+ ip = ipaddress.ip_address(ip.group().strip(' '))
+ # https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_private
+ if ip.is_private:
+ return None
+ if ip.is_multicast:
+ return None
+ if ip.is_global is False:
+ return None
+ return (f"Use IPv4 reserved for Documentation (RFC 5737) or private Space: {ip}", cnt, 'error')
+
+
+def lint_ipv6(cnt, line):
+ ip = re.search(IPV6ADDR, line, re.I)
+ if ip is not None:
+ ip = ipaddress.ip_address(ip.group().strip(' '))
+ if ip.is_private:
+ return None
+ if ip.is_multicast:
+ return None
+ if ip.is_global is False:
+ return None
+ return (f"Use IPv6 reserved for Documentation (RFC 3849) or private Space: {ip}", cnt, 'error')
+
+
+def lint_AS(cnt, line):
+ number = re.search(NUMBER, line, re.I)
+ if number:
+ pass
+ # find a way to detect AS numbers
+
+
+def lint_linelen(cnt, line):
+ line = line.rstrip()
+ if len(line) > 80:
+ return (f"Line too long: len={len(line)}", cnt, 'warning')
+
+def handle_file_action(filepath):
+ errors = []
+ try:
+ with open(filepath) as fp:
+ line = fp.readline()
+ cnt = 1
+ test_line_lenght = True
+ start_vyoslinter = True
+ indentation = 0
+ while line:
+ # search for ignore linter comments in lines
+ if ".. stop_vyoslinter" in line:
+ start_vyoslinter = False
+ if ".. start_vyoslinter" in line:
+ start_vyoslinter = True
+ if start_vyoslinter:
+ # ignore every '.. code-block::' for line lenght
+ # rst code-block have its own style in html the format in rst
+ # and the build page must be the same
+ if test_line_lenght is False:
+ if len(line) > indentation:
+ #print(f"'{line}'")
+ #print(indentation)
+ if line[indentation].isspace() is False:
+ test_line_lenght = True
+
+ if ".. code-block::" in line:
+ test_line_lenght = False
+ indentation = 0
+ for i in line:
+ if i.isspace():
+ indentation = indentation + 1
+ else:
+ break
+
+ err_mac = lint_mac(cnt, line.strip())
+ # disable mac detection for the moment, too many false positives
+ err_mac = None
+ err_ip4 = lint_ipv4(cnt, line.strip())
+ err_ip6 = lint_ipv6(cnt, line.strip())
+ if test_line_lenght:
+ err_len = lint_linelen(cnt, line)
+ else:
+ err_len = None
+ if err_mac:
+ errors.append(err_mac)
+ if err_ip4:
+ errors.append(err_ip4)
+ if err_ip6:
+ errors.append(err_ip6)
+ if err_len:
+ errors.append(err_len)
+
+ line = fp.readline()
+ cnt += 1
+
+ # ensure linter was not stop on top and forgot to tun on again
+ if start_vyoslinter == False:
+ errors.append((f"Don't forgett to turn linter back on", cnt, 'error'))
+ finally:
+ fp.close()
+
+ if len(errors) > 0:
+ '''
+ "::{$type} file={$filename},line={$line},col=$column::{$log}"
+ '''
+ print(f"File: {filepath}")
+ for error in errors:
+ print(f"::{error[2]} file={filepath},line={error[1]}::{error[0]}")
+ print('')
+ return False
+
+
+def main():
+ bool_error = True
+ print('start')
+ try:
+ files = ast.literal_eval(sys.argv[1])
+ for file in files:
+ if file[-4:] in [".rst", ".txt"] and "_build" not in file:
+ if handle_file_action(file) is False:
+ bool_error = False
+ except Exception as e:
+ for root, dirs, files in os.walk("docs"):
+ path = root.split(os.sep)
+ for file in files:
+ if file[-4:] in [".rst", ".txt"] and "_build" not in path:
+ fpath = '/'.join(path)
+ filepath = f"{fpath}/{file}"
+ if handle_file_action(filepath) is False:
+ bool_error = False
+
+ return bool_error
+
+
+if __name__ == "__main__":
+ if main() == False:
+ exit(1)