test fixes and new product advisories work
This commit is contained in:
258
.gitea/workflows/verify-reproducibility.yml
Normal file
258
.gitea/workflows/verify-reproducibility.yml
Normal file
@@ -0,0 +1,258 @@
|
||||
# .gitea/workflows/verify-reproducibility.yml
|
||||
# Verifies that builds are reproducible (same inputs produce same outputs)
|
||||
|
||||
name: Verify Reproducibility
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'Directory.Build.props'
|
||||
- 'Directory.Packages.props'
|
||||
- 'global.json'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'Directory.Build.props'
|
||||
- 'Directory.Packages.props'
|
||||
- 'global.json'
|
||||
schedule:
|
||||
# Run weekly to catch any drift
|
||||
- cron: '0 6 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
DOTNET_VERSION: '10.0.100'
|
||||
BUILD_CONFIGURATION: Release
|
||||
|
||||
jobs:
|
||||
verify-deterministic-build:
|
||||
runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Compute SOURCE_DATE_EPOCH
|
||||
id: epoch
|
||||
run: |
|
||||
EPOCH=$(git show -s --format=%ct HEAD)
|
||||
echo "epoch=$EPOCH" >> "$GITHUB_OUTPUT"
|
||||
echo "SOURCE_DATE_EPOCH=$EPOCH"
|
||||
|
||||
- name: Build pass 1
|
||||
env:
|
||||
SOURCE_DATE_EPOCH: ${{ steps.epoch.outputs.epoch }}
|
||||
CI: true
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf build1/
|
||||
|
||||
# Build a representative set of projects
|
||||
PROJECTS=(
|
||||
"src/Attestor/__Libraries/StellaOps.Attestor.EvidencePack/StellaOps.Attestor.EvidencePack.csproj"
|
||||
"src/__Libraries/StellaOps.Canonical.Json/StellaOps.Canonical.Json.csproj"
|
||||
"src/Signer/StellaOps.Signer/StellaOps.Signer.Core/StellaOps.Signer.Core.csproj"
|
||||
)
|
||||
|
||||
for project in "${PROJECTS[@]}"; do
|
||||
if [ -f "$project" ]; then
|
||||
name=$(basename "$(dirname "$project")")
|
||||
echo "Building: $name (pass 1)"
|
||||
dotnet build "$project" \
|
||||
--configuration $BUILD_CONFIGURATION \
|
||||
--output "build1/$name" \
|
||||
/p:Deterministic=true \
|
||||
/p:ContinuousIntegrationBuild=true \
|
||||
/p:SourceRevisionId=${{ github.sha }}
|
||||
fi
|
||||
done
|
||||
|
||||
# Generate checksums
|
||||
find build1 -name "*.dll" -type f -exec sha256sum {} \; | sort > build1.checksums
|
||||
echo "Pass 1 checksums:"
|
||||
cat build1.checksums
|
||||
|
||||
- name: Clean build
|
||||
run: |
|
||||
dotnet clean --configuration $BUILD_CONFIGURATION || true
|
||||
rm -rf obj/ bin/ */obj/ */bin/
|
||||
|
||||
- name: Build pass 2
|
||||
env:
|
||||
SOURCE_DATE_EPOCH: ${{ steps.epoch.outputs.epoch }}
|
||||
CI: true
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf build2/
|
||||
|
||||
PROJECTS=(
|
||||
"src/Attestor/__Libraries/StellaOps.Attestor.EvidencePack/StellaOps.Attestor.EvidencePack.csproj"
|
||||
"src/__Libraries/StellaOps.Canonical.Json/StellaOps.Canonical.Json.csproj"
|
||||
"src/Signer/StellaOps.Signer/StellaOps.Signer.Core/StellaOps.Signer.Core.csproj"
|
||||
)
|
||||
|
||||
for project in "${PROJECTS[@]}"; do
|
||||
if [ -f "$project" ]; then
|
||||
name=$(basename "$(dirname "$project")")
|
||||
echo "Building: $name (pass 2)"
|
||||
dotnet build "$project" \
|
||||
--configuration $BUILD_CONFIGURATION \
|
||||
--output "build2/$name" \
|
||||
/p:Deterministic=true \
|
||||
/p:ContinuousIntegrationBuild=true \
|
||||
/p:SourceRevisionId=${{ github.sha }}
|
||||
fi
|
||||
done
|
||||
|
||||
# Generate checksums
|
||||
find build2 -name "*.dll" -type f -exec sha256sum {} \; | sort > build2.checksums
|
||||
echo "Pass 2 checksums:"
|
||||
cat build2.checksums
|
||||
|
||||
- name: Compare builds
|
||||
id: compare
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "Comparing build outputs..."
|
||||
|
||||
# Extract just the hashes for comparison (paths may differ)
|
||||
cut -d' ' -f1 build1.checksums | sort > build1.hashes
|
||||
cut -d' ' -f1 build2.checksums | sort > build2.hashes
|
||||
|
||||
if diff build1.hashes build2.hashes > /dev/null; then
|
||||
echo "✅ Builds are reproducible! All checksums match."
|
||||
echo "reproducible=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "❌ Builds are NOT reproducible!"
|
||||
echo ""
|
||||
echo "Differences:"
|
||||
diff build1.checksums build2.checksums || true
|
||||
echo "reproducible=false" >> "$GITHUB_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload build artifacts for debugging
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: reproducibility-debug
|
||||
path: |
|
||||
build1.checksums
|
||||
build2.checksums
|
||||
build1/
|
||||
build2/
|
||||
retention-days: 7
|
||||
|
||||
verify-cli-reproducibility:
|
||||
runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Compute SOURCE_DATE_EPOCH
|
||||
id: epoch
|
||||
run: |
|
||||
EPOCH=$(git show -s --format=%ct HEAD)
|
||||
echo "epoch=$EPOCH" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build CLI pass 1
|
||||
env:
|
||||
SOURCE_DATE_EPOCH: ${{ steps.epoch.outputs.epoch }}
|
||||
CI: true
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj \
|
||||
--configuration $BUILD_CONFIGURATION \
|
||||
--runtime linux-x64 \
|
||||
--self-contained false \
|
||||
--output cli-build1 \
|
||||
/p:Deterministic=true \
|
||||
/p:ContinuousIntegrationBuild=true \
|
||||
/p:SourceRevisionId=${{ github.sha }}
|
||||
|
||||
sha256sum cli-build1/StellaOps.Cli.dll > cli-build1.checksum
|
||||
cat cli-build1.checksum
|
||||
|
||||
- name: Clean
|
||||
run: |
|
||||
dotnet clean --configuration $BUILD_CONFIGURATION || true
|
||||
rm -rf src/Cli/StellaOps.Cli/obj src/Cli/StellaOps.Cli/bin
|
||||
|
||||
- name: Build CLI pass 2
|
||||
env:
|
||||
SOURCE_DATE_EPOCH: ${{ steps.epoch.outputs.epoch }}
|
||||
CI: true
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj \
|
||||
--configuration $BUILD_CONFIGURATION \
|
||||
--runtime linux-x64 \
|
||||
--self-contained false \
|
||||
--output cli-build2 \
|
||||
/p:Deterministic=true \
|
||||
/p:ContinuousIntegrationBuild=true \
|
||||
/p:SourceRevisionId=${{ github.sha }}
|
||||
|
||||
sha256sum cli-build2/StellaOps.Cli.dll > cli-build2.checksum
|
||||
cat cli-build2.checksum
|
||||
|
||||
- name: Compare CLI builds
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
HASH1=$(cut -d' ' -f1 cli-build1.checksum)
|
||||
HASH2=$(cut -d' ' -f1 cli-build2.checksum)
|
||||
|
||||
if [ "$HASH1" = "$HASH2" ]; then
|
||||
echo "✅ CLI builds are reproducible!"
|
||||
echo " Hash: $HASH1"
|
||||
else
|
||||
echo "❌ CLI builds are NOT reproducible!"
|
||||
echo " Pass 1: $HASH1"
|
||||
echo " Pass 2: $HASH2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
report:
|
||||
runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }}
|
||||
needs: [verify-deterministic-build, verify-cli-reproducibility]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Report results
|
||||
run: |
|
||||
echo "========================================"
|
||||
echo " REPRODUCIBILITY VERIFICATION"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "Library builds: ${{ needs.verify-deterministic-build.result }}"
|
||||
echo "CLI builds: ${{ needs.verify-cli-reproducibility.result }}"
|
||||
echo ""
|
||||
|
||||
if [ "${{ needs.verify-deterministic-build.result }}" = "success" ] && \
|
||||
[ "${{ needs.verify-cli-reproducibility.result }}" = "success" ]; then
|
||||
echo "✅ All builds are reproducible!"
|
||||
else
|
||||
echo "❌ Some builds are not reproducible"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user