diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9368ba8..7a3f5d3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -166,6 +166,11 @@ jobs:
echo "ASSEMBLY_VERSION=${{ steps.gitversion.outputs.assemblySemVer }}" >> $GITHUB_ENV
echo "FILE_VERSION=${{ steps.gitversion.outputs.assemblySemFileVer }}" >> $GITHUB_ENV
+ - name: Replace version placeholders in documentation
+ shell: pwsh
+ run: |
+ ./build/replace-version.ps1 -Version "${{ env.PACKAGE_VERSION }}" -Path "."
+
- name: Build (Release)
run: >
dotnet build JD.Efcpt.Build.sln
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7aa26d0..0b16829 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -374,6 +374,50 @@ When contributing, please update:
- **XML comments** - For all public APIs
- **Code comments** - For complex logic
+#### Version Placeholders in Documentation
+
+Documentation and README files use `PACKAGE_VERSION` as a placeholder for version numbers. This placeholder is automatically replaced with the actual version during the CI/CD build process.
+
+**When to use placeholders:**
+
+Use `PACKAGE_VERSION` in documentation for:
+- SDK version references: `Sdk="JD.Efcpt.Sdk/PACKAGE_VERSION"`
+- PackageReference version attributes: `Version="PACKAGE_VERSION"`
+- Any mention of the current package version in examples
+
+**Example:**
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+**Testing version replacement locally:**
+
+```bash
+# Dry run (shows what would be replaced)
+pwsh ./build/replace-version.ps1 -Version "1.2.3" -DryRun
+
+# Actually replace versions
+pwsh ./build/replace-version.ps1 -Version "1.2.3"
+
+# Revert changes after testing
+git checkout README.md docs/ samples/
+```
+
+**Important:** Always commit documentation with `PACKAGE_VERSION` placeholders, not actual version numbers. The CI/CD workflow automatically replaces these during the build and package process.
+
### Commit Messages
Follow conventional commits format:
diff --git a/README.md b/README.md
index 45328ca..eeb5105 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ dotnet build
### Option B: SDK Approach (Recommended)
```xml
-
+
net8.0
@@ -101,7 +101,7 @@ Automatically generate SQL scripts from your live database when JD.Efcpt.Build d
Server=...;Database=MyDb;...
-
+
```
@@ -110,7 +110,7 @@ Automatically generate SQL scripts from your live database when JD.Efcpt.Build d
```xml
-
+
```
diff --git a/build/README.md b/build/README.md
new file mode 100644
index 0000000..9be4939
--- /dev/null
+++ b/build/README.md
@@ -0,0 +1,94 @@
+# Build Scripts
+
+This directory contains build-time scripts and tools used during the CI/CD process.
+
+## replace-version.ps1
+
+PowerShell script that replaces version placeholders in documentation files with actual version numbers from GitVersion.
+
+### Purpose
+
+Ensures that all documentation (README, docs, samples) shows the current package version without requiring manual updates. This prevents version drift and user confusion.
+
+### Usage
+
+```powershell
+# Dry run - shows what would be replaced without making changes
+./replace-version.ps1 -Version "1.2.3" -DryRun
+
+# Replace versions in current directory
+./replace-version.ps1 -Version "1.2.3"
+
+# Replace versions in specific path
+./replace-version.ps1 -Version "1.2.3" -Path "../docs"
+```
+
+### Parameters
+
+- **Version** (required): The version string to use for replacement (e.g., "1.2.3")
+- **Path** (optional): The root path to search for files (defaults to current directory)
+- **DryRun** (optional): If specified, shows what would be replaced without making changes
+
+### Placeholders
+
+The script recognizes and replaces the following patterns:
+
+1. **SDK version in Sdk attribute**: `Sdk="JD.Efcpt.Sdk/PACKAGE_VERSION"`
+2. **PackageReference Version attribute**: `Version="PACKAGE_VERSION"`
+3. **Inline text placeholder**: `PACKAGE_VERSION` (word boundary)
+
+### CI/CD Integration
+
+This script is automatically executed during the release build in the CI/CD workflow:
+
+1. GitVersion calculates the version based on commits and tags
+2. The version is stored in `PACKAGE_VERSION` environment variable
+3. `replace-version.ps1` is executed to update all documentation
+4. The build continues with the updated documentation
+5. NuGet packages are created with the correct version in all docs
+
+### Testing
+
+```bash
+# Test in dry run mode
+pwsh ./build/replace-version.ps1 -Version "1.2.3" -DryRun
+
+# Test actual replacement (remember to revert after)
+pwsh ./build/replace-version.ps1 -Version "1.2.3"
+
+# Revert test changes
+git checkout README.md docs/ samples/
+```
+
+### Adding Version Placeholders
+
+When adding new documentation:
+
+1. Use `PACKAGE_VERSION` instead of hardcoded version numbers
+2. Place the placeholder where users would see version numbers
+3. Test with the script to ensure replacement works correctly
+
+**Example:**
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Notes
+
+- The script only processes markdown (.md) files
+- Files in `.git` and `node_modules` directories are excluded
+- All replacements use regex for precise pattern matching
+- The script preserves file encoding and line endings
diff --git a/build/replace-version.ps1 b/build/replace-version.ps1
new file mode 100755
index 0000000..d0d1b76
--- /dev/null
+++ b/build/replace-version.ps1
@@ -0,0 +1,112 @@
+#!/usr/bin/env pwsh
+<#
+.SYNOPSIS
+ Replaces version placeholders in documentation files.
+
+.DESCRIPTION
+ This script replaces PACKAGE_VERSION placeholders in markdown and documentation
+ files with the actual version number from GitVersion or provided as a parameter.
+
+.PARAMETER Version
+ The version string to use for replacement (e.g., "1.2.3")
+
+.PARAMETER Path
+ The root path to search for files (defaults to repository root)
+
+.PARAMETER DryRun
+ If specified, shows what would be replaced without making changes
+
+.EXAMPLE
+ ./replace-version.ps1 -Version "1.2.3"
+
+.EXAMPLE
+ ./replace-version.ps1 -Version "1.2.3" -Path "../docs" -DryRun
+#>
+
+param(
+ [Parameter(Mandatory=$true)]
+ [string]$Version,
+
+ [Parameter(Mandatory=$false)]
+ [string]$Path = ".",
+
+ [Parameter(Mandatory=$false)]
+ [switch]$DryRun
+)
+
+$ErrorActionPreference = "Stop"
+
+# Resolve the path to an absolute path for consistent handling
+$Path = [System.IO.Path]::GetFullPath($Path)
+
+Write-Host "Version Replacement Script" -ForegroundColor Cyan
+Write-Host "=========================" -ForegroundColor Cyan
+Write-Host "Version: $Version" -ForegroundColor Green
+Write-Host "Path: $Path" -ForegroundColor Green
+Write-Host "Dry Run: $DryRun" -ForegroundColor Green
+Write-Host ""
+
+# Define the patterns to replace
+$patterns = @(
+ # SDK version in Sdk attribute
+ @{
+ Pattern = 'Sdk="JD\.Efcpt\.Sdk/PACKAGE_VERSION"'
+ Replacement = "Sdk=`"JD.Efcpt.Sdk/$Version`""
+ },
+ # PackageReference Version attribute
+ @{
+ Pattern = 'Version="PACKAGE_VERSION"'
+ Replacement = "Version=`"$Version`""
+ },
+ # Inline text placeholder
+ @{
+ Pattern = '\bPACKAGE_VERSION\b'
+ Replacement = $Version
+ }
+)
+
+# Find all markdown files
+$files = Get-ChildItem -Path $Path -Recurse -Include "*.md" -File |
+ Where-Object { $_.FullName -notmatch "[\\/]\.git[\\/]" -and $_.FullName -notmatch "[\\/]node_modules[\\/]" }
+
+Write-Host "Found $($files.Count) markdown files to process" -ForegroundColor Yellow
+Write-Host ""
+
+$totalReplacements = 0
+
+foreach ($file in $files) {
+ # Use GetRelativePath for robust path handling
+ $relativePath = [System.IO.Path]::GetRelativePath($Path, $file.FullName)
+ $content = Get-Content -Path $file.FullName -Raw -ErrorAction Stop
+ $fileReplacements = 0
+
+ foreach ($patternInfo in $patterns) {
+ $matches = [regex]::Matches($content, $patternInfo.Pattern)
+ if ($matches.Count -gt 0) {
+ $content = [regex]::Replace($content, $patternInfo.Pattern, $patternInfo.Replacement)
+ $fileReplacements += $matches.Count
+ }
+ }
+
+ if ($fileReplacements -gt 0) {
+ Write-Host " $relativePath" -ForegroundColor White
+ Write-Host " -> $fileReplacements replacement(s)" -ForegroundColor Gray
+
+ if (-not $DryRun) {
+ # Preserve the original file's newline behavior
+ # Get-Content with -Raw preserves trailing newlines, so we use -NoNewline to avoid adding an extra one
+ Set-Content -Path $file.FullName -Value $content -NoNewline -ErrorAction Stop
+ }
+
+ $totalReplacements += $fileReplacements
+ }
+}
+
+Write-Host ""
+if ($DryRun) {
+ Write-Host "Dry run complete. Would have made $totalReplacements replacement(s) across $($files.Count) files." -ForegroundColor Yellow
+} else {
+ Write-Host "Successfully replaced $totalReplacements version placeholder(s)." -ForegroundColor Green
+}
+
+exit 0
diff --git a/docs/index.md b/docs/index.md
index a4bbadd..ca21593 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -31,7 +31,7 @@ dotnet build
### Option B: SDK Approach (Recommended)
```xml
-
+
net8.0
diff --git a/docs/user-guide/advanced.md b/docs/user-guide/advanced.md
index e8a1749..067794b 100644
--- a/docs/user-guide/advanced.md
+++ b/docs/user-guide/advanced.md
@@ -26,7 +26,7 @@ Create a `Directory.Build.props` file at the solution root:
-
+
```
diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md
index 3dcac5a..51feee1 100644
--- a/docs/user-guide/configuration.md
+++ b/docs/user-guide/configuration.md
@@ -449,7 +449,7 @@ Just add the package; everything is auto-discovered:
```xml
-
+
```
@@ -511,7 +511,7 @@ Include only specific tables:
-
+
```
diff --git a/docs/user-guide/connection-string-mode.md b/docs/user-guide/connection-string-mode.md
index 30e6edd..4c44cc7 100644
--- a/docs/user-guide/connection-string-mode.md
+++ b/docs/user-guide/connection-string-mode.md
@@ -320,7 +320,7 @@ Use Windows/Integrated Authentication when possible:
```xml
-
+
@@ -333,7 +333,7 @@ Use Windows/Integrated Authentication when possible:
```xml
-
+
@@ -346,7 +346,7 @@ Use Windows/Integrated Authentication when possible:
```xml
-
+
@@ -359,7 +359,7 @@ Use Windows/Integrated Authentication when possible:
```xml
-
+
@@ -380,7 +380,7 @@ Complete example for an ASP.NET Core project:
-
+
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index 98ab2c9..31be145 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -28,7 +28,7 @@ The SDK approach provides the cleanest project files.
Use the SDK in your project file with the version specified inline:
```xml
-
+
net8.0
enable
@@ -56,7 +56,7 @@ Add JD.Efcpt.Build to your application project (the project that should contain
```xml
-
+
```
diff --git a/docs/user-guide/sdk.md b/docs/user-guide/sdk.md
index 3b7e5d8..9e0605b 100644
--- a/docs/user-guide/sdk.md
+++ b/docs/user-guide/sdk.md
@@ -30,7 +30,7 @@ Choose JD.Efcpt.Build (PackageReference) when:
Use the SDK in your project file with the version specified inline:
```xml
-
+
net8.0
enable
@@ -147,7 +147,7 @@ The SDK works with all SQL project types:
The SDK also supports connection string mode for direct database reverse engineering:
```xml
-
+
net8.0
Server=localhost;Database=MyDb;Integrated Security=True;
@@ -166,7 +166,7 @@ See [Connection String Mode](connection-string-mode.md) for details.
The SDK supports multi-targeting just like the standard .NET SDK:
```xml
-
+
net8.0;net9.0;net10.0
@@ -180,7 +180,7 @@ Model generation happens once and is shared across all target frameworks.
| Feature | JD.Efcpt.Sdk | JD.Efcpt.Build (PackageReference) |
|---------|--------------|-----------------------------------|
-| Project file | `Sdk="JD.Efcpt.Sdk/1.0.0"` | `` |
+| Project file | `Sdk="JD.Efcpt.Sdk/PACKAGE_VERSION"` | `` |
| Version location | Sdk attribute or `global.json` | `.csproj` or Directory.Build.props |
| Setup complexity | Lower | Slightly higher |
| Existing projects | Requires SDK change | Drop-in addition |
@@ -279,7 +279,7 @@ If you prefer using tools like `dotnet outdated` for version management, use `JD
If you see an error like "The SDK 'JD.Efcpt.Sdk' could not be resolved":
-1. Verify the version is specified (either inline `Sdk="JD.Efcpt.Sdk/1.0.0"` or in `global.json`)
+1. Verify the version is specified (either inline `Sdk="JD.Efcpt.Sdk/PACKAGE_VERSION"` or in `global.json`)
2. Check that the version matches an available package version
3. Ensure the package is available in your NuGet sources
@@ -295,7 +295,7 @@ If the SQL project isn't building:
If you need different SDK versions for different projects:
-1. Specify the version inline in each project file: `Sdk="JD.Efcpt.Sdk/1.0.0"`
+1. Specify the version inline in each project file: `Sdk="JD.Efcpt.Sdk/PACKAGE_VERSION"`
2. Or use JD.Efcpt.Build via PackageReference instead
## Next Steps
diff --git a/docs/user-guide/split-outputs.md b/docs/user-guide/split-outputs.md
index e40a11b..d843db1 100644
--- a/docs/user-guide/split-outputs.md
+++ b/docs/user-guide/split-outputs.md
@@ -199,7 +199,7 @@ Edit `MyProject.Models/MyProject.Models.csproj`:
-
+
@@ -246,7 +246,7 @@ Edit `MyProject.Data/MyProject.Data.csproj`:
-
+
diff --git a/docs/user-guide/use-cases/enterprise.md b/docs/user-guide/use-cases/enterprise.md
index d212bc0..1cfa7ad 100644
--- a/docs/user-guide/use-cases/enterprise.md
+++ b/docs/user-guide/use-cases/enterprise.md
@@ -53,7 +53,7 @@ dotnet new efcptbuild -n MyProject -o src/MyProject
```xml
-
+
```
@@ -63,7 +63,7 @@ dotnet new efcptbuild -n MyProject -o src/MyProject
```xml
-
+
```
diff --git a/samples/README.md b/samples/README.md
index e84e9ca..df875b1 100644
--- a/samples/README.md
+++ b/samples/README.md
@@ -80,7 +80,7 @@ sdk-zero-config/
│ ├── DatabaseProject.csproj # Microsoft.Build.Sql project
│ └── dbo/Tables/*.sql
└── EntityFrameworkCoreProject/
- └── EntityFrameworkCoreProject.csproj # Uses JD.Efcpt.Sdk/1.0.0
+ └── EntityFrameworkCoreProject.csproj # Uses JD.Efcpt.Sdk/PACKAGE_VERSION
```
**Key Features:**
@@ -91,7 +91,7 @@ sdk-zero-config/
**Project File:**
```xml
-
+
net8.0
diff --git a/samples/msbuild-sdk-sql-proj-generation/README.md b/samples/msbuild-sdk-sql-proj-generation/README.md
index a4e77c6..2a1cb0d 100644
--- a/samples/msbuild-sdk-sql-proj-generation/README.md
+++ b/samples/msbuild-sdk-sql-proj-generation/README.md
@@ -55,7 +55,7 @@ In a real project, you would consume JD.Efcpt.Build as a NuGet package:
```xml
-
+
```
diff --git a/samples/simple-generation/README.md b/samples/simple-generation/README.md
index d803366..f57a574 100644
--- a/samples/simple-generation/README.md
+++ b/samples/simple-generation/README.md
@@ -40,7 +40,7 @@ In a real project, you would consume JD.Efcpt.Build as a NuGet package:
```xml
-
+
```
diff --git a/samples/split-data-and-models-between-multiple-projects/README.md b/samples/split-data-and-models-between-multiple-projects/README.md
index 0428ad5..1432cf0 100644
--- a/samples/split-data-and-models-between-multiple-projects/README.md
+++ b/samples/split-data-and-models-between-multiple-projects/README.md
@@ -131,7 +131,7 @@ In a real project, you would consume JD.Efcpt.Build as a NuGet package:
```xml
-
+
```