summaryrefslogtreecommitdiff
path: root/.github
diff options
context:
space:
mode:
authoromnom62 <75066712+omnom62@users.noreply.github.com>2026-07-28 05:09:47 +1000
committerGitHub <noreply@github.com>2026-07-28 05:09:47 +1000
commitb0243027a73583eed7014ae924fbc79bb55577b5 (patch)
tree822de31d5246309612f50c6a1c8b6f5717dba8eb /.github
parent2e2a0f2da3df1a3197bef3c19d3e7deecf869759 (diff)
parent17041b6f6953b993762854a67953fb35176b46e7 (diff)
downloadvyos.vyos-b0243027a73583eed7014ae924fbc79bb55577b5.tar.gz
vyos.vyos-b0243027a73583eed7014ae924fbc79bb55577b5.zip
Merge branch 'main' into fix/black-formatting
Diffstat (limited to '.github')
l---------.github/copilot-instructions.md1
-rw-r--r--.github/instructions/modules.instructions.md37
-rw-r--r--.github/instructions/tests.instructions.md114
-rw-r--r--.github/mergify.yml34
-rw-r--r--.github/workflows/ah_token_refresh.yml2
-rw-r--r--.github/workflows/cla-check.yml2
-rw-r--r--.github/workflows/codecoverage.yml2
-rw-r--r--.github/workflows/codeql.yml30
8 files changed, 219 insertions, 3 deletions
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 120000
index 00000000..be77ac83
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1 @@
+../AGENTS.md \ No newline at end of file
diff --git a/.github/instructions/modules.instructions.md b/.github/instructions/modules.instructions.md
new file mode 100644
index 00000000..d7782e1e
--- /dev/null
+++ b/.github/instructions/modules.instructions.md
@@ -0,0 +1,37 @@
+---
+applyTo: "plugins/**,meta/runtime.yml"
+---
+
+# Plugin conventions
+
+## Module option descriptions
+
+- Must be complete English sentences ending with a period.
+- No grammar errors. Common mistake: "the number hops" should be "the number of hops".
+- Deprecated options must include `removed_in_version` and `removed_from_collection` fields.
+- Do not add new options with `deprecated: true` — remove deprecated options entirely.
+
+## rm_templates files
+
+Files in `plugins/module_utils/network/vyos/rm_templates/` define regex parsers and Jinja2 generators for a resource module. Each entry has:
+- `name` — unique identifier
+- `getval` — compiled regex with named groups
+- `setval` — Jinja2 template or callable producing a VyOS CLI command
+- `result` — dict mapping regex groups to facts structure
+- `shared` (optional) — bool, whether the template applies to a shared config block
+
+## meta/runtime.yml redirects
+
+Short-name redirects must point to the actual module name with the `vyos_` prefix. For example:
+```yaml
+snmp_server:
+ redirect: vyos.vyos.vyos_snmp_server # correct
+ # NOT: vyos.vyos.vyos_snmp_servers # wrong (pluralized)
+```
+
+Verify any changed redirect target exists as a real module file under `plugins/modules/`.
+
+## cliconf / terminal plugins
+
+`plugins/cliconf/vyos.py` — do not modify without understanding edit-mode and commit semantics.
+`plugins/terminal/vyos.py` — handles prompt detection; regex changes require testing against all supported VyOS versions listed in README.md.
diff --git a/.github/instructions/tests.instructions.md b/.github/instructions/tests.instructions.md
new file mode 100644
index 00000000..150db41e
--- /dev/null
+++ b/.github/instructions/tests.instructions.md
@@ -0,0 +1,114 @@
+---
+applyTo: "tests/unit/**"
+---
+
+# Unit test conventions
+
+## Base class and structure
+
+All test classes inherit from `TestVyosModule` in `tests/unit/modules/network/vyos/vyos_module.py`.
+
+```python
+class TestVyosFooModule(TestVyosModule):
+ module = vyos_foo
+
+ def setUp(self): ...
+ def tearDown(self): ...
+ def load_fixtures(self, commands=None, filename=None): ...
+ def test_...(self): ...
+```
+
+## Mocking: resource modules
+
+Resource module tests require two framework-level patches in `setUp` with corresponding cleanup in `tearDown`:
+
+```python
+# in setUp:
+self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection"
+)
+self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection"
+)
+self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+# in tearDown:
+self.mock_get_resource_connection_config.stop()
+self.mock_get_resource_connection_facts.stop()
+```
+
+Most resource module tests also patch the facts class's `get_device_data` method directly and use it in `load_fixtures`:
+
+```python
+# in setUp:
+self.mock_execute_show_command = patch(
+ "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos."
+ "facts.{resource}.{resource}.{Resource}Facts.get_device_data"
+)
+self.execute_show_command = self.mock_execute_show_command.start()
+
+# in load_fixtures:
+def load_from_file(*args, **kwargs):
+ return load_fixture("vyos_{resource}_config.cfg")
+self.execute_show_command.side_effect = load_from_file
+```
+
+An alternative pattern sets `self.get_resource_connection_facts.return_value.get_config.return_value = fixture_data` in `load_fixtures` instead — both approaches work, but the `get_device_data` pattern is used by most existing tests.
+
+## Mocking: legacy modules
+
+Legacy modules (`vyos_vlan`, `vyos_config`, `vyos_command`, etc.) patch the specific helper the module calls, directly in the module under test. Which helper depends on the module:
+
+```python
+# vyos_command, vyos_facts, vyos_ping — patch run_commands
+self.mock_run_commands = patch("ansible_collections.vyos.vyos.plugins.modules.vyos_foo.run_commands")
+# vyos_config — patch get_config / load_config
+self.mock_load_config = patch("ansible_collections.vyos.vyos.plugins.modules.vyos_foo.load_config")
+```
+
+In `load_fixtures`, configure the mock using `side_effect` (for dynamic fixture loading) or `return_value` (for a fixed response):
+
+```python
+# side_effect — used by most existing legacy tests
+def load_from_file(*args, **kwargs):
+ return load_fixture("vyos_foo_config.cfg")
+self.run_commands.side_effect = load_from_file
+
+# return_value — acceptable for simple fixed responses
+self.run_commands.return_value = [SHOW_OUTPUT]
+```
+
+## load_fixtures and filename
+
+`execute_module()` always calls `load_fixtures()`. Never set mock return values inside a test method — they will be overwritten by the next `execute_module` call. Use the `filename` parameter to vary the fixture:
+
+```python
+def load_fixtures(self, commands=None, filename=None):
+ if filename == "empty":
+ self.run_commands.return_value = [EMPTY_OUTPUT]
+ else:
+ self.run_commands.return_value = [DEFAULT_OUTPUT]
+```
+
+Then call: `self.execute_module(changed=True, commands=commands, filename="empty")`
+
+## Fixture files
+
+Raw device CLI output lives in `tests/unit/modules/network/vyos/fixtures/` as `.cfg` files.
+Load with `load_fixture("vyos_foo_config.cfg")`.
+
+## Required test coverage for resource modules
+
+A complete resource module test file should cover all applicable states:
+- `merged` (including an idempotent case)
+- `replaced`
+- `overridden`
+- `deleted`
+- `rendered` — assert `result["rendered"]` matches expected CLI commands
+- `gathered` — assert `result["gathered"]` contains expected structured data
+- `parsed` — pass `running_config=raw_string` and assert `result["parsed"]`
+
+Flag test files that are missing `rendered`, `gathered`, or `parsed` tests without explanation.
+
diff --git a/.github/mergify.yml b/.github/mergify.yml
new file mode 100644
index 00000000..43353ea4
--- /dev/null
+++ b/.github/mergify.yml
@@ -0,0 +1,34 @@
+# yaml-language-server: $schema=https://docs.mergify.com/mergify-configuration-schema.json
+extends: mergify
+merge_protections_settings:
+ reporting_method: check-runs
+
+pull_request_rules:
+ - name: Flag product T-ID format violation in PR title or commit messages
+ description: >
+ Product-repo convention: the PR title AND every commit's first line must
+ match `T<digits>: <text>` (optional `scope: ` prefix). The title is always
+ checked; the per-commit check is exempted when a maintainer applies the
+ `legacy` label — an escape hatch for grandfathered PRs whose commit history
+ cannot be rewritten (repos that squash-merge AND block force-push, e.g.
+ vyos.vyos enforces `non_fast_forward` on ~ALL branches with zero bypass).
+ New PRs are still nudged toward the convention; `legacy` is the deliberate,
+ maintainer-controlled opt-out. Relocated from the central config (T8966)
+ so the convention is opt-in per product repo. Name is intentionally
+ distinct from any central rule name so this stays additive (not an
+ `extends:` override). Legacy-label escape added 2026-06-08 (T8966).
+ conditions:
+ - '-closed'
+ - '-merged'
+ - '-author~=\[bot\]$'
+ - 'author!=copilot-swe-agent'
+ - 'author!=vyosbot'
+ - or:
+ - '-title~=^(([a-zA-Z0-9\-_.]+:\s)?)T\d+:\s+[^\s]+.*'
+ - and:
+ - 'label!=legacy'
+ - 'commits[*].commit_message~=^(?!(([a-zA-Z0-9\-_.]+:\s)?)T\d+:\s+[^\s]+).*'
+ actions:
+ label:
+ toggle:
+ - invalid-task-id
diff --git a/.github/workflows/ah_token_refresh.yml b/.github/workflows/ah_token_refresh.yml
index 0346920e..09d2f9db 100644
--- a/.github/workflows/ah_token_refresh.yml
+++ b/.github/workflows/ah_token_refresh.yml
@@ -7,7 +7,7 @@ on:
jobs:
refresh:
- uses: ansible/team-devtools/.github/workflows/ah_token_refresh.yml@v26.1.0
+ uses: ansible/team-devtools/.github/workflows/ah_token_refresh.yml@v26.4.0
with:
environment: release
secrets:
diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml
index da3e6efd..fa96d19d 100644
--- a/.github/workflows/cla-check.yml
+++ b/.github/workflows/cla-check.yml
@@ -11,5 +11,5 @@ on:
types: [created]
jobs:
call-cla-assistant:
- uses: vyos/vyos-cla-signatures/.github/workflows/cla-reusable.yml@current
+ uses: vyos/vyos-cla-signatures/.github/workflows/cla-reusable.yml@production
secrets: inherit
diff --git a/.github/workflows/codecoverage.yml b/.github/workflows/codecoverage.yml
index 878ae247..ee71e179 100644
--- a/.github/workflows/codecoverage.yml
+++ b/.github/workflows/codecoverage.yml
@@ -62,7 +62,7 @@ jobs:
working-directory: ${{ steps.identify.outputs.collection_path }}
- name: Upload coverage report to Codecov
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@v7
with:
directory: ${{ steps.identify.outputs.collection_path }}
fail_ci_if_error: false
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000..b83b94e0
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,30 @@
+name: "Perform CodeQL Analysis"
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - '**'
+ - '!.github/**'
+ - '!**/*.md'
+ pull_request:
+ branches:
+ - main
+ paths:
+ - '**'
+ - '!.github/**'
+ - '!**/*.md'
+ schedule:
+ - cron: '52 13 * * 0'
+
+permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+jobs:
+ codeql-analysis-call:
+ uses: vyos/.github/.github/workflows/codeql-analysis.yml@production
+ with:
+ languages: "['python']"