Skip to content

Commit 7b004ea

Browse files
Add documentation for NuGet package management
Added a comprehensive guide on managing preview and stable NuGet packages in the Codebreaker Backend solution. The document includes an overview of the dual-pipeline approach, package versioning strategy, GitHub Actions workflows, deployment targets, and best practices. Detailed instructions for workflow execution, troubleshooting, and integration with development workflows are provided. Future enhancements such as automated release notes and vulnerability scanning are outlined. Examples, YAML configurations, and XML snippets are included for clarity.
1 parent b430f2b commit 7b004ea

1 file changed

Lines changed: 336 additions & 0 deletions

File tree

docs/nuget-package-management.md

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
# NuGet Package Management: Preview and Stable Builds
2+
3+
This document outlines the best practices for managing preview and stable NuGet package builds in the Codebreaker Backend solution, including GitHub Actions workflows and deployment strategies.
4+
5+
## Overview
6+
7+
The Codebreaker Backend solution uses a dual-pipeline approach for NuGet package management:
8+
9+
- **Preview Builds**: Automatically triggered on code changes, deployed to Azure DevOps Artifacts
10+
- **Stable Builds**: Manually triggered, deployed to both Azure DevOps Artifacts and public NuGet Gallery
11+
12+
## Architecture
13+
14+
```
15+
Code Changes (main branch)
16+
17+
Preview Build Pipeline
18+
↓ (automatic)
19+
Azure DevOps Artifacts (preview)
20+
↓ (manual approval)
21+
Stable Build Pipeline
22+
↓ (automatic)
23+
Azure DevOps Artifacts (stable) + NuGet Gallery
24+
```
25+
26+
## Package Versioning Strategy
27+
28+
### Preview Builds
29+
- **Format**: `{base-version}-preview.1.{build-number + offset}`
30+
- **Example**: `3.8.0-preview.1.15` (if build number is 5 and offset is 10)
31+
- **Trigger**: Automatic on push to main branch with changes in specific paths
32+
- **Retention**: 3 days
33+
34+
### Stable Builds
35+
- **Format**: `{base-version}` (no suffix)
36+
- **Example**: `3.8.0`
37+
- **Trigger**: Manual workflow dispatch
38+
- **Retention**: 30 days
39+
40+
## Central Package Management
41+
42+
The solution uses Central Package Management with `Directory.Packages.props`:
43+
44+
```xml
45+
<PropertyGroup>
46+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
47+
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
48+
</PropertyGroup>
49+
```
50+
51+
### Key Points:
52+
-**DO**: Add package versions to `src/Directory.Packages.props`
53+
-**DON'T**: Specify versions in individual `.csproj` files
54+
- ⚠️ **Warning**: Build will fail if PackageReference has version but package not in Directory.Packages.props
55+
56+
## GitHub Actions Workflows
57+
58+
### 1. Preview Build Workflows
59+
60+
Each library has a dedicated preview workflow (e.g., `codebreaker-lib-sqlserver.yml`):
61+
62+
```yaml
63+
name: Sql Server data lib
64+
65+
on:
66+
push:
67+
branches: [ main ]
68+
paths:
69+
- 'src/services/common/Codebreaker.Data.SqlServer/**'
70+
workflow_dispatch:
71+
72+
jobs:
73+
build:
74+
uses: CodebreakerApp/Codebreaker.Backend/.github/workflows/createnuget-withbuildnumber.yml@main
75+
with:
76+
version-suffix: preview.1.
77+
version-number: ${{ github.run_number }}
78+
version-offset: 10
79+
solutionfile-path: src/Codebreaker.Backend.SqlServer.slnx
80+
projectfile-path: src/services/common/Codebreaker.Data.SqlServer/Codebreaker.Data.SqlServer.csproj
81+
dotnet-version: '9.0.x'
82+
artifact-name: codebreaker-sqlserver
83+
branch-name: main
84+
85+
publishdevops:
86+
uses: CodebreakerApp/Codebreaker.Backend/.github/workflows/publishnuget-azuredevops.yml@main
87+
needs: build
88+
with:
89+
artifact-name: codebreaker-sqlserver
90+
secrets: inherit
91+
```
92+
93+
### 2. Stable Build Workflows
94+
95+
Each library has a stable workflow (e.g., `codebreaker-lib-sqlserver-stable.yml`):
96+
97+
```yaml
98+
name: SqlServer stable lib
99+
100+
on:
101+
workflow_dispatch:
102+
103+
jobs:
104+
build:
105+
runs-on: ubuntu-latest
106+
steps:
107+
- name: Checkout to the branch
108+
uses: actions/checkout@v5
109+
with:
110+
ref: main
111+
112+
- name: Setup .NET
113+
uses: actions/setup-dotnet@v5
114+
with:
115+
dotnet-version: 9.0.x
116+
117+
- name: Build the library
118+
run: dotnet build -c Release ${{ env.solutionfile-path }}
119+
120+
- name: Run the unit tests
121+
run: dotnet test ${{ env.solutionfile-path }}
122+
123+
- name: Create a Package
124+
run: dotnet pack -c Release ${{ env.projectfile-path }} -o packages
125+
126+
publishdevops:
127+
uses: CodebreakerApp/Codebreaker.Backend/.github/workflows/publishnuget-azuredevops.yml@main
128+
needs: build
129+
with:
130+
artifact-name: codebreaker-sqlserver-stable
131+
secrets: inherit
132+
133+
publishnuget:
134+
uses: CodebreakerApp/Codebreaker.Backend/.github/workflows/publishnuget-nugetserver.yml@main
135+
needs: publishdevops
136+
with:
137+
artifact-name: codebreaker-sqlserver-stable
138+
secrets: inherit
139+
```
140+
141+
### 3. Reusable Workflows
142+
143+
#### Build Workflow (`createnuget-withbuildnumber.yml`)
144+
145+
Features:
146+
- **Deterministic builds** for reproducible packages
147+
- **Source linking** with embedded sources
148+
- **Symbol packages** (.snupkg) generation
149+
- **Version calculation** with offsets
150+
- **Multi-targeting** support (net8.0;net9.0)
151+
152+
Key parameters:
153+
```yaml
154+
inputs:
155+
version-suffix: preview.1. # Quality marker
156+
version-number: ${{ github.run_number }} # Build number
157+
version-offset: 10 # Offset for version numbering
158+
solutionfile-path: src/Codebreaker.Backend.SqlServer.slnx
159+
projectfile-path: src/services/common/Codebreaker.Data.SqlServer/Codebreaker.Data.SqlServer.csproj
160+
dotnet-version: '9.0.x'
161+
artifact-name: codebreaker-sqlserver
162+
```
163+
164+
Deterministic build settings:
165+
```bash
166+
/p:ContinuousIntegrationBuild=true
167+
/p:Deterministic=true
168+
/p:EmbedUntrackedSources=true
169+
/p:DebugType=embedded
170+
/p:PublishRepositoryUrl=true
171+
/p:PathMap='$(MSBuildProjectDirectory)=/'
172+
```
173+
174+
#### Azure DevOps Publish Workflow (`publishnuget-azuredevops.yml`)
175+
176+
```yaml
177+
env:
178+
ARTIFACTS_URL: "https://pkgs.dev.azure.com/cnilearn/codebreakerpackages/_packaging/codebreaker/nuget/v3/index.json"
179+
180+
steps:
181+
- name: Add the Azure DevOps Artifacts Package Source
182+
run: dotnet nuget add source --username USERNAME --password ${{ secrets.DEVOPSARTIFACT_PAT }} --store-password-in-clear-text --name devopscninnovation ${{ env.ARTIFACTS_URL }}
183+
184+
- name: Publish to Azure DevOps Artifacts
185+
run: dotnet nuget push "packages/*.nupkg" --api-key ${{ secrets.DEVOPSARTIFACT_PAT }} --source devopscninnovation --skip-duplicate
186+
```
187+
188+
#### NuGet Gallery Publish Workflow (`publishnuget-nugetserver.yml`)
189+
190+
```yaml
191+
env:
192+
ARTIFACTS_URL: https://api.nuget.org/v3/index.json
193+
194+
steps:
195+
- name: Publish to the NuGet server (nupkg and snupkg)
196+
run: dotnet nuget push "packages/*.nupkg" --api-key ${{ secrets.NUGETAPIKEY }} --source ${{ env.ARTIFACTS_URL }}
197+
```
198+
199+
## Deployment Targets
200+
201+
### Azure DevOps Artifacts
202+
- **Purpose**: Internal package repository for preview and stable builds
203+
- **URL**: `https://pkgs.dev.azure.com/cnilearn/codebreakerpackages/_packaging/codebreaker/nuget/v3/index.json`
204+
- **Authentication**: Personal Access Token (PAT)
205+
- **Environment**: `DevOpsArtifacts`
206+
- **Features**:
207+
- Supports both preview and stable packages
208+
- Symbol packages (.snupkg)
209+
- Package retention policies
210+
211+
### NuGet Gallery
212+
- **Purpose**: Public package repository for stable builds only
213+
- **URL**: `https://api.nuget.org/v3/index.json`
214+
- **Authentication**: API Key
215+
- **Environment**: `NugetServer`
216+
- **Features**:
217+
- Global package distribution
218+
- Automatic symbol package handling
219+
- Package signing validation
220+
221+
## Required Secrets
222+
223+
Configure these secrets in your GitHub repository:
224+
225+
| Secret Name | Environment | Description |
226+
|-------------|-------------|-------------|
227+
| `DEVOPSARTIFACT_PAT` | DevOpsArtifacts | Personal Access Token for Azure DevOps Artifacts |
228+
| `NUGETAPIKEY` | NugetServer | API Key for NuGet Gallery |
229+
230+
## Best Practices
231+
232+
### 1. Version Management
233+
- Always update the base version in `.csproj` files before creating stable releases
234+
- Use semantic versioning (Major.Minor.Patch)
235+
- Preview versions automatically increment with build numbers
236+
237+
### 2. Package Dependencies
238+
- Keep internal package versions synchronized in `Directory.Packages.props`
239+
- Use conditional package versions for multi-targeting:
240+
```xml
241+
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" Condition="'$(TargetFramework)' == 'net8.0'" />
242+
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.9" Condition="'$(TargetFramework)' == 'net9.0'" />
243+
```
244+
245+
### 3. Testing Strategy
246+
- All builds run unit tests before packaging
247+
- Preview builds enable faster feedback cycles
248+
- Stable builds have additional validation through Azure DevOps Artifacts before NuGet Gallery
249+
250+
### 4. Path-Based Triggers
251+
- Preview workflows use path filters to trigger only on relevant changes:
252+
```yaml
253+
paths:
254+
- 'src/services/common/Codebreaker.Data.SqlServer/**'
255+
```
256+
257+
### 5. Artifact Management
258+
- Preview artifacts: 3-day retention
259+
- Stable artifacts: 30-day retention
260+
- Unique artifact names prevent conflicts
261+
262+
## Workflow Execution Guide
263+
264+
### Triggering Preview Builds
265+
1. **Automatic**: Push changes to main branch in monitored paths
266+
2. **Manual**: Use "Run workflow" button on GitHub Actions tab
267+
268+
### Triggering Stable Builds
269+
1. Navigate to GitHub Actions → Select stable workflow (e.g., "SqlServer stable lib")
270+
2. Click "Run workflow" button
271+
3. Confirm deployment to production environments
272+
273+
### Monitoring Builds
274+
- Check GitHub Actions tab for build status
275+
- Review Azure DevOps Artifacts for package availability
276+
- Verify NuGet Gallery for stable package publication
277+
278+
## Troubleshooting
279+
280+
### Common Issues
281+
282+
#### Build Failures
283+
- **Deterministic build issues**: Ensure all source files are committed
284+
- **Package reference errors**: Verify `Directory.Packages.props` contains all required packages
285+
- **Multi-targeting issues**: Check conditional package references
286+
287+
#### Deployment Failures
288+
- **Azure DevOps authentication**: Verify PAT token permissions
289+
- **NuGet Gallery publishing**: Check API key validity and package metadata
290+
- **Duplicate packages**: Use `--skip-duplicate` flag (already configured)
291+
292+
#### Version Conflicts
293+
- **Preview version conflicts**: Increase version offset in workflow
294+
- **Stable version conflicts**: Update base version in project file
295+
296+
### Debug Commands
297+
298+
```bash
299+
# Local package creation (preview)
300+
dotnet pack --version-suffix preview.1.123 -c Release src/services/common/Codebreaker.Data.SqlServer/Codebreaker.Data.SqlServer.csproj
301+
302+
# Local package creation (stable)
303+
dotnet pack -c Release src/services/common/Codebreaker.Data.SqlServer/Codebreaker.Data.SqlServer.csproj
304+
305+
# Test package installation
306+
dotnet add package CNinnovation.Codebreaker.SqlServer --version 3.8.0-preview.1.123 --source https://pkgs.dev.azure.com/...
307+
```
308+
309+
## Integration with Development Workflow
310+
311+
### For Library Developers
312+
1. **Development**: Work on feature branches
313+
2. **Integration**: Merge to main branch → Automatic preview build
314+
3. **Testing**: Use preview packages in dependent projects
315+
4. **Release**: Trigger stable build when ready for production
316+
317+
### For Library Consumers
318+
1. **Development**: Use preview packages from Azure DevOps Artifacts
319+
2. **Production**: Use stable packages from NuGet Gallery
320+
3. **Testing**: Pin specific preview versions for reproducible builds
321+
322+
## Future Enhancements
323+
324+
### Planned Improvements
325+
- **Automated release notes** generation from Git history
326+
- **Package vulnerability scanning** integration
327+
- **Performance regression testing** for library updates
328+
- **Automated dependency updates** with Dependabot
329+
- **Package usage analytics** and deprecation warnings
330+
331+
### Environment-Specific Deployments
332+
- **Development Environment**: Auto-deploy preview packages
333+
- **Staging Environment**: Manual promotion of stable candidates
334+
- **Production Environment**: Stable packages only with approval gates
335+
336+
This documentation provides a comprehensive guide for managing NuGet packages in the Codebreaker Backend solution, ensuring reliable and efficient package distribution for both development and production scenarios.

0 commit comments

Comments
 (0)