Skip to content

fix: ServiceClient org metadata and multi-layer environment resolution#98

Merged
joshsmithxrm merged 7 commits intomainfrom
fix/environment-resolution
Jan 2, 2026
Merged

fix: ServiceClient org metadata and multi-layer environment resolution#98
joshsmithxrm merged 7 commits intomainfrom
fix/environment-resolution

Conversation

@joshsmithxrm
Copy link
Copy Markdown
Owner

Summary

Root Cause (#86)

ServiceClient uses lazy initialization for org metadata properties. The connection pool clones clients before properties are accessed, so clones had empty metadata.

Fix: Access ConnectedOrgFriendlyName immediately after ServiceClient creation to force lazy initialization before cloning.

Changes

Credential Providers (5 files)

  • InteractiveBrowserCredentialProvider.cs
  • DeviceCodeCredentialProvider.cs
  • ManagedIdentityCredentialProvider.cs
  • GitHubFederatedCredentialProvider.cs
  • AzureDevOpsFederatedCredentialProvider.cs

Added eager property access after ServiceClient creation.

New Service

  • EnvironmentResolutionService.cs - Multi-layer resolution:
    • URL identifier → Direct Dataverse connection first
    • Name/ID identifier → Global Discovery
    • Service principals without URL → Helpful error message

CLI Commands

  • EnvCommandGroup.cs - Updated ppds env select to use resolver
  • AuthCommandGroup.cs - Updated ppds auth update --environment to use resolver

Test plan

  • ppds env who shows populated Unique Name and Friendly Name
  • ppds env select <url> works with service principals (direct connection)
  • ppds env select <name> works with user auth (Global Discovery fallback)
  • All unit tests pass

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings January 2, 2026 21:30
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @joshsmithxrm, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the reliability and user experience for connecting to Dataverse environments. It resolves a critical bug where organization metadata was often missing from ServiceClient instances by ensuring eager initialization. Furthermore, it introduces a sophisticated multi-layer environment resolution mechanism for CLI commands, allowing users to specify environments by URL, name, or ID, and intelligently determining the best connection method based on the input and authentication type. This enhances both the ppds env select and ppds auth update --environment commands, making environment management more robust and informative.

Highlights

  • ServiceClient Metadata Fix: Addressed an issue where ServiceClient organization metadata (FriendlyName, UniqueName, OrgId) was not being populated due to lazy initialization and client cloning in the connection pool. This is fixed by forcing eager initialization of these properties immediately after client creation.
  • Multi-Layer Environment Resolution: Introduced a new EnvironmentResolutionService to provide a robust, multi-layer approach for resolving environments in CLI commands (ppds env select and ppds auth update --environment). This service prioritizes direct Dataverse connections for URLs and falls back to Global Discovery for name/ID resolution, with specific handling for service principals.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces significant improvements by fixing organization metadata population and adding a multi-layer environment resolution service. The new EnvironmentResolutionService is a great architectural enhancement that centralizes and simplifies how environments are resolved, correctly handling different authentication methods like service principals and interactive users. The fix for the lazy-loading of ServiceClient metadata is clever and effectively solves the described issue. However, I've identified a regression in several credential providers where the cancellationToken is no longer respected for the initial token acquisition, which could make the application unresponsive. I've left comments with details on this. Overall, these are excellent changes that improve the robustness and usability of the authentication and environment management features.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes ServiceClient organization metadata population issues and adds multi-layer environment resolution to support service principals with URL-based environment selection.

Key Changes:

  • Fixed lazy initialization of ServiceClient org metadata by eagerly accessing ConnectedOrgFriendlyName in 5 credential providers
  • Added EnvironmentResolutionService that tries direct Dataverse connection before falling back to Global Discovery
  • Updated ppds env select and ppds auth update --environment commands to use the new resolution service

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/PPDS.Auth/Discovery/EnvironmentResolutionService.cs New multi-layer environment resolution service with direct connection and Global Discovery fallback
src/PPDS.Auth/Credentials/InteractiveBrowserCredentialProvider.cs Switched to ConnectionOptions constructor and added eager metadata access
src/PPDS.Auth/Credentials/DeviceCodeCredentialProvider.cs Switched to ConnectionOptions constructor and added eager metadata access
src/PPDS.Auth/Credentials/ManagedIdentityCredentialProvider.cs Switched to ConnectionOptions constructor and added eager metadata access
src/PPDS.Auth/Credentials/GitHubFederatedCredentialProvider.cs Switched to ConnectionOptions constructor and added eager metadata access
src/PPDS.Auth/Credentials/AzureDevOpsFederatedCredentialProvider.cs Switched to ConnectionOptions constructor and added eager metadata access
src/PPDS.Cli/Commands/Env/EnvCommandGroup.cs Replaced Global Discovery-only logic with EnvironmentResolutionService
src/PPDS.Cli/Commands/Auth/AuthCommandGroup.cs Replaced string parsing with EnvironmentResolutionService for validation
src/PPDS.Auth/CHANGELOG.md Documented ServiceClient metadata fix and new resolution service
src/PPDS.Cli/CHANGELOG.md Documented environment resolution improvements for service principals

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

joshsmithxrm and others added 6 commits January 2, 2026 15:45
Issue #86: Added SkipDiscovery = false to ConnectionOptions in 5 credential
providers (InteractiveBrowser, DeviceCode, ManagedIdentity, GitHubFederated,
AzureDevOpsFederated) to force org metadata discovery.

Issues #89 + #88: Added EnvironmentResolutionService for multi-layer resolution:
- Direct Dataverse connection first (works for service principals)
- Global Discovery fallback (for interactive users)
- Updated ppds env select and ppds auth update --environment to use new resolver

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ServiceClient org metadata discovery is lazy - properties are only
populated when first accessed. Since the connection pool clones the
seed client before properties are accessed, the clones had empty
org metadata.

Fix: Access ConnectedOrgFriendlyName immediately after creating the
ServiceClient to trigger discovery while values can still be copied
to clones.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Testing confirmed that SkipDiscovery = false is not required.
The eager property access alone triggers org metadata discovery.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added detailed comments explaining why we access ConnectedOrgFriendlyName
immediately after ServiceClient creation. Referenced that PAC CLI uses
the same pattern (ConnectedOrgToSelectedOrganizationInfo after Connect).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add token cache priming with cancellationToken in GitHubFederated,
  AzureDevOpsFederated, and ManagedIdentity credential providers
- Simplify CanUseGlobalDiscovery to use 'is or' pattern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@joshsmithxrm joshsmithxrm force-pushed the fix/environment-resolution branch from 6904f3e to 334ae11 Compare January 2, 2026 21:46
- Fixed return description to match actual Result type
- Removed incorrect exception documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@joshsmithxrm joshsmithxrm force-pushed the fix/environment-resolution branch from 582611d to b9bd8d2 Compare January 2, 2026 21:58
@joshsmithxrm joshsmithxrm merged commit 236bb33 into main Jan 2, 2026
6 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in PPDS Roadmap Jan 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants