From 8dbf8b052075b0fb7af38b7b505260e4f673a998 Mon Sep 17 00:00:00 2001 From: Yuriy Andamasov Date: Sun, 10 May 2026 15:33:09 +0300 Subject: ci/docs: drop current branch references after rename to rolling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/ai-validation.yml | 2 +- .github/workflows/check-open-prs-conflict.yml | 1 - .github/workflows/pr-mirror-repo-sync.yml | 11 +++++------ .github/workflows/submodules.yml | 8 ++++---- .github/workflows/update-translations.yml | 2 +- .github/workflows/update-version-tags.yml | 3 +-- README.md | 6 +++--- docs/conf.py | 10 ++++++---- 9 files changed, 22 insertions(+), 23 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: -- [ ] 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/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..bb93b93f 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 = { -- cgit v1.2.3 From 4a1d027c39a0816fd0690ee612987f066f5d3651 Mon Sep 17 00:00:00 2001 From: Yuriy Andamasov Date: Sun, 10 May 2026 15:40:14 +0300 Subject: ci: fix Github→GitHub typo in submodules.yml update_rolling job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .github/workflows/submodules.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submodules.yml b/.github/workflows/submodules.yml index bb93b93f..16ba1ab5 100644 --- a/.github/workflows/submodules.yml +++ b/.github/workflows/submodules.yml @@ -31,8 +31,8 @@ jobs: uses: peter-evans/create-pull-request@v6 with: token: ${{ secrets.PR_ACTION_DOCUMENTATION_SUBMODULE_UPDATE }} - commit-message: "Github: update rolling branch" - title: "Github: update rolling branch" + commit-message: "GitHub: update rolling branch" + title: "GitHub: update rolling branch" body: | Autoupdate vyos-1x submodule update releasenotes -- cgit v1.2.3 From 1bf386e2ce6e4039f9adbef868ef54758e4204c0 Mon Sep 17 00:00:00 2001 From: Yuriy Andamasov Date: Sun, 10 May 2026 15:42:44 +0300 Subject: ci: inline doc lint workflow, drop vyos/.github cross-repo dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .github/workflows/lint-doc.yml | 34 ++++++-- scripts/doc-linter.py | 177 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 scripts/doc-linter.py 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/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) -- cgit v1.2.3