Skip to content

Commit 775fa11

Browse files
committed
Refine SqlClient pack fallback and nuspec version flow
- Move Abstractions/Logging version fallback into SqlClient pack target - Reuse shared sibling project paths and DOTNET_HOST_PATH - Document intermediate nuspec generation and sibling version evaluation - Pass NuspecVersion through shared nuget pack pipeline properties
1 parent d334db7 commit 775fa11

4 files changed

Lines changed: 101 additions & 85 deletions

File tree

build.proj

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -535,60 +535,7 @@
535535
<Output TaskParameter="ConsoleOutput" PropertyName="CommitId" />
536536
</Exec>
537537

538-
<Error Text="PackSqlClient requires PackageVersionAbstractions. Specify -p:PackageVersionAbstractions=&lt;version&gt;."
539-
Condition="'$(PackageVersionAbstractions)' == ''" />
540-
<Error Text="PackSqlClient requires PackageVersionLogging. Specify -p:PackageVersionLogging=&lt;version&gt;."
541-
Condition="'$(PackageVersionLogging)' == ''" />
542-
543-
<!-- Evaluate AbstractionsPackageVersion from project if not provided -->
544-
<PropertyGroup Condition="'$(PackageVersionAbstractions)' == ''">
545-
<GetAbstractionsPackageVersionCommand>
546-
"$(DotnetPath)dotnet" msbuild "$(AbstractionsProjectPath)"
547-
-nologo
548-
-verbosity:quiet
549-
-getProperty:AbstractionsPackageVersion
550-
$(BuildNumberArgument)
551-
$(BuildSuffixArgument)
552-
</GetAbstractionsPackageVersionCommand>
553-
<GetAbstractionsPackageVersionCommand>$([System.Text.RegularExpressions.Regex]::Replace($(GetAbstractionsPackageVersionCommand), "\s+", " "))</GetAbstractionsPackageVersionCommand>
554-
</PropertyGroup>
555-
<Message Text=">>> Evaluating Abstractions package version via command: $(GetAbstractionsPackageVersionCommand)"
556-
Condition="'$(PackageVersionAbstractions)' == ''" />
557-
<Exec ConsoleToMsBuild="true" Command="$(GetAbstractionsPackageVersionCommand)"
558-
Condition="'$(PackageVersionAbstractions)' == ''">
559-
<Output TaskParameter="ConsoleOutput" PropertyName="PackageVersionAbstractions" />
560-
</Exec>
561-
<Error Text="Failed to evaluate AbstractionsPackageVersion for PackSqlClient."
562-
Condition="'$(PackageVersionAbstractions)' == ''" />
563-
564-
<!-- Evaluate LoggingPackageVersion from project if not provided -->
565-
<PropertyGroup Condition="'$(PackageVersionLogging)' == ''">
566-
<GetLoggingPackageVersionCommand>
567-
"$(DotnetPath)dotnet" msbuild "$(LoggingProjectPath)"
568-
-nologo
569-
-verbosity:quiet
570-
-getProperty:LoggingPackageVersion
571-
$(BuildNumberArgument)
572-
$(BuildSuffixArgument)
573-
</GetLoggingPackageVersionCommand>
574-
<GetLoggingPackageVersionCommand>$([System.Text.RegularExpressions.Regex]::Replace($(GetLoggingPackageVersionCommand), "\s+", " "))</GetLoggingPackageVersionCommand>
575-
</PropertyGroup>
576-
<Message Text=">>> Evaluating Logging package version via command: $(GetLoggingPackageVersionCommand)"
577-
Condition="'$(PackageVersionLogging)' == ''" />
578-
<Exec ConsoleToMsBuild="true" Command="$(GetLoggingPackageVersionCommand)"
579-
Condition="'$(PackageVersionLogging)' == ''">
580-
<Output TaskParameter="ConsoleOutput" PropertyName="PackageVersionLogging" />
581-
</Exec>
582-
<Error Text="Failed to evaluate LoggingPackageVersion for PackSqlClient."
583-
Condition="'$(PackageVersionLogging)' == ''" />
584-
585538
<PropertyGroup>
586-
<<<<<<< HEAD
587-
<_EvaluatedSqlClientPackageVersion>$([System.Text.RegularExpressions.Regex]::Replace($(_EvaluatedSqlClientPackageVersion), "\s", ""))</_EvaluatedSqlClientPackageVersion>
588-
<PackageVersionAbstractions>$([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionAbstractions), "\s", ""))</PackageVersionAbstractions>
589-
<PackageVersionLogging>$([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionLogging), "\s", ""))</PackageVersionLogging>
590-
=======
591-
>>>>>>> a31e7e8fc (Simplify SqlClient pack version flow)
592539
<CommitId>$([System.Text.RegularExpressions.Regex]::Replace($(CommitId), "\s", ""))</CommitId>
593540
<DotnetCommand>
594541
"$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)"

eng/pipelines/common/templates/steps/generate-nuget-package-step.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ steps:
7070
${{parameters.nuspecPath}}
7171
-Version ${{parameters.packageVersion}}
7272
-OutputDirectory ${{parameters.outputDirectory}}
73-
-properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};${{parameters.properties}}"
73+
-properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};NuspecVersion=${{parameters.packageVersion}};${{parameters.properties}}"
7474
${{else }}:
7575
arguments: >-
7676
pack
7777
${{parameters.nuspecPath}}
7878
-Version ${{parameters.packageVersion}}
7979
-OutputDirectory ${{parameters.outputDirectory}}
80-
-properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};${{parameters.properties}}"
80+
-properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};NuspecVersion=${{parameters.packageVersion}};${{parameters.properties}}"

src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,41 +79,90 @@
7979
<!-- NuGet Package Config ============================================ -->
8080
<!-- Pack design notes: ./sqlclient-dotnet-pack.md -->
8181
<PropertyGroup>
82+
83+
<!-- Spec and proj paths. -->
8284
<SqlClientPackNuspecTemplatePath Condition="'$(SqlClientPackNuspecTemplatePath)' == ''">$(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec</SqlClientPackNuspecTemplatePath>
8385
<SqlClientPackNuspecGeneratedPath Condition="'$(SqlClientPackNuspecGeneratedPath)' == ''">$(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec</SqlClientPackNuspecGeneratedPath>
86+
<AbstractionsProjectPath>$(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj</AbstractionsProjectPath>
87+
<LoggingProjectPath>$(RepoRoot)/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj</LoggingProjectPath>
8488

85-
<NuspecVersion Condition="'$(NuspecVersion)' == ''">$(Version)</NuspecVersion>
89+
<!-- Properties used by dotnet pack. -->
8690
<NuspecFile Condition="'$(NuspecFile)' == ''">$(SqlClientPackNuspecTemplatePath)</NuspecFile>
8791
<NuspecBasePath Condition="'$(NuspecBasePath)' == ''">$([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))</NuspecBasePath>
92+
<NuspecVersion Condition="'$(NuspecVersion)' == ''">$(Version)</NuspecVersion>
93+
<NuspecProperties Condition="'$(NuspecProperties)' == ''">COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)</NuspecProperties>
8894
<IncludeSymbols Condition="'$(IncludeSymbols)' == ''">true</IncludeSymbols>
8995
<SymbolPackageFormat Condition="'$(SymbolPackageFormat)' == ''">snupkg</SymbolPackageFormat>
9096
<SuppressDependenciesWhenPacking Condition="'$(SuppressDependenciesWhenPacking)' == ''">true</SuppressDependenciesWhenPacking>
91-
92-
<NuspecProperties Condition="'$(NuspecProperties)' == ''">COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)</NuspecProperties>
9397
</PropertyGroup>
9498

9599
<!--
96100
SDK pack does not reliably substitute dependency version tokens in this nuspec flow.
97101
We materialize those dependency versions into an intermediate nuspec before PackTask runs.
102+
103+
Why an intermediate nuspec is generated:
104+
* The source nuspec keeps dependency versions as tokens to stay template-driven.
105+
* During SDK-style packing, dependency token substitution is not consistently applied in this flow.
106+
* Expanding tokens up front guarantees deterministic dependency versions in the final package metadata.
107+
108+
Why sibling package versions are evaluated here:
109+
* Pack entrypoints may call this project directly and omit Abstractions/Logging version overrides.
110+
* Those versions must still align with sibling projects' versioning rules (BuildNumber/BuildSuffix and defaults).
111+
* Querying each sibling project for its computed package version preserves a single source of version truth.
98112
-->
99113
<Target Name="PrepareSqlClientPackNuspec"
100114
BeforeTargets="GenerateNuspec"
101115
Condition="'$(NuspecFile)' == '$(SqlClientPackNuspecTemplatePath)'">
102-
<Error Text="PrepareSqlClientPackNuspec requires AbstractionsPackageVersion. Specify -p:AbstractionsPackageVersion=&lt;version&gt; (or -p:PackageVersionAbstractions=&lt;version&gt; when invoking build.proj)."
103-
Condition="'$(AbstractionsPackageVersion)' == ''" />
104-
<Error Text="PrepareSqlClientPackNuspec requires LoggingPackageVersion. Specify -p:LoggingPackageVersion=&lt;version&gt; (or -p:PackageVersionLogging=&lt;version&gt; when invoking build.proj)."
105-
Condition="'$(LoggingPackageVersion)' == ''" />
106-
<Error Text="PrepareSqlClientPackNuspec requires NuspecVersion. Specify -p:NuspecVersion=&lt;version&gt;."
107-
Condition="'$(NuspecVersion)' == ''" />
108116

117+
<!-- Calculate AbstractionsPackageVersion if not already set. -->
118+
<PropertyGroup Condition="'$(AbstractionsPackageVersion)' == ''">
119+
<GetAbstractionsPackageVersionCommand>
120+
"$(DOTNET_HOST_PATH)" msbuild "$(AbstractionsProjectPath)"
121+
-nologo
122+
-verbosity:quiet
123+
-getProperty:AbstractionsPackageVersion
124+
-p:BuildNumber=$(BuildNumber)
125+
-p:BuildSuffix=$(BuildSuffix)
126+
</GetAbstractionsPackageVersionCommand>
127+
<GetAbstractionsPackageVersionCommand>$([System.Text.RegularExpressions.Regex]::Replace($(GetAbstractionsPackageVersionCommand), "\s+", " "))</GetAbstractionsPackageVersionCommand>
128+
</PropertyGroup>
129+
<Exec ConsoleToMsBuild="true" Command="$(GetAbstractionsPackageVersionCommand)"
130+
Condition="'$(AbstractionsPackageVersion)' == ''">
131+
<Output TaskParameter="ConsoleOutput" PropertyName="AbstractionsPackageVersion" />
132+
</Exec>
133+
<PropertyGroup Condition="'$(GetAbstractionsPackageVersionCommand)' != ''">
134+
<AbstractionsPackageVersion>$([System.Text.RegularExpressions.Regex]::Replace($(AbstractionsPackageVersion), "\s", ""))</AbstractionsPackageVersion>
135+
</PropertyGroup>
136+
137+
<!-- Calculate LoggingPackageVersion if not already set. -->
138+
<PropertyGroup Condition="'$(LoggingPackageVersion)' == ''">
139+
<GetLoggingPackageVersionCommand>
140+
"$(DOTNET_HOST_PATH)" msbuild "$(LoggingProjectPath)"
141+
-nologo
142+
-verbosity:quiet
143+
-getProperty:LoggingPackageVersion
144+
-p:BuildNumber=$(BuildNumber)
145+
-p:BuildSuffix=$(BuildSuffix)
146+
</GetLoggingPackageVersionCommand>
147+
<GetLoggingPackageVersionCommand>$([System.Text.RegularExpressions.Regex]::Replace($(GetLoggingPackageVersionCommand), "\s+", " "))</GetLoggingPackageVersionCommand>
148+
</PropertyGroup>
149+
<Exec ConsoleToMsBuild="true" Command="$(GetLoggingPackageVersionCommand)"
150+
Condition="'$(LoggingPackageVersion)' == ''">
151+
<Output TaskParameter="ConsoleOutput" PropertyName="LoggingPackageVersion" />
152+
</Exec>
153+
<PropertyGroup Condition="'$(GetLoggingPackageVersionCommand)' != ''">
154+
<LoggingPackageVersion>$([System.Text.RegularExpressions.Regex]::Replace($(LoggingPackageVersion), "\s", ""))</LoggingPackageVersion>
155+
</PropertyGroup>
156+
157+
<!-- Expand the SqlClientPackNuspec template with the computed package versions. -->
109158
<PropertyGroup>
110159
<_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('$NuspecVersion$','$(NuspecVersion)'))</_SqlClientPackNuspecExpandedText>
111160
</PropertyGroup>
112-
113161
<WriteLinesToFile File="$(SqlClientPackNuspecGeneratedPath)"
114162
Lines="$(_SqlClientPackNuspecExpandedText)"
115163
Overwrite="true" />
116164

165+
<!-- Set the NuspecFile property to the generated nuspec file. -->
117166
<PropertyGroup>
118167
<NuspecFile>$(SqlClientPackNuspecGeneratedPath)</NuspecFile>
119168
</PropertyGroup>
@@ -158,15 +207,15 @@
158207
<!-- References ====================================================== -->
159208
<!-- Reference to Abstractions -->
160209
<ItemGroup>
161-
<ProjectReference Include="$(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj"
210+
<ProjectReference Include="$(AbstractionsProjectPath)"
162211
Condition="'$(ReferenceType)' != 'Package'" />
163212
<PackageReference Include="Microsoft.Data.SqlClient.Extensions.Abstractions"
164213
Condition="'$(ReferenceType)' == 'Package'" />
165214
</ItemGroup>
166215

167216
<!-- Reference to Logging -->
168217
<ItemGroup>
169-
<ProjectReference Include="$(RepoRoot)/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj"
218+
<ProjectReference Include="$(LoggingProjectPath)"
170219
Condition="'$(ReferenceType)' != 'Package'" />
171220
<PackageReference Include="Microsoft.Data.SqlClient.Internal.Logging"
172221
Condition="'$(ReferenceType)' == 'Package'" />

src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,27 @@ This document describes how the SqlClient package is produced with dotnet pack i
1313
Run from repo root:
1414

1515
```bash
16-
dotnet build build.proj -t:PackSqlClient -p:Configuration=Release -p:ReferenceType=Project -p:PackBuild=false -p:PackageVersionAbstractions=<version> -p:PackageVersionLogging=<version>
16+
dotnet build -t:PackSqlClient -p:Configuration=Release -p:ReferenceType=Project -p:PackBuild=false
1717
```
1818

19-
Required pack inputs:
19+
Optional version override inputs:
2020

2121
- `PackageVersionAbstractions`
2222
- `PackageVersionLogging`
2323

24-
These are required because dependency versions are injected into the SqlClient nuspec at pack time.
24+
These can still be passed to override sibling package versions, but they are no longer required. If
25+
omitted, `PrepareSqlClientPackNuspec` evaluates the computed `AbstractionsPackageVersion` and
26+
`LoggingPackageVersion` from the sibling projects using the current `BuildNumber` and `BuildSuffix`
27+
context.
2528

2629
## Why a generated nuspec is used
2730

28-
SqlClient packaging still relies on `tools/specs/Microsoft.Data.SqlClient.nuspec` for file mapping and dependency groups (`lib/*`, `ref/*`, `runtimes/*`, resources, metadata).
31+
SqlClient packaging still relies on `tools/specs/Microsoft.Data.SqlClient.nuspec` for file mapping
32+
and dependency groups (`lib/*`, `ref/*`, `runtimes/*`, resources, metadata).
2933

30-
In this flow, SDK pack token substitution is reliable for general nuspec properties, but dependency version token replacement in the nuspec dependency section can fail. To avoid that, the project generates an intermediate nuspec before `GenerateNuspec`:
34+
In this flow, SDK pack token substitution is reliable for general nuspec properties, but dependency
35+
version token replacement in the nuspec dependency section can fail. To avoid that, the project
36+
generates an intermediate nuspec before `GenerateNuspec`:
3137

3238
- Template nuspec: `tools/specs/Microsoft.Data.SqlClient.nuspec`
3339
- Generated nuspec: `obj/Microsoft.Data.SqlClient.pack.nuspec`
@@ -40,40 +46,53 @@ This keeps layout parity with the existing nuspec while using `dotnet pack` end-
4046

4147
## Known SDK behavior and repro
4248

43-
Passing all tokens through `NuspecProperties` looks correct, but this command fails on SDK `10.0.107`:
49+
Passing all tokens through `NuspecProperties` looks correct, but this command fails on SDK
50+
`10.0.107`:
4451

4552
```bash
4653
dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:NuspecFile=<repo>/tools/specs/Microsoft.Data.SqlClient.nuspec -p:NuspecBasePath=<repo>/tools/specs -p:NuspecProperties="COMMITID=abc;Configuration=Debug;ReferenceType=Project;AbstractionsPackageVersion=1.0.0-dev;LoggingPackageVersion=1.0.0-dev" -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=<repo>/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
4754
```
4855

49-
To reproduce this failure in the current branch and exercise the workaround, also pass the required MSBuild properties:
56+
To reproduce this failure in the current branch and exercise the workaround, you can still pass the
57+
direct project properties explicitly:
5058

5159
```bash
5260
dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:AbstractionsPackageVersion=1.0.0-dev -p:LoggingPackageVersion=1.0.0-dev -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=<repo>/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
5361
```
5462

55-
Note: `PackageVersionAbstractions` and `PackageVersionLogging` are `build.proj` entrypoint properties and are translated to `AbstractionsPackageVersion` and `LoggingPackageVersion` for direct project pack.
63+
Note: `PackageVersionAbstractions` and `PackageVersionLogging` are `build.proj` entrypoint
64+
properties. Direct project pack can instead pass `AbstractionsPackageVersion` and
65+
`LoggingPackageVersion`, or omit them and let the project evaluate sibling defaults.
5666

57-
The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec, bypassing the SDK's substitution bug.
67+
The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec,
68+
bypassing the SDK's substitution bug.
5869

5970
Observed error (without workaround):
6071

6172
- `An error occurred while trying to parse the value '' of property 'dependencies' in the manifest file.`
6273
- `'' is not a valid version string.`
6374

64-
The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by `PrepareSqlClientPackNuspec`.
75+
The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by
76+
`PrepareSqlClientPackNuspec`.
6577

6678
## Related upstream issues
6779

68-
The behavior appears related to long-standing SDK/NuGet pack substitution issues when using nuspec files with `dotnet pack`:
80+
The behavior appears related to long-standing SDK/NuGet pack substitution issues when using nuspec
81+
files with `dotnet pack`:
6982

70-
- [dotnet/sdk#15482](https://github.com/dotnet/sdk/issues/15482) (open): multiple `NuspecProperties` values, only first substituted and others become empty.
71-
- [dotnet/sdk#29661](https://github.com/dotnet/sdk/issues/29661) (closed as duplicate): same symptom on SDK 6.0.404.
72-
- [dotnet/sdk#10516](https://github.com/dotnet/sdk/issues/10516) (closed): `dotnet pack` with nuspec not filling tokens like `$version$`.
73-
- [dotnet/sdk#15407](https://github.com/dotnet/sdk/issues/15407) (closed): `$configuration$` empty when packing with nuspec.
74-
- [dotnet/sdk#16816](https://github.com/dotnet/sdk/issues/16816) (closed): nuspec token/path behavior inconsistencies with `dotnet pack`.
83+
- [dotnet/sdk#15482](https://github.com/dotnet/sdk/issues/15482) (open): multiple `NuspecProperties`
84+
values, only first substituted and others become empty.
85+
- [dotnet/sdk#29661](https://github.com/dotnet/sdk/issues/29661) (closed as duplicate): same symptom
86+
on SDK 6.0.404.
87+
- [dotnet/sdk#10516](https://github.com/dotnet/sdk/issues/10516) (closed): `dotnet pack` with nuspec
88+
not filling tokens like `$version$`.
89+
- [dotnet/sdk#15407](https://github.com/dotnet/sdk/issues/15407) (closed): `$configuration$` empty
90+
when packing with nuspec.
91+
- [dotnet/sdk#16816](https://github.com/dotnet/sdk/issues/16816) (closed): nuspec token/path
92+
behavior inconsistencies with `dotnet pack`.
7593

76-
These links do not prove this exact dependency-token timing path is identical, but they strongly indicate related substitution behavior in the same pack surface area.
94+
These links do not prove this exact dependency-token timing path is identical, but they strongly
95+
indicate related substitution behavior in the same pack surface area.
7796

7897
## Where pack properties are defined
7998

@@ -87,7 +106,8 @@ The `build.proj` target passes dynamic values only:
87106
- `PackageOutputPath`
88107
- plus standard version/reference-type arguments
89108

90-
Note: `NuspecVersion` is derived from `$(Version)` by SDK defaults and does not need to be explicitly passed.
109+
Note: `NuspecVersion` is derived from `$(Version)` by SDK defaults and does not need to be
110+
explicitly passed.
91111

92112
## Outputs
93113

0 commit comments

Comments
 (0)