Skip to content

feat: Self-contained CLI publishing and release workflow#108

Merged
joshsmithxrm merged 3 commits intomainfrom
jovial-snyder
Jan 3, 2026
Merged

feat: Self-contained CLI publishing and release workflow#108
joshsmithxrm merged 3 commits intomainfrom
jovial-snyder

Conversation

@joshsmithxrm
Copy link
Copy Markdown
Owner

Summary

  • Configure CLI to publish as self-contained single-file executables for all major platforms
  • Add GitHub Actions workflow to build and release binaries when Cli-v* tags are pushed

Changes

Issue #53 - Self-Contained Publishing:

  • Added publish settings to PPDS.Cli.csproj:
    • EnableCompressionInSingleFile=true - reduces binary size (~38MB compressed)
    • IncludeNativeLibrariesForSelfExtract=true - ensures native dependencies work
    • Defaults to false for normal builds, enabled via -p:PublishSingleFile=true

Issue #54 - Release Workflow:

  • Created .github/workflows/release-cli.yml:
    • Triggers on Cli-v* tags (runs alongside existing NuGet publish workflow)
    • Parallel matrix build for 5 platforms: win-x64, win-arm64, osx-x64, osx-arm64, linux-x64
    • Uses net8.0 (LTS) for self-contained binaries
    • Generates SHA256 checksums (checksums.sha256)
    • Creates GitHub Release with auto-generated release notes

Platforms

Runtime ID Binary Name
win-x64 ppds-win-x64.exe
win-arm64 ppds-win-arm64.exe
osx-x64 ppds-osx-x64
osx-arm64 ppds-osx-arm64
linux-x64 ppds-linux-x64

Test plan

  • Build succeeds with new csproj settings
  • dotnet publish -p:PublishSingleFile=true --self-contained -r win-x64 produces ~38MB executable
  • ppds --version outputs correct version from MinVer
  • All unit tests pass
  • After merge, create test tag (e.g., Cli-v1.0.0-beta.6) to verify workflow

Closes #53, closes #54

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings January 3, 2026 08:58
@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 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

  • Self-Contained CLI Publishing: The CLI is now configured to publish as self-contained single-file executables for all major platforms (Windows x64/ARM64, macOS x64/ARM64, Linux x64). This significantly simplifies distribution and execution by bundling all necessary dependencies into a single binary.
  • Automated Release Workflow: A new GitHub Actions workflow (release-cli.yml) has been added. This workflow automatically builds and releases the self-contained binaries for all supported platforms to GitHub Releases whenever a Cli-v* tag is pushed. It also generates SHA256 checksums for integrity verification.
  • Secure Credential Storage: Sensitive authentication details (client secrets, certificate passwords, user passwords) are no longer stored directly within the AuthProfile objects. Instead, a new SecureCredentialStore has been introduced, utilizing platform-native secure storage mechanisms (DPAPI on Windows, Keychain on macOS, libsecret on Linux) to protect these credentials.
  • Auth Profile Schema Update: The AuthProfile and ProfileCollection schemas have been updated to version 2. This includes changing ProfileCollection to store profiles in a list instead of a dictionary, tracking the active profile by name instead of index, and removing sensitive fields from AuthProfile itself. A migration mechanism is in place to detect and delete old v1 profile files, requiring users to re-authenticate.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release-cli.yml
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 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 ISecureCredentialStore and SecureCredentialStore implementation: A new interface and class are added to handle secure storage, retrieval, and removal of StoredCredential objects, 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.
  • AuthProfile simplification: The AuthProfile class no longer contains Password, ClientSecret, or CertificatePassword properties, reducing its responsibility and improving security by separating profile metadata from sensitive credentials. An Authority property was added to AuthProfile, and the EnvironmentInfo class was simplified by removing its Id property.
  • CredentialProviderFactory updates: The factory now includes an asynchronous CreateAsync method that can utilize the ISecureCredentialStore to fetch secrets for ClientSecret, CertificateFile, and UsernamePassword authentication methods. A synchronous Create overload is also provided but explicitly disallows secure store lookups for UsernamePassword and falls back to environment variables for ClientSecret. Helper methods were added to encapsulate secret retrieval logic, and the previous ValidateRequiredFields method was removed, with validation now occurring within specific provider FromProfile methods. Review comments highlighted that federated credential providers (GitHubFederated, AzureDevOpsFederated) were using null-suppressing operators (!) without proper validation for ApplicationId and TenantId, recommending explicit ArgumentException throws for missing required fields.
  • Profile Store Schema Migration (v1 to v2): The ProfileCollection and ProfileStore were updated to a new schema (version 2). This involves changing ProfileCollection from using a dictionary of profiles keyed by index to a list of profiles, and tracking the active profile by name instead of index. The ProfileStore now 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 create command: The ppds auth create command was updated to store secrets in the new SecureCredentialStore instead 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.

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 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.

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

joshsmithxrm and others added 2 commits January 3, 2026 04:40
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>
@joshsmithxrm
Copy link
Copy Markdown
Owner Author

@gemini-code-assist review

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 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:

  1. In CHANGELOG.md, I've recommended consolidating the new entries under the existing ### Added section to adhere to the 'Keep a Changelog' standard.
  2. In PPDS.Cli.csproj, I've suggested restructuring the new publish properties into a conditional PropertyGroup to make the configuration clearer and more maintainable.

Overall, the changes are well-implemented to achieve the goal of self-contained CLI publishing.

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

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>
@joshsmithxrm joshsmithxrm merged commit beb1cef into main Jan 3, 2026
8 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in PPDS Roadmap Jan 3, 2026
@joshsmithxrm joshsmithxrm deleted the jovial-snyder branch January 3, 2026 18:03
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.

Add GitHub release workflow for CLI binaries Add self-contained single-file publish for all platforms

3 participants