Skip to content

Commit c0e7625

Browse files
Add deterministic build configuration and workflow
Co-authored-by: christiannagel <1908285+christiannagel@users.noreply.github.com>
1 parent 4397f49 commit c0e7625

4 files changed

Lines changed: 215 additions & 4 deletions

File tree

.github/workflows/createnuget-withbuildnumber.yml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ jobs:
4949
uses: actions/checkout@v5
5050
with:
5151
ref: ${{ inputs.branch-name }}
52+
# Fetch all history for proper source control information in deterministic builds
53+
fetch-depth: 0
5254

5355
- name: Setup .NET
5456
uses: actions/setup-dotnet@v5
@@ -71,14 +73,28 @@ jobs:
7173
run: |
7274
echo "version-suffix-string=$VERSION_SUFFIX$VERSION_NUMBER_WITH_OFFSET" >> "$GITHUB_OUTPUT"
7375
74-
- name: Build the library
75-
run: dotnet build --version-suffix ${{ steps.version-suffix.outputs.version-suffix-string }} -c Release ${{ inputs.solutionfile-path }}
76+
- name: Build the library (deterministic)
77+
run: |
78+
echo "Building with deterministic settings..."
79+
dotnet build --version-suffix ${{ steps.version-suffix.outputs.version-suffix-string }} -c Release ${{ inputs.solutionfile-path }} \
80+
/p:ContinuousIntegrationBuild=true \
81+
/p:Deterministic=true \
82+
/p:EmbedUntrackedSources=true \
83+
/p:DebugType=embedded \
84+
/p:PublishRepositoryUrl=true
7685
7786
- name: Run the unit tests
7887
run: dotnet test ${{ inputs.solutionfile-path }}
7988

80-
- name: Create a Package
81-
run: dotnet pack --version-suffix ${{ steps.version-suffix.outputs.version-suffix-string }} -c Release ${{ inputs.projectfile-path }} -o packages
89+
- name: Create a Package (deterministic)
90+
run: |
91+
echo "Creating deterministic NuGet package..."
92+
dotnet pack --version-suffix ${{ steps.version-suffix.outputs.version-suffix-string }} -c Release ${{ inputs.projectfile-path }} -o packages \
93+
/p:ContinuousIntegrationBuild=true \
94+
/p:Deterministic=true \
95+
/p:EmbedUntrackedSources=true \
96+
/p:DebugType=embedded \
97+
/p:PublishRepositoryUrl=true
8298
8399
- name: Upload artifact
84100
uses: actions/upload-artifact@v4
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
name: Deterministic Build
2+
3+
on:
4+
# Trigger on push and pull requests to main branch
5+
push:
6+
branches: [ main ]
7+
paths:
8+
- 'src/**'
9+
- '.github/workflows/deterministic-build.yml'
10+
pull_request:
11+
branches: [ main ]
12+
paths:
13+
- 'src/**'
14+
- '.github/workflows/deterministic-build.yml'
15+
16+
# Allow manual trigger
17+
workflow_dispatch:
18+
19+
env:
20+
DOTNET_VERSION: '9.0.x'
21+
CI: true
22+
23+
jobs:
24+
deterministic-build:
25+
name: Deterministic Build
26+
runs-on: ubuntu-latest
27+
28+
strategy:
29+
matrix:
30+
solution:
31+
- name: Analyzers
32+
path: src/Codebreaker.Analyzers.slnx
33+
project: src/services/common/Codebreaker.GameAPIs.Analyzers/Codebreaker.Analyzers.csproj
34+
- name: Backend-Models
35+
path: src/Codebreaker.Backend.Models.slnx
36+
project: src/services/common/Codebreaker.GameAPIs.Models/Codebreaker.GameAPIs.Models.csproj
37+
- name: Cosmos
38+
path: src/Codebreaker.Backend.Cosmos.slnx
39+
project: src/services/common/Codebreaker.Data.Cosmos/Codebreaker.Data.Cosmos.csproj
40+
- name: SqlServer
41+
path: src/Codebreaker.Backend.SqlServer.slnx
42+
project: src/services/common/Codebreaker.Data.SqlServer/Codebreaker.Data.SqlServer.csproj
43+
- name: Postgres
44+
path: src/Codebreaker.Backend.Postgres.slnx
45+
project: src/services/common/Codebreaker.Data.Postgres/Codebreaker.Data.Postgres.csproj
46+
- name: GameAPIs-Client
47+
path: src/Codebreaker.GameAPIs.Client.slnx
48+
project: src/clients/Codebreaker.GameAPIs.Client/Codebreaker.GameAPIs.Client.csproj
49+
50+
steps:
51+
- name: Checkout repository
52+
uses: actions/checkout@v5
53+
with:
54+
# Fetch all history for proper source control information
55+
fetch-depth: 0
56+
57+
- name: Setup .NET
58+
uses: actions/setup-dotnet@v5
59+
with:
60+
dotnet-version: ${{ env.DOTNET_VERSION }}
61+
62+
- name: Restore dependencies
63+
run: dotnet restore ${{ matrix.solution.path }}
64+
65+
- name: Build solution (deterministic)
66+
run: |
67+
echo "Building ${{ matrix.solution.name }} with deterministic settings..."
68+
dotnet build ${{ matrix.solution.path }} \
69+
--configuration Release \
70+
--no-restore \
71+
--verbosity normal \
72+
/p:ContinuousIntegrationBuild=true \
73+
/p:Deterministic=true \
74+
/p:EmbedUntrackedSources=true \
75+
/p:DebugType=embedded \
76+
/p:PublishRepositoryUrl=true
77+
78+
- name: Run tests
79+
run: dotnet test ${{ matrix.solution.path }} --configuration Release --no-build --verbosity normal
80+
81+
- name: Create NuGet package (deterministic)
82+
run: |
83+
echo "Creating deterministic NuGet package for ${{ matrix.solution.name }}..."
84+
dotnet pack ${{ matrix.solution.project }} \
85+
--configuration Release \
86+
--no-build \
87+
--output ./packages \
88+
/p:ContinuousIntegrationBuild=true \
89+
/p:Deterministic=true \
90+
/p:EmbedUntrackedSources=true \
91+
/p:DebugType=embedded \
92+
/p:PublishRepositoryUrl=true
93+
94+
- name: Verify deterministic build
95+
shell: bash
96+
run: |
97+
echo "Verifying deterministic build for ${{ matrix.solution.name }}..."
98+
99+
# Create a second build to compare determinism
100+
rm -rf ./packages-verify
101+
mkdir ./packages-verify
102+
103+
echo "Building second time for verification..."
104+
dotnet pack ${{ matrix.solution.project }} \
105+
--configuration Release \
106+
--no-build \
107+
--output ./packages-verify \
108+
/p:ContinuousIntegrationBuild=true \
109+
/p:Deterministic=true \
110+
/p:EmbedUntrackedSources=true \
111+
/p:DebugType=embedded \
112+
/p:PublishRepositoryUrl=true
113+
114+
# Compare the packages (basic check - file sizes should be identical)
115+
echo "Comparing package files..."
116+
ls -la ./packages/
117+
ls -la ./packages-verify/
118+
119+
# Check if the files have the same size
120+
for file in ./packages/*.nupkg; do
121+
filename=$(basename "$file")
122+
if [ -f "./packages-verify/$filename" ]; then
123+
size1=$(stat -c%s "./packages/$filename")
124+
size2=$(stat -c%s "./packages-verify/$filename")
125+
echo "Package $filename: Original size=$size1, Verify size=$size2"
126+
if [ "$size1" != "$size2" ]; then
127+
echo "ERROR: Package sizes differ! Build is not deterministic."
128+
exit 1
129+
fi
130+
else
131+
echo "ERROR: Verification package $filename not found!"
132+
exit 1
133+
fi
134+
done
135+
136+
echo "✅ Deterministic build verification passed for ${{ matrix.solution.name }}"
137+
138+
- name: Upload build artifacts
139+
uses: actions/upload-artifact@v4
140+
with:
141+
name: deterministic-packages-${{ matrix.solution.name }}
142+
path: |
143+
./packages/*.nupkg
144+
./packages/*.snupkg
145+
retention-days: 7
146+
compression-level: 6
147+
148+
summary:
149+
name: Build Summary
150+
runs-on: ubuntu-latest
151+
needs: deterministic-build
152+
if: always()
153+
154+
steps:
155+
- name: Build Summary
156+
run: |
157+
echo "## Deterministic Build Summary" >> $GITHUB_STEP_SUMMARY
158+
echo "" >> $GITHUB_STEP_SUMMARY
159+
echo "All library solutions have been built with deterministic settings:" >> $GITHUB_STEP_SUMMARY
160+
echo "- ✅ ContinuousIntegrationBuild=true" >> $GITHUB_STEP_SUMMARY
161+
echo "- ✅ Deterministic=true" >> $GITHUB_STEP_SUMMARY
162+
echo "- ✅ EmbedUntrackedSources=true" >> $GITHUB_STEP_SUMMARY
163+
echo "- ✅ DebugType=embedded" >> $GITHUB_STEP_SUMMARY
164+
echo "- ✅ PublishRepositoryUrl=true" >> $GITHUB_STEP_SUMMARY
165+
echo "" >> $GITHUB_STEP_SUMMARY
166+
echo "Build artifacts have been uploaded and are available for download." >> $GITHUB_STEP_SUMMARY
167+
echo "" >> $GITHUB_STEP_SUMMARY
168+
echo "### Solutions Built:" >> $GITHUB_STEP_SUMMARY
169+
echo "- Analyzers" >> $GITHUB_STEP_SUMMARY
170+
echo "- Backend Models" >> $GITHUB_STEP_SUMMARY
171+
echo "- Cosmos DB Library" >> $GITHUB_STEP_SUMMARY
172+
echo "- SQL Server Library" >> $GITHUB_STEP_SUMMARY
173+
echo "- PostgreSQL Library" >> $GITHUB_STEP_SUMMARY
174+
echo "- GameAPIs Client Library" >> $GITHUB_STEP_SUMMARY

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ NuGet: https://www.nuget.org/packages/CNinnovation.Codebreaker.GamesClient
5353

5454
## Builds
5555

56+
### Deterministic Builds
57+
58+
All NuGet packages produced by this repository are built using deterministic builds to ensure reproducible outputs. The deterministic build process is configured with the following MSBuild properties:
59+
60+
- `ContinuousIntegrationBuild=true` - Enables CI-specific build optimizations
61+
- `Deterministic=true` - Ensures deterministic compilation outputs
62+
- `EmbedUntrackedSources=true` - Embeds source files in PDB for better debugging
63+
- `DebugType=embedded` - Embeds PDB information directly in assemblies
64+
- `PublishRepositoryUrl=true` - Includes repository information in packages
65+
66+
The deterministic build workflow runs on push and pull requests to main branch, building all library solutions and uploading artifacts for inspection. Individual library workflows also use deterministic build settings.
67+
5668
### Libraries
5769

5870
#### Preview versions

src/Directory.Build.props

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,13 @@
1717
<PropertyGroup>
1818
<VersionPrefix>3.8.0</VersionPrefix>
1919
</PropertyGroup>
20+
21+
<!-- Deterministic Build Properties -->
22+
<PropertyGroup Condition="'$(CI)' == 'true' OR '$(TF_BUILD)' == 'true'">
23+
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
24+
<Deterministic>true</Deterministic>
25+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
26+
<DebugType>embedded</DebugType>
27+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
28+
</PropertyGroup>
2029
</Project>

0 commit comments

Comments
 (0)