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/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 +-- 6 files changed, 12 insertions(+), 15 deletions(-) (limited to '.github/workflows') 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 ;; -- 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(-) (limited to '.github/workflows') 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 (limited to '.github/workflows') 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