Skip to content

feat(wrapper-generator): module packaging scripts and full v1.0 validation - #3698

Open
Joywambui-maina wants to merge 13 commits into
powershell-v3from
feature/wrapper-module-packaging
Open

feat(wrapper-generator): module packaging scripts and full v1.0 validation#3698
Joywambui-maina wants to merge 13 commits into
powershell-v3from
feature/wrapper-module-packaging

Conversation

@Joywambui-maina

Copy link
Copy Markdown

Changes proposed in this pull request

  • Packaging scripts: Build-WrapperModule.ps1 turns an OpenAPI doc into an importable module (kiota client + wrappers + dll + PSD1); Test-WrapperModule.ps1 imports it in a fresh pwsh and smoke-tests it like a user would. Generation defaults to the
    Kiota-compatible docs — kiota rejects or hangs on the PowerShell-profile ones.
  • Eight emitter fixes, each found by compiling a real module and pinned by a test: worker errors no longer masked by dispatchers, -DeviceId1-style collision handling matching the published SDK, fully-qualified model types mirroring kiota's renames, query options only where declared, re-fetch only where a GET exists, media endpoints skipped.
  • Two naming findings: shipped *-MgPlaceCheck is an AutoRest preposition truncation (Investigate how to mitigate AutoREST command name truncation when operationIds contain prepositions #912 class) — corrected per policy; "Rights" added to the invariants (Get-MgPrivacySubjectRightsRequest), taking Compliance to 23/23.
  • Catalog: new edge-cases/kiota-alignment-edge-cases.md documenting each defect class.

Results: 35/35 cmdlet-producing v1.0 modules build and pass import smoke tests (the 4 actions/functions-only modules emit nothing by design); names match the published inventory wherever it has an entry, corrections reported as [CORRECTED]. 103 tests pass.

Graph declares Edm.Int32/Int64 as "number" with the real type in the
format; mapping by type alone emitted double? against Kiota's int? and
did not compile. An explicit format now decides the CLR type, mirroring
Kiota's own mapping.
…racle audit

Auditing every v1.0 GET command in MgCommandMetadata.json against the
singularizer surfaced four words where the rules disagree with shipped
cmdlet names: Cookies -> "Cooky" (ships as ...HostCookie), Skus kept
as-is (ships as Get-MgSubscribedSku), Dns -> "Dn" (ships as
Get-MgDomainVerificationDnsRecord), Ios -> "Io" (ships as
Get-MgDeviceAppManagementIosManagedAppProtection). Adds two irregulars
and two invariants, each with a pinned test, and refreshes the README
test count.

82 tests passing. Full-inventory match after fix: 796 of 870 noun
segments; the remaining 74 are action/function segments and AutoRest
hand renames, tracked separately.
…nt, start edge-case catalog

Only 2 of 30 shipped whois-family commands truncate "Whois" to "Whoi"; per
review decision the generator emits the corrected ...HostWhois (no alias for
the old name), and the parity gate reports it as [CORRECTED] instead of
failing. "Statistics" joins the invariants, found via the DEVX Humanizer
exception list. edge-cases/naming-edge-cases.md starts the per-class
catalog of naming defects. 88 tests passing.
Build-WrapperModule.ps1 turns one OpenAPI doc into an importable module
(kiota client + wrappers + csproj + dll + PSD1 manifest), reading the
Kiota-compatible docs by default with a hard kiota timeout and per-module
doc fallback. Test-WrapperModule.ps1 imports each build in a fresh pwsh
and verifies exports, worker pairing, and the sessionless NoGraphSession
path. All 35 cmdlet-producing v1.0 modules build and pass.
Compiling all v1.0 modules against freshly generated kiota clients
surfaced eight alignment defects, each fixed and pinned by a test:
dispatchers re-wrapped worker errors (NoGraphSession was lost); body
properties colliding with path ids (published convention: -DeviceId1);
bare model types colliding with namespaces and BCL types (now fully
qualified, mirroring kiota's move-inside and reserved-name renames at
root and in sub-namespaces); collection responses resolved from their
own $ref; underscore members (riskEventTypes_v2 -> RiskEventTypesV2);
$select/$expand emitted only where declared; re-fetch only where a GET
exists; media/content endpoints skipped like $value.
…ant, catalog kiota edge cases

The full-module parity sweep found two shipped-name issues: AutoRest
truncated /places/{id}/checkIns at the preposition (8 commands ship as
*-MgPlaceCheck while Get-MgPlaceCheckInCount keeps "In") - corrected per
policy with gate rows and pinned tests; and "Rights" needs to be an
inflection invariant (Get-MgPrivacySubjectRightsRequest, 42 cmdlets) -
Compliance now matches 23 of 23. New edge-cases/kiota-alignment file
catalogs the compile-found defect classes; README refreshed. 103 tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (1)

tools/WrapperGenerator/CmdletEmitter.cs:694

  • EmitPropertyAssignments currently uses the null-forgiving operator for array parameters (e.g., ParameterName!.ToList()). In PowerShell, a user can bind an array parameter explicitly as $null; IsParameterBound(...) will be true, and this will throw a NullReferenceException at runtime. Prefer ?.ToList() so bound $null cleanly maps to a null model property (and still distinguishes omitted vs bound-null via IsParameterBound).
        string.Join("\n", properties.Select(p => $$"""

            if (this.IsParameterBound(nameof({{p.ParameterName}})))
                body.{{p.PascalName}} = {{(p.IsArray ? $"{p.ParameterName}!.ToList()" : p.ParameterName)}};
        """));

A second operation resolving to an already-written cmdlet file now fails
generation with the full collision list instead of silently overwriting it,
which is the silent-drop failure mode AutoRest had.

OData cast list/item pairs (owners/graph.user) now merge like plain pairs,
and the sweep's collisions land as cited NamingOverrides entries: termStore
and agreement-file stitches, default-singleton renames (SubSite,
DefaultDrive, DefaultCalendarEvent), and nested navs the SDK never shipped.
Remaining families are tracked on #3704.
… data

Derive-CollisionResolutions.ps1 replays the checked-in collision inventory
(212 lines, 365 contested routes) against MgCommandMetadata and emits
exact-match resolution data: 191 suppressions (routes the published SDK
prunes) and 64 renames (published nouns), each entry carrying its oracle
evidence. The files embed into the generator and apply only when
UseCollisionData is set; -Validate fails on drift, and a new xunit test
runs it on every `dotnet test` so staleness fails the suite instead of
depending on someone remembering to run the script by hand. Derivation
itself fails on any unclassified or ambiguous route. Only 2 cross-path
variant merges exist in all of v1.0 (GroupPhoto, ShareListItem) - deferred
with the singleton side kept, cataloged in crosspath-merge-edge-cases.md.

Full 39-module v1.0 generation now produces zero collisions; 20 published
commands that lost filename races are recovered; exact-name matches rise
5,042 -> 5,098.

Also: cmdlets emit into a per-module namespace derived from the client
namespace instead of the leftover MgPoC placeholder; Build-WrapperModule's
generated csproj references Authentication by a relative path instead of
an absolute one; its -Configuration parameter now actually reaches the
wrapper generator's own build, not just the final module build; and a
pre-existing nullable warning in the list/item pairing check is fixed.
121 tests pass.
Comment thread tools/Build-WrapperModule.ps1 Outdated
Comment thread tools/Build-WrapperModule.ps1 Outdated
Comment thread tools/Build-WrapperModule.ps1 Outdated
Comment thread tools/Build-WrapperModule.ps1 Outdated
Joywambui-maina and others added 4 commits August 13, 2026 21:20
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
fix(wrapper-generator): fail loudly on cmdlet file collisions
Both lines carried the same singularizer-era fixes as different commits, so
the five conflicts resolve to identical rules plus each side's real
additions: powershell-v3's docs/edge-cases layout and lean comments win;
the packaging line's Rights invariant, ResolveParameterNameCollisions, and
PlaceCheckIn corrections survive. README test count set to the measured
121; its no-compile-test claim was already false here and is corrected.
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.

3 participants