test fixes and new product advisories work
This commit is contained in:
195
docs/releases/REPRODUCIBLE_BUILDS.md
Normal file
195
docs/releases/REPRODUCIBLE_BUILDS.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# Reproducible Builds
|
||||
|
||||
Stella Ops releases are **reproducible**: given the same source code and build environment, anyone can produce byte-identical artifacts.
|
||||
|
||||
## Overview
|
||||
|
||||
Reproducible builds provide:
|
||||
|
||||
1. **Verifiability** - Anyone can verify that released binaries match source code
|
||||
2. **Trust** - No need to trust the build infrastructure
|
||||
3. **Auditability** - Build process can be independently audited
|
||||
4. **Security** - Compromised builds can be detected
|
||||
|
||||
## How It Works
|
||||
|
||||
### SOURCE_DATE_EPOCH
|
||||
|
||||
All timestamps in build outputs use the `SOURCE_DATE_EPOCH` environment variable instead of the current time. This is set to the git commit timestamp:
|
||||
|
||||
```bash
|
||||
export SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)
|
||||
```
|
||||
|
||||
### Deterministic Build Settings
|
||||
|
||||
The following MSBuild properties ensure deterministic .NET builds:
|
||||
|
||||
```xml
|
||||
<!-- src/Directory.Build.props -->
|
||||
<PropertyGroup>
|
||||
<Deterministic>true</Deterministic>
|
||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||
<PathMap>$(MSBuildProjectDirectory)=/src/</PathMap>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
### Pinned Dependencies
|
||||
|
||||
All dependencies are pinned to exact versions in `Directory.Packages.props`:
|
||||
|
||||
```xml
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
```
|
||||
|
||||
### Containerized Builds
|
||||
|
||||
Release builds run in containerized environments with:
|
||||
|
||||
- Fixed base images
|
||||
- Pinned tool versions
|
||||
- Isolated network (no external fetches during build)
|
||||
|
||||
## Reproducing a Build
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- .NET SDK (version in `global.json`)
|
||||
- Git
|
||||
- Docker (optional, for containerized builds)
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Clone the repository**
|
||||
|
||||
```bash
|
||||
git clone https://git.stella-ops.org/stella-ops.org/git.stella-ops.org.git
|
||||
cd git.stella-ops.org
|
||||
```
|
||||
|
||||
2. **Checkout the release tag**
|
||||
|
||||
```bash
|
||||
git checkout v1.2.3
|
||||
```
|
||||
|
||||
3. **Set SOURCE_DATE_EPOCH**
|
||||
|
||||
Get the value from the release evidence pack `manifest.json`:
|
||||
|
||||
```bash
|
||||
export SOURCE_DATE_EPOCH=1705315800
|
||||
```
|
||||
|
||||
Or compute from git:
|
||||
|
||||
```bash
|
||||
export SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)
|
||||
```
|
||||
|
||||
4. **Build**
|
||||
|
||||
```bash
|
||||
# Using make
|
||||
make release
|
||||
|
||||
# Or using dotnet directly
|
||||
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj \
|
||||
--configuration Release \
|
||||
--runtime linux-x64 \
|
||||
--self-contained true \
|
||||
/p:Deterministic=true \
|
||||
/p:ContinuousIntegrationBuild=true \
|
||||
/p:SourceRevisionId=$(git rev-parse HEAD)
|
||||
```
|
||||
|
||||
5. **Compare checksums**
|
||||
|
||||
```bash
|
||||
sha256sum dist/stella-* | diff - path/to/evidence-pack/checksums/SHA256SUMS
|
||||
```
|
||||
|
||||
## CI Verification
|
||||
|
||||
The CI pipeline automatically verifies reproducibility:
|
||||
|
||||
1. Builds artifacts twice with the same `SOURCE_DATE_EPOCH`
|
||||
2. Compares checksums between builds
|
||||
3. Fails if checksums don't match
|
||||
|
||||
See `.gitea/workflows/verify-reproducibility.yml`.
|
||||
|
||||
## What Can Cause Non-Reproducibility
|
||||
|
||||
### Timestamps
|
||||
|
||||
- **Problem**: Build tools embed current time
|
||||
- **Solution**: Use `SOURCE_DATE_EPOCH`
|
||||
|
||||
### Path Information
|
||||
|
||||
- **Problem**: Absolute paths embedded in binaries/PDBs
|
||||
- **Solution**: Use `PathMap` to normalize paths
|
||||
|
||||
### Random Values
|
||||
|
||||
- **Problem**: GUIDs, random seeds
|
||||
- **Solution**: Use deterministic generation or inject via DI
|
||||
|
||||
### Unordered Collections
|
||||
|
||||
- **Problem**: Dictionary/HashSet iteration order varies
|
||||
- **Solution**: Use `ImmutableSortedDictionary` or explicit sorting
|
||||
|
||||
### External Resources
|
||||
|
||||
- **Problem**: Network fetches return different content
|
||||
- **Solution**: Pin dependencies, use hermetic builds
|
||||
|
||||
### Compiler/Tool Versions
|
||||
|
||||
- **Problem**: Different tool versions produce different output
|
||||
- **Solution**: Pin all tool versions in `global.json` and CI
|
||||
|
||||
## Debugging Non-Reproducible Builds
|
||||
|
||||
### Compare binaries
|
||||
|
||||
```bash
|
||||
# Install diffoscope
|
||||
pip install diffoscope
|
||||
|
||||
# Compare two builds
|
||||
diffoscope build1/stella.dll build2/stella.dll
|
||||
```
|
||||
|
||||
### Check for timestamps
|
||||
|
||||
```bash
|
||||
# Look for embedded timestamps
|
||||
strings stella.dll | grep -E '20[0-9]{2}-[0-9]{2}'
|
||||
```
|
||||
|
||||
### Check PDB content
|
||||
|
||||
```bash
|
||||
# Examine PDB for path information
|
||||
dotnet tool install -g dotnet-symbol
|
||||
dotnet symbol --symbols stella.dll
|
||||
```
|
||||
|
||||
## Verification in Evidence Pack
|
||||
|
||||
The Release Evidence Pack includes:
|
||||
|
||||
1. **SOURCE_DATE_EPOCH** in `manifest.json`
|
||||
2. **Source commit** for exact source checkout
|
||||
3. **Checksums** for comparison
|
||||
4. **Build instructions** in `VERIFY.md`
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Release Evidence Pack](./RELEASE_EVIDENCE_PACK.md)
|
||||
- [SLSA Compliance](./SLSA_COMPLIANCE.md)
|
||||
- [Release Engineering Playbook](./RELEASE_ENGINEERING_PLAYBOOK.md)
|
||||
Reference in New Issue
Block a user