Skip to content

feat(rust): port config validate to native Rust (Phase 1.3)#1282

Draft
jd wants to merge 1 commit intodevs/jd/worktree-rust-port/add-mergify-core-http-retry-typed-errors-phase-1--9c66057cfrom
devs/jd/worktree-rust-port/port-config-validate-native-rust-phase-1-3--52ffe9eb
Draft

feat(rust): port config validate to native Rust (Phase 1.3)#1282
jd wants to merge 1 commit intodevs/jd/worktree-rust-port/add-mergify-core-http-retry-typed-errors-phase-1--9c66057cfrom
devs/jd/worktree-rust-port/port-config-validate-native-rust-phase-1-3--52ffe9eb

Conversation

@jd
Copy link
Copy Markdown
Member

@jd jd commented Apr 21, 2026

First native command. Exercises every piece of the foundations
work so far — HTTP fetch, JSON-schema validation, output
discipline, typed exit codes — and proves the shim-fallback
dispatch pattern.

What ports natively

mergify config validate [-f PATH]:

  1. Resolves the config file (explicit --config-file or the
    first of .mergify.yml, .mergify/config.yml,
    .github/mergify.yml).
  2. Parses it as YAML via serde_norway. Empty files are treated
    as an empty mapping; non-mapping top-level values are rejected.
  3. Fetches the published schema from
    https://docs.mergify.com/mergify-configuration-schema.json
    via the Phase 1.2b HTTP client (30s timeout, retry on 5xx).
  4. Validates with the jsonschema crate (draft-07).
  5. Emits a human-readable success line or a sorted, path-prefixed
    per-error list via Output::emit.

Exit codes: success → 0, missing / unparseable / schema violations
→ 8 (CONFIGURATION_ERROR), schema-fetch failure → 6
(MERGIFY_API_ERROR).

Dispatch

mergify-cli/src/main.rs inspects argv for a config validate
pair; if present, it parses with clap and runs the native path.
Everything else — including config simulate, every stack
command, the global --version / --help, plus any invalid
invocation — falls through to the Python shim unchanged. Clap is
loaded only when a native match is suspected, so unknown flags on
un-ported commands still produce Python's click error messages
verbatim.

Smoke-tested against the real docs CDN

Missing config → exit 8. Valid config → exit 0. Invalid config →
detailed error list + summary, exit 8. mergify --version still
falls through to Python.

Test coverage

11 unit tests in mergify-config:

  • resolve_config_path with explicit, default, and missing paths
  • load_yaml happy path, scalar rejection, malformed YAML,
    empty-file-is-empty-mapping
  • validate_against_schema happy path + error aggregation
  • emit_result for success and failure rendering

Binary size

2.7 MB → 8.0 MB. The jump is jsonschema pulling fancy-regex + the
referencing crate's schema resolver. Still well under the 15 MB
design target; we can trim with features later if needed.

Follow-up

  • 1.3b: port config simulate
  • 1.4+: ci commands (first CI-facing wins for the port story)

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

Depends-On: #1281

@jd
Copy link
Copy Markdown
Member Author

jd commented Apr 21, 2026

This pull request is part of a Mergify stack:

# Pull Request Link
1 feat(rust): scaffold Cargo workspace and Rust CI #1263
2 feat(rust): add mergify-py-shim with embedded Python fallback #1272
3 feat(rust): add mergify-core foundation types (Phase 1.2a) #1280
4 feat(rust): add mergify-core::http with retry + typed errors (Phase 1.2b) #1281
5 feat(rust): port config validate to native Rust (Phase 1.3) #1282 👈

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Apr 21, 2026

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🔴 👀 Review Requirements

Waiting for:

  • #approved-reviews-by>=2
This rule is failing.
  • any of:
    • #approved-reviews-by>=2
    • author = dependabot[bot]
    • author = mergify-ci-bot
    • author = renovate[bot]

🔴 🔎 Reviews

Waiting for:

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

🟢 🤖 Continuous Integration

Wonderful, this rule succeeded.
  • all of:
    • check-success=ci-gate

🟢 Enforce conventional commit

Wonderful, this rule succeeded.

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?:

🟢 📕 PR description

Wonderful, this rule succeeded.
  • body ~= (?ms:.{48,})

@mergify mergify Bot requested a review from a team April 21, 2026 13:09
First native command. Exercises every piece of the foundations
work so far — HTTP fetch, JSON-schema validation, output
discipline, typed exit codes — and proves the shim-fallback
dispatch pattern.

## What ports natively

``mergify config validate [-f PATH]``:

1. Resolves the config file (explicit ``--config-file`` or the
   first of ``.mergify.yml``, ``.mergify/config.yml``,
   ``.github/mergify.yml``).
2. Parses it as YAML via ``serde_norway``. Empty files are treated
   as an empty mapping; non-mapping top-level values are rejected.
3. Fetches the published schema from
   ``https://docs.mergify.com/mergify-configuration-schema.json``
   via the Phase 1.2b HTTP client (30s timeout, retry on 5xx).
4. Validates with the ``jsonschema`` crate (draft-07).
5. Emits a human-readable success line or a sorted, path-prefixed
   per-error list via ``Output::emit``.

Exit codes: success → 0, missing / unparseable / schema violations
→ 8 (``CONFIGURATION_ERROR``), schema-fetch failure → 6
(``MERGIFY_API_ERROR``).

## Dispatch

``mergify-cli/src/main.rs`` inspects argv for a ``config validate``
pair; if present, it parses with clap and runs the native path.
Everything else — including ``config simulate``, every ``stack``
command, the global ``--version`` / ``--help``, plus any invalid
invocation — falls through to the Python shim unchanged. Clap is
loaded only when a native match is suspected, so unknown flags on
un-ported commands still produce Python's click error messages
verbatim.

## Smoke-tested against the real docs CDN

Missing config → exit 8. Valid config → exit 0. Invalid config →
detailed error list + summary, exit 8. ``mergify --version`` still
falls through to Python.

## Test coverage

11 unit tests in ``mergify-config``:

- ``resolve_config_path`` with explicit, default, and missing paths
- ``load_yaml`` happy path, scalar rejection, malformed YAML,
  empty-file-is-empty-mapping
- ``validate_against_schema`` happy path + error aggregation
- ``emit_result`` for success and failure rendering

## Binary size

2.7 MB → 8.0 MB. The jump is jsonschema pulling fancy-regex + the
referencing crate's schema resolver. Still well under the 15 MB
design target; we can trim with features later if needed.

## Follow-up

- 1.3b: port ``config simulate``
- 1.4+: ``ci`` commands (first CI-facing wins for the port story)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Change-Id: I52ffe9eb817c1879c467c22e2827cbe4c0a4e327
@jd jd force-pushed the devs/jd/worktree-rust-port/port-config-validate-native-rust-phase-1-3--52ffe9eb branch from 08627d5 to 8b898c2 Compare April 21, 2026 13:13
@jd
Copy link
Copy Markdown
Member Author

jd commented Apr 21, 2026

Revision history

# Type Changes Date
1 initial 08627d5 2026-04-21 13:13 UTC
2 rebase 08627d5 → 8b898c2 2026-04-21 13:13 UTC

@mergify mergify Bot had a problem deploying to Mergify Merge Protections April 21, 2026 13:14 Failure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant