Skip to content

Dev/nl/cisconxos#87

Merged
liunick-msft merged 11 commits intomainfrom
dev/nl/cisconxos
Feb 9, 2026
Merged

Dev/nl/cisconxos#87
liunick-msft merged 11 commits intomainfrom
dev/nl/cisconxos

Conversation

@liunick-msft
Copy link
Contributor

This pull request introduces comprehensive improvements to the build, test, and release workflow for the Azure Local Network Switch Config Generator tool. The changes enhance CI/CD pipeline safety, enforce best practices, and document architectural and coding standards for future contributors. The most important updates are grouped below:

Documentation and Standards

  • Added .github/copilot-instructions.md with detailed architectural, design, testing, and coding conventions to guide contributors and ensure production-grade quality and extensibility.

CI/CD Pipeline Enhancements

  • Updated .github/workflows/build-switchgentool.yml to restrict builds to the main branch and tag pushes, improving release discipline and preventing unnecessary builds on feature branches.
  • Introduced concurrency controls to cancel in-progress runs for the same branch or PR, ensuring only the latest commit is built and tested, except for tag pushes which always complete.
  • Split the workflow into three jobs: test (pytest suite), build (PyInstaller executables for Windows and Linux), and release (GitHub Release with environment approval gate and write permissions). The build job now depends on successful test completion, and the release job is only triggered by tag pushes, requiring manual approval. [1] [2]
  • Updated Python version to 3.12 across all jobs for consistency with project standards.

Build and Test Improvements

  • Simplified dependency installation and removed redundant source test steps for a cleaner build process.
  • Improved BMC converter module inclusion verification with a more robust import check.

Permissions

  • Added scoped permissions for workflow jobs and explicit write permissions for the release job, increasing security and compliance. [1] [2]

These changes collectively enforce architectural invariants, streamline the CI/CD pipeline, and provide clear guidance for maintainers and contributors, ensuring safe, consistent, and extensible production switch configuration generation.

- Create src/constants.py: centralized magic strings, defaults, templates,
  BMC_HARDCODED_VLANS (VLANs 2/99 per DC4)
- Create src/utils.py: infer_firmware(), classify_vlan_group() shared utils
- Rewrite src/loader.py: remove dead pretty_print_json, raise exceptions
  instead of returning None, add type hints, use logging
- Rewrite src/generator.py: relative imports only, logging, propagate
  template errors (no more warnings.warn)
- Rewrite src/main.py: add --debug CLI flag (DC3), decompose monolithic
  main(), _configure_logging(), relative imports (DC1)
- Refactor src/convertors/convertors_lab_switch_json.py: import from
  constants/utils, remove dead code, gate debug behind parameter, logging
- Rewrite src/convertors/convertors_bmc_switch_json.py: use get_real_path(),
  infer_firmware(), BMC_HARDCODED_VLANS from constants, logging
- Create tests/conftest.py: shared fixtures, path setup, diff helpers
- Create tests/test_unit.py: 25 unit tests for constants, utils, loader
- Rewrite tests/test_convertors.py: use tmp_path, strip debug key (DC6)
- Fix tests/test_generator.py: proper parametrize IDs (was embedding
  entire _ALL_PAIRS list into each test name)
- Update Dell BMC expected output: remove VLAN 7, update VLAN 99 name

All 56 tests pass (25 unit + 8 converter + 23 generator).
- Create input/switch_interface_templates/cisco/9348GC-FXP.json (16-node BMC)
- Create input/switch_interface_templates/cisco/9348GC-FX3.json (20-node BMC)
- Enhance BMC converter: add port_channels, static_routes, site field
  - _load_template() extracted for reuse by interfaces and port_channels
  - _build_port_channels() reads from template (Trunk type, no IP enrichment)
  - _build_static_routes() derives default route from BMC supernet gateway
  - _build_switch_info() reads site from MainEnvData (consistent with TOR)
- Add Cisco BMC expected outputs for switched (9348GC-FXP) and FC (9348GC-FX3)
- Update Dell BMC expected output with new fields (port_channels, static_routes, site)
- Add 17 new unit tests for BMC converter (switch info, VLANs, port-channels,
  static routes, interfaces)

All 73 tests pass (42 unit + 8 converter + 23 generator).
- ROADMAP.md: Added principle 8 — TOR configs must be template-driven and
  production-quality; BMC configs may hardcode values but must have clear
  comments for future troubleshooting.
- constants.py: Enhanced BMC_HARDCODED_VLANS and BMC_RELEVANT_GROUPS comments
  explaining what each VLAN/prefix means, why it exists, and what to update.
- convertors_bmc_switch_json.py: Updated module docstring to reference the
  principle; improved docstrings on _build_port_channels and _build_static_routes
  with change-guidance for future engineers.
Test data sanitization:
- Replaced all lab-specific hostnames (s46-r21-*, b88-b11-*, etc.) with
  generic role-based names (tor-1a, border-1a, bmc-1, mux-1)
- Replaced all lab IPs (100.71.85.x, 100.69.x, etc.) with private 10.x.x.x
  addresses, preserving subnet alignment for /23 and /22 networks
- Replaced domains (masd.stbtest.microsoft.com → test.example.com),
  sites (rr1 → site1, b88 → site2), naming prefixes, and regions
- Renamed 12 expected output files and 1 reference config to match
  sanitized hostnames
- 49 files modified, zero lab identifiers remaining

test_unit.py rewrite:
- Clear module docstring explaining organization by module under test
- Added pytest fixtures (bmc_converter, bmc_switch_data) to reduce
  boilerplate — BMC tests that use static methods no longer need tmp_path
- Consolidated similar tests via parametrize (e.g. vendor mapping)
- Class-level docstrings describing what each test group validates
- Shared template data as class attributes where appropriate
- Same test count (42 unit tests), same coverage, cleaner structure

All 73 tests pass, 8 skipped.
Test improvements:
- Add 2 new converter test cases: switched_nobmc (93108TC-FX3P, no BMC)
  and switched_20node (93180YC-FX3, 20-node with BMC)
- Add 43 StandardJSONBuilder unit tests covering build_switch,
  build_vlans, resolve_interface_vlans, build_bgp, build_prefix_lists,
  build_qos, deployment_pattern, and build_ip_mapping
- Fix test_generator.py: move generation from collection-time to
  test-time with tmp_path isolation, remove silent except:pass
- Add 8 missing expected .cfg files for std_cisco_nxos_fc
- Clean up stale generated_*.cfg from test case folders
- Total: 103 tests passing (85 unit + 12 converter + 6 generator)

Documentation consolidation:
- Remove QUICK_START.md (merged into README), COPILOT_AGENT_GUIDE.md
  (2177 lines of generic boilerplate), SWITCH_INTERFACE_TEMPLATE.md
  (merged into TEMPLATE_GUIDE)
- Consolidate 7 files / 4179 lines -> 4 files / 659 lines (84% reduction)
- Update README with quick start, Python usage, accurate directory tree
- Deduplicate JSON schema references, remove Go-era content
Build workflow (build-switchgentool.yml):
- Restructure to 3-job pipeline: test → build → release
- Add pytest job (103 tests) as gate before build
- Fix Python 3.11 → 3.12
- Remove stale dev/nl/newDesignv1 branch trigger
- Remove fake 'Quick source test' (replaced by real pytest)
- Remove fallback requirements.txt creation (masks errors)
- Enable release job with GitHub Environment approval gate
- Set fail-fast: true on build matrix (was false)
- Add concurrency group to cancel stale runs
- Push triggers: main only (was main + stale branch)

Triage workflow (triage-submissions.yml):
- Fix checkbox threshold: < 3 → < 2 (template has 2 required)
- Fix error message to match actual checkbox labels
- Fix unsafe JSON interpolation: env var instead of ${{ }}
- Downgrade template patterns (${} / {{}}) to warnings
- Add permissions: issues: write

New files:
- .github/copilot-instructions.md: project-level dev guidance
- ROADMAP.md: CI/CD section, DP9 (BMC optional), KD17-20, DC7-9
Align all references with the official Microsoft product name 'Azure Local'
(formerly Azure Stack HCI). This repo is specific to Azure Local deployments.

Updated files:
- src/*.py docstrings (5 files)
- .github/copilot-instructions.md (title, overview, design principles)
- tools/PortMap/ (README, PortMap.ps1, PortMap.psd1)
- tools/IPAssignment/IPManagement.psd1
- ROADMAP.md (multi-vendor extensibility section)

NOT changed (intentionally):
- InfraAzureDirectoryTenantName — Azure platform field name
- GitHub repo URLs — can't rename the repository
- Golden-file configs (TACACS group name) — would break tests
- Sample reference configs in _cisco_configs/samples/
HIGH fixes:
- SUPPORT.md: Replace unedited template with actual support content
- .gitignore: Remove dangerous '_*' rule that silently ignored files,
  clean up stale Go-related comments and bare '1' line
- TEST_CASES_SUMMARY.md: Rewrite with accurate test counts (103 tests,
  85 unit + 12 converter + 6 generator) replacing stale 38-test data
- Remove .vscode/settings.json from git tracking (already in .gitignore)

MEDIUM fixes:
- BMC converter: Replace legacy 'typing.Dict/List' with modern dict/list
  syntax, add 'from __future__ import annotations'
- TOR converter: Add missing 'from __future__ import annotations'
- main.py: Replace bare print() with _safe_print() wrapper
- CONVERTOR_GUIDE.md: Replace os.path example with pathlib, fix print()
  debugging advice to use logging.debug()
- Fix extra space before comma in TOR converter line 298

LOW fixes:
- Rename s5248f-on.json → S5248F-ON.json (consistent uppercase model names)
- Rename tools/PortMap/README.MD → README.md (consistent extension)
- Delete stale src/test.ps1 (outdated PyInstaller paths, wrong location)
- Normalize sample config extensions from .txt to .conf
- README: Add --debug flag to CLI examples, fix directory tree accuracy,
  use 'python -m src.main' invocation pattern
- Update copilot-instructions.md and TEMPLATE_GUIDE.md for renames

All 103 tests passing.
The _cisco_configs/ folder contained reference sample configs and a
development roadmap used during the dev branch. All architectural
decisions, design principles, and conventions are documented in
.github/copilot-instructions.md — no need to carry dev artifacts to main.
PyInstaller cannot use src/main.py directly because it contains relative
imports (from .generator, from .loader, etc.) which fail with
'ImportError: attempted relative import with no known parent package'
in frozen builds.

Add pyinstaller_entry.py as the build entry point — it bootstraps
sys.path so the src package resolves correctly in both frozen
(sys._MEIPASS) and development environments.

Fixes the 'Smoke test executable' step failure on ubuntu-latest.
Use 'from src.convertors...' instead of inserting 'src' into sys.path
and importing 'from convertors...' — the latter makes convertors the
top-level package, breaking relative imports like 'from ..loader'.
@liunick-msft liunick-msft merged commit 7120384 into main Feb 9, 2026
8 checks passed
@liunick-msft liunick-msft deleted the dev/nl/cisconxos branch February 9, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant