Skip to content

Merge master into next - #305

Merged
jtdub merged 7 commits into
nextfrom
sync-master-into-next
Sep 20, 2026
Merged

jtdub merged 7 commits into
nextfrom
sync-master-into-next

Conversation

@jtdub

@jtdub jtdub commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes: DNE

Merges master into next. master carries one commit that next does not have: the Ruckus/Brocade FastIron (ICX) driver (#304). The merge conflicts because next reorganized the docs, the tests, and the driver registry after master branched, so the FastIron change is re-landed on those structures.

Library

  • Registers RUCKUS_FASTIRON in hier_config/registry.py. next moved the platform-to-driver map out of constructors.py, so the entry goes there, keyed on Platform.RUCKUS_FASTIRON.name.
  • Converts HConfigDriverRuckusFastIron to the unified negation rule list. It declared negate_with and negation_sub, which on next are the permanent v3 compatibility surface. Every other built-in driver uses negation. all_negation_rules() resolves both, so behavior does not change.

Docs

  • Moves the FastIron driver section and the platform table row to docs/admin/platforms.md. next replaced docs/user/drivers.md with that page, and mkdocs.yml already redirects the old path.
  • Uses HConfig.from_text() and remediation() in the section's example, matching the rest of the page.
  • Drops master's platform table row for docs/index.md: that page carries no table on next.

Tests

  • Moves the driver scenarios to tests/integration/test_ruckus_fastiron.py, the four config fixtures to tests/integration/fixtures/, and their accessors to tests/integration/conftest.py.
  • Rewrites the test to HConfig.from_text(), remediation(), and to_lines(), the idiom every other integration test uses.
  • Freezes the platform list in tests/integration/v3_scenarios.py. The v3_platform_to_v2_os scenario enumerated every Platform member, so any platform added after v3.7.0 broke the committed v3 baseline. A v4-only platform has no v3 mapping to compare against.

CI

  • .github/workflows/claude-review.yml set UV_FROZEN on the job and UV_LOCKED on the install step. uv refuses both together, so uv sync exited 2 and the review job failed. Every earlier run was skipped, for draft or fork pull requests, so nothing caught it. The job-level UV_FROZEN is what stops the agent rewriting uv.lock, so the step-level UV_LOCKED is removed. build-and-test.yml still asserts the lock is current on every push.

Test plan

  • uv run ./scripts/build.py lint-and-test exits 0. Coverage is 97.58%, above the 95% floor. The FastIron driver and its functions module are at 100%.
  • uv run mkdocs build --strict exits 0.
  • tests/integration/test_ruckus_fastiron.py passes all 56 tests, including both round trips against the ICX 6450 and ICX 6650 fixtures.
  • tests/integration/test_v3_baseline.py passes against the committed v3.7.0 recording.

Note on the review check: claude-code-action requires the workflow file to match the copy on the default branch, which is master. next converted the workflow from poetry to uv in #301, so the two differ and the action skips itself. The job reports success. The review runs again once next reaches master.

Self-Review Checklist

  • uv run ./scripts/build.py lint-and-test passes locally (lint + 95% test coverage).
  • Tests were written first (TDD) and cover the change, following the testing conventions. This is a merge of code that shipped with its tests in Add Ruckus/Brocade FastIron (ICX) platform support #304; no new behavior is added here.
  • CHANGELOG.md has an entry under ## [Unreleased] referencing this issue/PR ((#NNN)).
  • Documentation is updated if public API or driver behavior changed (and mkdocs build --strict passes if docs were touched).
  • Commit messages follow the contributing guide: imperative mood, subject ≤72 characters, body explains why.

AI-Assisted Contributions

Written with Claude Code and reviewed with the hier-config-review skill.

@jtdub
jtdub requested a review from aedwardstx as a code owner September 20, 2026 03:17
Brings the Ruckus/Brocade FastIron (ICX) driver (#304) onto next and
adapts it to the structures next introduced after master branched.

Conflict resolutions:

- Registry: next moved the platform-to-driver map out of constructors.py
  into registry.py, so RUCKUS_FASTIRON is registered there instead.
- Docs: next replaced docs/user/drivers.md with docs/admin/platforms.md,
  so the FastIron section and the platform table row moved there. The
  code example uses the v4 constructor names the rest of the page uses.
  docs/index.md on next carries no platform table, so master's row is
  dropped rather than re-added.
- Tests: next split tests into tests/unit/ and tests/integration/, so
  the driver scenarios moved to tests/integration/test_ruckus_fastiron.py,
  the fixtures to tests/integration/fixtures/, and their conftest
  fixtures to tests/integration/conftest.py. The test now calls the v4
  names (HConfig.from_text, remediation, to_lines) like every other
  integration test.
- v3 baseline: v3_scenarios.py enumerated every Platform member, so a
  platform v4 adds after v3.7.0 broke the frozen recording. The scenario
  now iterates a frozen list of the platforms v3 declares, because a v4
  platform has no v3 mapping to compare against.
The driver landed on master before v4 merged the three negation rule
lists into one, so it configured `negate_with` and `negation_sub`. On
next those two are the permanent v3 compatibility surface, kept for
users who wrote against v3; every other built-in driver declares its
negation through the unified `negation` list.

`all_negation_rules()` resolves both spellings, so behaviour is
unchanged and the driver's tests pass as written.
uv refuses both at once ("the argument `UV_LOCKED` cannot be used with
`UV_FROZEN`"), so `uv sync` exited 2 and the review never ran. Every
earlier run of this workflow was skipped, because the pull requests were
drafts or came from forks, so nothing caught it.

The job-level UV_FROZEN already stops the agent's `uv run` calls from
rewriting uv.lock, which is what the setting is there for.
build-and-test.yml keeps UV_LOCKED and asserts the lock is current on
every push, so that check is not lost.
The driver recorded every device-enforced dependency as a `#` comment
beside the rule it explains. The reasons belong in the docstring of the
function that holds the rules, where a reader finds them from the class
and where `help()` shows them.

`_instantiate_rules()` now carries the ordering rationale as a list, one
item per dependency, and the remaining platform facts under it. One
comment pointed at `docs/user/drivers.md`, which this branch replaced
with `docs/admin/platforms.md`.
@jtdub
jtdub force-pushed the sync-master-into-next branch from d0fec3c to 56b8dd1 Compare September 20, 2026 03:42
The Rust rewrite moved the Python version to `dynamic` and sourced it from
`[workspace.package] version`, which it set to `4.0.0-beta.4`. Every earlier
release of this line spelled the version `4.0.0bN`, and the tags follow the
same spelling.

Cargo requires semver, so the closest spelling is `4.0.0-b4`. PEP 440
normalizes it to `4.0.0b4`, which is what the wheel and `uv sync` now report.
The driver arrived from master before the Rust core landed on next, so it
existed only in Python. Adding `RUCKUS_FASTIRON` to the Python `Platform`
enum on its own breaks VyOS: the enum uses `auto()`, so its members are
numbered by position, the PyO3 bindings parse a member's value, and the core
mapped "13" to VyOS and rejected "14". Every `HConfig.from_text(Platform.VYOS,
...)` call would raise `unsupported driver.platform: "14"`.

Add the `RuckusFastiron` variant in the position the Python enum gives it and
renumber VyOS to "14", so the two enums stay aligned. `FromStr` now documents
that contract, because the next platform added to the middle of the Python
enum hits the same trap.

Move the driver rules into `crates/hier_config_core/src/platforms/
ruckus_fastiron/rules.json`. The core's embedded JSON is the single source of
truth for a built-in platform, and `test_all_14_platforms_load_rules_via_
rust_and_python` asserts the driver's rules match it, so the rules cannot stay
as a Python literal. `_instantiate_rules()` now calls `load_platform_rules()`
and keeps only the four post-load callbacks, which the core does not own and
`hier_config.constructors` still runs in Python.

Cover the platform the way the others are covered: a driver test for the
prefixes, the single-space indentation, the prompt-echo stripping, the LAG
regex negation and the ACL ordering, plus four corpus cases that the property
tests need.
`maturin develop` installs the project dependencies before it builds, and it
passes the PEP 735 `--group` flag to do so. Its default installer is the pip
inside `.venv`, which the job seeds with `python -m venv`. That pip is older
than 25.1, so it answers "no such option: --group" and maturin exits 1 before
the review agent ever starts.

`--uv` makes maturin install with uv, which the job already uses for
everything else, so the venv's pip version stops mattering.

build-and-test.yml avoids the same failure by upgrading pip first. This job
has no pip step to hang that on.
@jtdub
jtdub merged commit 871bbcf into next Sep 20, 2026
18 checks passed
@jtdub
jtdub deleted the sync-master-into-next branch September 20, 2026 04:15
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