feat: Self-contained CLI publishing and release workflow#108
feat: Self-contained CLI publishing and release workflow#108joshsmithxrm merged 3 commits intomainfrom
Conversation
Summary of ChangesHello @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 enhances the distribution and security of the CLI. By enabling self-contained binary publishing and automating the release process via GitHub Actions, the CLI becomes much easier to consume across different operating systems. Concurrently, a major security improvement has been implemented by moving sensitive authentication credentials into a platform-native secure storage solution, ensuring that secrets are no longer stored directly in plain text within user profiles. Highlights
Ignored Files
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request introduces a significant refactoring of credential management by implementing a new secure credential store. Previously, sensitive information like client secrets, certificate passwords, and user passwords were encrypted and stored directly within the AuthProfile objects in the profile store. This change moves these secrets out of the AuthProfile and into a new SecureCredentialStore, which leverages platform-native secure storage mechanisms (DPAPI on Windows, Keychain on macOS, libsecret on Linux) via Microsoft.Identity.Client.Extensions.Msal.
Key changes include:
- New
ISecureCredentialStoreandSecureCredentialStoreimplementation: A new interface and class are added to handle secure storage, retrieval, and removal ofStoredCredentialobjects, keyed by application ID. This store serializes credentials to a JSON dictionary and encrypts them at rest. A review comment suggested improving the serialization of certificate path and password by using separate fields in the internal DTO instead of a combined string with a separator, to avoid potential parsing issues. AuthProfilesimplification: TheAuthProfileclass no longer containsPassword,ClientSecret, orCertificatePasswordproperties, reducing its responsibility and improving security by separating profile metadata from sensitive credentials. AnAuthorityproperty was added toAuthProfile, and theEnvironmentInfoclass was simplified by removing itsIdproperty.CredentialProviderFactoryupdates: The factory now includes an asynchronousCreateAsyncmethod that can utilize theISecureCredentialStoreto fetch secrets forClientSecret,CertificateFile, andUsernamePasswordauthentication methods. A synchronousCreateoverload is also provided but explicitly disallows secure store lookups forUsernamePasswordand falls back to environment variables forClientSecret. Helper methods were added to encapsulate secret retrieval logic, and the previousValidateRequiredFieldsmethod was removed, with validation now occurring within specific providerFromProfilemethods. Review comments highlighted that federated credential providers (GitHubFederated, AzureDevOpsFederated) were using null-suppressing operators (!) without proper validation forApplicationIdandTenantId, recommending explicitArgumentExceptionthrows for missing required fields.- Profile Store Schema Migration (v1 to v2): The
ProfileCollectionandProfileStorewere updated to a new schema (version 2). This involves changingProfileCollectionfrom using a dictionary of profiles keyed by index to a list of profiles, and tracking the active profile by name instead of index. TheProfileStorenow detects and deletes old v1 schema profile files, requiring users to re-authenticate, which was noted as a breaking change in the remarks. - CLI
auth createcommand: Theppds auth createcommand was updated to store secrets in the newSecureCredentialStoreinstead of directly in the profile, and to store the full authority URL in the profile. - Build configuration: Added self-contained publish configuration to the CLI project file.
There was a problem hiding this comment.
Pull request overview
This PR introduces self-contained CLI publishing capabilities and a major refactoring of the authentication system from schema v1 to v2, moving secrets from encrypted profile storage to a platform-native secure credential store.
Key Changes:
- Configured CLI for self-contained single-file executable publishing with compression
- Added GitHub Actions workflow for automated multi-platform binary releases with SHA256 checksums
- Migrated authentication profiles to schema v2: secrets now stored separately in SecureCredentialStore using platform-native encryption (DPAPI/Keychain/libsecret), active profile tracked by name instead of index, profiles stored as array instead of dictionary
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/release-cli.yml | New workflow for building and releasing CLI binaries across 5 platforms (Windows, macOS, Linux x64/ARM64) on Cli-v* tags |
| src/PPDS.Cli/PPDS.Cli.csproj | Added publish configuration for self-contained single-file executables with compression |
| src/PPDS.Cli/CHANGELOG.md | Documented new self-contained publishing and release workflow features |
| src/PPDS.Cli/Commands/Auth/AuthCommandGroup.cs | Integrated SecureCredentialStore for storing secrets during profile creation; updated to use new profile schema |
| src/PPDS.Auth/Credentials/SecureCredentialStore.cs | New platform-native secure storage using MSAL.Extensions for encrypting client secrets, certificates, and passwords |
| src/PPDS.Auth/Credentials/ISecureCredentialStore.cs | Interface and DTO for secure credential storage operations |
| src/PPDS.Auth/Credentials/CredentialProviderFactory.cs | Added async CreateAsync method with credential store support; synchronous Create now throws for methods requiring secrets |
| src/PPDS.Auth/Credentials/ClientSecretCredentialProvider.cs | Split FromProfile into two methods: one accepting StoredCredential, one accepting explicit secret string |
| src/PPDS.Auth/Credentials/CertificateFileCredentialProvider.cs | Updated to accept certificate password from StoredCredential instead of profile |
| src/PPDS.Auth/Credentials/JwtClaimsParser.cs | Refactored to extract helper methods for claim value retrieval |
| src/PPDS.Auth/Profiles/ProfileStore.cs | Added v1 to v2 migration logic that detects and deletes v1 profiles; removed encryption/decryption logic |
| src/PPDS.Auth/Profiles/ProfilePaths.cs | Added CredentialCacheFileName constant for secure credential store file |
| src/PPDS.Auth/Profiles/ProfileCollection.cs | Changed from dictionary to list storage; active profile tracked by name instead of index; defaults to version 2 |
| src/PPDS.Auth/Profiles/EnvironmentInfo.cs | Removed Id field, kept only URL and DisplayName in Create method |
| src/PPDS.Auth/Profiles/AuthProfile.cs | Removed ClientSecret, Password, and CertificatePassword fields; added Authority field for storing full authority URL |
| tests/* | Updated all tests to reflect schema v2 changes and secure credential store integration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
abd80a5 to
1c18e58
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Add configuration for publishing CLI as self-contained single-file executables and create GitHub Actions workflow to build and release binaries for all major platforms when Cli-v* tags are pushed. Changes: - Add publish settings to PPDS.Cli.csproj (compression, native libs) - Create release-cli.yml workflow with 5-platform matrix build - Generate SHA256 checksums for all release binaries - Auto-generate release notes from commits Platforms: win-x64, win-arm64, osx-x64, osx-arm64, linux-x64 🤖 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>
1c18e58 to
e2444bd
Compare
|
@gemini-code-assist review |
There was a problem hiding this comment.
Code Review
This pull request introduces self-contained single-file executable publishing for the CLI and a corresponding GitHub Actions workflow for releases. The changes to the .csproj file correctly configure the build properties for this new publishing method, and the CHANGELOG.md is updated to reflect these new features.
My review includes two suggestions for improvement:
- In
CHANGELOG.md, I've recommended consolidating the new entries under the existing### Addedsection to adhere to the 'Keep a Changelog' standard. - In
PPDS.Cli.csproj, I've suggested restructuring the new publish properties into a conditionalPropertyGroupto make the configuration clearer and more maintainable.
Overall, the changes are well-implemented to achieve the goal of self-contained CLI publishing.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Improve csproj comment clarity for publish settings - Upgrade upload-artifact to v6 for consistency - Add validation step to ensure all 5 binaries present before release 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
Cli-v*tags are pushedChanges
Issue #53 - Self-Contained Publishing:
PPDS.Cli.csproj:EnableCompressionInSingleFile=true- reduces binary size (~38MB compressed)IncludeNativeLibrariesForSelfExtract=true- ensures native dependencies workfalsefor normal builds, enabled via-p:PublishSingleFile=trueIssue #54 - Release Workflow:
.github/workflows/release-cli.yml:Cli-v*tags (runs alongside existing NuGet publish workflow)checksums.sha256)Platforms
Test plan
dotnet publish -p:PublishSingleFile=true --self-contained -r win-x64produces ~38MB executableppds --versionoutputs correct version from MinVerCli-v1.0.0-beta.6) to verify workflowCloses #53, closes #54
🤖 Generated with Claude Code