Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions .github/workflows/publish-nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,54 @@ jobs:
runs-on: windows-latest

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
10.0.x

- name: Get version from tag
id: version
shell: bash
run: |
# Extract version from tag (v1.0.0-alpha.1 -> 1.0.0-alpha.1)
VERSION=${GITHUB_REF#refs/tags/v}
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "Publishing version: $VERSION"

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --configuration Release --no-restore
run: dotnet build --configuration Release --no-restore -p:Version=${{ steps.version.outputs.VERSION }}

- name: Pack
run: dotnet pack --configuration Release --no-build --output ./nupkgs
run: dotnet pack --configuration Release --no-build --output ./nupkgs -p:Version=${{ steps.version.outputs.VERSION }}

- name: List packages
shell: bash
run: ls -la ./nupkgs/

- name: Push to NuGet
- name: Push packages to NuGet
shell: bash
run: dotnet nuget push ./nupkgs/PPDS.Plugins.*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
for package in ./nupkgs/*.nupkg; do
echo "Pushing $package"
dotnet nuget push "$package" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate
done

- name: Push symbols to NuGet
shell: bash
run: dotnet nuget push ./nupkgs/PPDS.Plugins.*.snupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
for package in ./nupkgs/*.snupkg; do
echo "Pushing $package"
dotnet nuget push "$package" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate
done
continue-on-error: true
36 changes: 33 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
# Changelog

All notable changes to PPDS.Plugins will be documented in this file.
All notable changes to the PPDS SDK packages will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- **PPDS.Migration** - New library for high-performance Dataverse data migration
- Parallel export with configurable degree of parallelism
- Tiered import with automatic dependency resolution using Tarjan's algorithm
- Circular reference detection with deferred field processing
- CMT format compatibility (schema.xml and data.zip)
- Progress reporting with console and JSON output formats
- Security-first design: connection string redaction, no PII in logs
- DI integration via `AddDataverseMigration()` extension method
- Targets: `net8.0`, `net10.0`

- **PPDS.Migration.Cli** - New CLI tool for high-performance Dataverse data migration
- Commands: `export`, `import`, `analyze`, `migrate`
- JSON progress output for tool integration (`--json` flag)
- Support for multiple Application Users and bypass options
- Packaged as .NET global tool (`ppds-migrate`)
- Comprehensive unit test suite (98 tests)
- Targets: `net8.0`, `net10.0`

- **PPDS.Dataverse** - New package for high-performance Dataverse connectivity
- Multi-connection pool supporting multiple Application Users for load distribution
- Connection selection strategies: RoundRobin, LeastConnections, ThrottleAware
- Throttle tracking with automatic routing away from throttled connections
- Bulk operation wrappers: CreateMultiple, UpdateMultiple, UpsertMultiple, DeleteMultiple
- DI integration via `AddDataverseConnectionPool()` extension method
- Affinity cookie disabled by default for improved throughput
- Targets: `net8.0`, `net10.0`

### Changed

- Updated target frameworks: dropped `net6.0` (out of support), added `net10.0` (current LTS)
- Now targets: `net462`, `net8.0`, `net10.0`
- Updated publish workflow to support multiple packages and extract version from git tag
- Updated target frameworks for PPDS.Plugins: dropped `net6.0` (out of support), added `net10.0` (current LTS)
- PPDS.Plugins now targets: `net462`, `net8.0`, `net10.0`

## [1.1.0] - 2025-12-16

Expand Down
35 changes: 29 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,37 @@ namespace PPDS.Plugins.Enums; // Enums

---

## 🔗 Ecosystem Integration
## 🔗 Dependencies & Versioning

**This package is used by:**
- **ppds-demo** - Reference implementation
- **Customer plugin projects** - Via NuGet reference
### This Repo Produces

**Extracted by:**
- **ppds-tools** - `Get-DataversePluginRegistrations` reads these attributes
| Package | Distribution |
|---------|--------------|
| PPDS.Plugins | NuGet |
| PPDS.Dataverse | NuGet |
| PPDS.Migration.Cli | .NET Tool |

### Consumed By

| Consumer | How | Breaking Change Impact |
|----------|-----|------------------------|
| ppds-tools | Reflects on attributes | Must update reflection code |
| ppds-tools | Shells to `ppds-migrate` CLI | Must update CLI calls |
| ppds-demo | NuGet reference | Must update package reference |

### Version Sync Rules

| Rule | Details |
|------|---------|
| Major versions | Sync with ppds-tools when attributes have breaking changes |
| Minor/patch | Independent |
| Pre-release format | `-alpha.N`, `-beta.N`, `-rc.N` suffix in git tag |

### Breaking Changes Requiring Coordination

- Adding required properties to `PluginStepAttribute` or `PluginImageAttribute`
- Changing attribute property types or names
- Changing `ppds-migrate` CLI arguments or output format

---

Expand Down
75 changes: 75 additions & 0 deletions PPDS.Sdk.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPDS.Plugins.Tests", "tests\PPDS.Plugins.Tests\PPDS.Plugins.Tests.csproj", "{C7CC0394-6DE6-44C6-A6F3-EC9F5376B0D0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPDS.Dataverse", "src\PPDS.Dataverse\PPDS.Dataverse.csproj", "{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPDS.Dataverse.Tests", "tests\PPDS.Dataverse.Tests\PPDS.Dataverse.Tests.csproj", "{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPDS.Migration.Cli", "src\PPDS.Migration.Cli\PPDS.Migration.Cli.csproj", "{10DA306C-4AB2-464D-B090-3DA7B18B1C08}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPDS.Migration.Cli.Tests", "tests\PPDS.Migration.Cli.Tests\PPDS.Migration.Cli.Tests.csproj", "{45DB0E17-0355-4342-8218-2FD8FA545157}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPDS.Migration", "src\PPDS.Migration\PPDS.Migration.csproj", "{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -45,12 +55,77 @@ Global
{C7CC0394-6DE6-44C6-A6F3-EC9F5376B0D0}.Release|x64.Build.0 = Release|Any CPU
{C7CC0394-6DE6-44C6-A6F3-EC9F5376B0D0}.Release|x86.ActiveCfg = Release|Any CPU
{C7CC0394-6DE6-44C6-A6F3-EC9F5376B0D0}.Release|x86.Build.0 = Release|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Debug|x64.ActiveCfg = Debug|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Debug|x64.Build.0 = Debug|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Debug|x86.ActiveCfg = Debug|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Debug|x86.Build.0 = Debug|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Release|Any CPU.Build.0 = Release|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Release|x64.ActiveCfg = Release|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Release|x64.Build.0 = Release|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Release|x86.ActiveCfg = Release|Any CPU
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0}.Release|x86.Build.0 = Release|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Debug|x64.ActiveCfg = Debug|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Debug|x64.Build.0 = Debug|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Debug|x86.ActiveCfg = Debug|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Debug|x86.Build.0 = Debug|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Release|Any CPU.Build.0 = Release|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Release|x64.ActiveCfg = Release|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Release|x64.Build.0 = Release|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Release|x86.ActiveCfg = Release|Any CPU
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1}.Release|x86.Build.0 = Release|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Debug|x64.ActiveCfg = Debug|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Debug|x64.Build.0 = Debug|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Debug|x86.ActiveCfg = Debug|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Debug|x86.Build.0 = Debug|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Release|Any CPU.Build.0 = Release|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Release|x64.ActiveCfg = Release|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Release|x64.Build.0 = Release|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Release|x86.ActiveCfg = Release|Any CPU
{10DA306C-4AB2-464D-B090-3DA7B18B1C08}.Release|x86.Build.0 = Release|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Debug|x64.ActiveCfg = Debug|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Debug|x64.Build.0 = Debug|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Debug|x86.ActiveCfg = Debug|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Debug|x86.Build.0 = Debug|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Release|Any CPU.Build.0 = Release|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Release|x64.ActiveCfg = Release|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Release|x64.Build.0 = Release|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Release|x86.ActiveCfg = Release|Any CPU
{45DB0E17-0355-4342-8218-2FD8FA545157}.Release|x86.Build.0 = Release|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Debug|x64.ActiveCfg = Debug|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Debug|x64.Build.0 = Debug|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Debug|x86.ActiveCfg = Debug|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Debug|x86.Build.0 = Debug|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Release|Any CPU.Build.0 = Release|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Release|x64.ActiveCfg = Release|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Release|x64.Build.0 = Release|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Release|x86.ActiveCfg = Release|Any CPU
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{1E79DC81-59E1-4E4F-8B73-7F05E99F03F4} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{C7CC0394-6DE6-44C6-A6F3-EC9F5376B0D0} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{B1B07978-1CCC-4DE3-A9AD-2E0B10DF6CB0} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{738F9CC6-9EAC-4EA0-9B8B-DD6A5157A1F1} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{10DA306C-4AB2-464D-B090-3DA7B18B1C08} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{45DB0E17-0355-4342-8218-2FD8FA545157} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{1642C0BD-0B5B-476D-86EB-73BE3CD9BD67} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
EndGlobalSection
EndGlobal
Loading
Loading