Files
git.stella-ops.org/.gitea/workflows/attestation-linkage.yml

273 lines
9.6 KiB
YAML

# Attestation Linkage Workflow
# Sprint: Testing Enhancement Advisory - Phase 1.3
# Generates test run attestations linking outputs to inputs (SBOMs, VEX)
name: attestation-linkage
on:
push:
branches: [main]
paths:
- 'src/__Tests/**'
- 'src/__Libraries/StellaOps.Testing.Manifests/**'
pull_request:
paths:
- 'src/__Tests/**'
- 'src/__Libraries/StellaOps.Testing.Manifests/**'
workflow_dispatch:
inputs:
sign_attestations:
description: 'Sign attestations with production key'
type: boolean
default: false
verify_existing:
description: 'Verify existing attestations in evidence locker'
type: boolean
default: false
concurrency:
group: attestation-linkage-${{ github.ref }}
cancel-in-progress: true
env:
DETERMINISM_OUTPUT_DIR: ${{ github.workspace }}/attestation-output
jobs:
# ==========================================================================
# Build Attestation Infrastructure
# ==========================================================================
build-attestation:
name: Build Attestation Infrastructure
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.0.100"
- name: Restore dependencies
run: dotnet restore src/__Tests/__Libraries/StellaOps.Testing.Manifests/StellaOps.Testing.Manifests.csproj
- name: Build attestation library
run: |
dotnet build src/__Tests/__Libraries/StellaOps.Testing.Manifests/StellaOps.Testing.Manifests.csproj \
--configuration Release \
--no-restore
- name: Verify attestation types compile
run: |
# Verify the attestation generator compiles correctly
dotnet build src/__Tests/__Libraries/StellaOps.Testing.Manifests/StellaOps.Testing.Manifests.csproj \
--configuration Release \
-warnaserror
# ==========================================================================
# Generate Test Run Attestations
# ==========================================================================
generate-attestations:
name: Generate Test Run Attestations
runs-on: ubuntu-latest
timeout-minutes: 20
needs: build-attestation
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.0.100"
- name: Create output directory
run: mkdir -p $DETERMINISM_OUTPUT_DIR/attestations
- name: Restore and build test projects
run: |
dotnet restore src/StellaOps.sln
dotnet build src/StellaOps.sln --configuration Release --no-restore
- name: Run determinism tests with attestation
run: |
# Run determinism tests and capture results for attestation
dotnet test src/__Tests/__Libraries/StellaOps.HybridLogicalClock.Tests \
--configuration Release \
--no-build \
--filter "Category=Unit" \
--logger "trx;LogFileName=hlc-unit.trx" \
--results-directory $DETERMINISM_OUTPUT_DIR/results \
|| true
- name: Collect test evidence
run: |
# Collect test run evidence for attestation generation
cat > $DETERMINISM_OUTPUT_DIR/test-evidence.json << 'EOF'
{
"testFramework": "xunit",
"executedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"gitCommitSha": "${{ github.sha }}",
"gitBranch": "${{ github.ref_name }}",
"ciBuildId": "${{ github.run_id }}",
"ciWorkflow": "${{ github.workflow }}"
}
EOF
- name: Generate attestation manifest
run: |
# Generate a manifest of test outputs for attestation
echo "Generating attestation manifest..."
# Compute digests of test result files
if [ -d "$DETERMINISM_OUTPUT_DIR/results" ]; then
find $DETERMINISM_OUTPUT_DIR/results -name "*.trx" -exec sha256sum {} \; \
> $DETERMINISM_OUTPUT_DIR/attestations/output-digests.txt
fi
# Create attestation metadata
cat > $DETERMINISM_OUTPUT_DIR/attestations/attestation-metadata.json << EOF
{
"schemaVersion": "1.0.0",
"generatedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"runId": "${{ github.run_id }}-${{ github.run_attempt }}",
"predicateType": "https://stellaops.io/attestation/test-run/v1",
"signed": ${{ github.event.inputs.sign_attestations == 'true' && 'true' || 'false' }}
}
EOF
- name: Upload attestation artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: attestation-artifacts
path: |
${{ env.DETERMINISM_OUTPUT_DIR }}/attestations/**
${{ env.DETERMINISM_OUTPUT_DIR }}/results/**
${{ env.DETERMINISM_OUTPUT_DIR }}/test-evidence.json
# ==========================================================================
# Verify Attestation Linkage
# ==========================================================================
verify-attestation-linkage:
name: Verify Attestation Linkage
runs-on: ubuntu-latest
timeout-minutes: 10
needs: generate-attestations
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download attestation artifacts
uses: actions/download-artifact@v4
with:
name: attestation-artifacts
path: ${{ env.DETERMINISM_OUTPUT_DIR }}
- name: Verify attestation structure
run: |
echo "Verifying attestation structure..."
# Check that metadata file exists and is valid JSON
if [ -f "$DETERMINISM_OUTPUT_DIR/attestations/attestation-metadata.json" ]; then
cat $DETERMINISM_OUTPUT_DIR/attestations/attestation-metadata.json | jq .
echo "Attestation metadata is valid JSON"
else
echo "::warning::No attestation metadata found"
fi
# Check output digests
if [ -f "$DETERMINISM_OUTPUT_DIR/attestations/output-digests.txt" ]; then
echo "Output digests recorded:"
cat $DETERMINISM_OUTPUT_DIR/attestations/output-digests.txt
fi
- name: Verify SBOM linkage
run: |
echo "Verifying SBOM linkage..."
# In a full implementation, this would:
# 1. Load the test run manifest
# 2. Verify all SBOM digests are referenced in the attestation
# 3. Verify the attestation subject digests match actual outputs
echo "SBOM linkage verification: PASS (placeholder)"
- name: Verify VEX linkage
run: |
echo "Verifying VEX linkage..."
# In a full implementation, this would:
# 1. Load VEX documents referenced in the test run
# 2. Verify they were considered in the test execution
# 3. Verify the attestation predicate includes VEX digests
echo "VEX linkage verification: PASS (placeholder)"
# ==========================================================================
# Attestation Unit Tests
# ==========================================================================
attestation-unit-tests:
name: Attestation Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.0.100"
- name: Restore dependencies
run: dotnet restore src/__Tests/__Libraries/StellaOps.Testing.Manifests/StellaOps.Testing.Manifests.csproj
- name: Build
run: |
dotnet build src/__Tests/__Libraries/StellaOps.Testing.Manifests/StellaOps.Testing.Manifests.csproj \
--configuration Release \
--no-restore
- name: Run attestation tests
run: |
# Run tests for the attestation infrastructure
# Note: Tests would be in a .Tests project
echo "Attestation unit tests: Would run from StellaOps.Testing.Manifests.Tests"
# For now, verify the types are correctly structured
dotnet build src/__Tests/__Libraries/StellaOps.Testing.Manifests/StellaOps.Testing.Manifests.csproj \
--configuration Release \
-warnaserror
# ==========================================================================
# Gate Status
# ==========================================================================
attestation-gate:
name: Attestation Linkage Gate
runs-on: ubuntu-latest
needs: [build-attestation, generate-attestations, verify-attestation-linkage, attestation-unit-tests]
if: always()
steps:
- name: Check gate status
run: |
if [ "${{ needs.build-attestation.result }}" == "failure" ]; then
echo "::error::Attestation build failed"
exit 1
fi
if [ "${{ needs.generate-attestations.result }}" == "failure" ]; then
echo "::error::Attestation generation failed"
exit 1
fi
if [ "${{ needs.verify-attestation-linkage.result }}" == "failure" ]; then
echo "::error::Attestation linkage verification failed"
exit 1
fi
if [ "${{ needs.attestation-unit-tests.result }}" == "failure" ]; then
echo "::error::Attestation unit tests failed"
exit 1
fi
echo "All attestation linkage checks passed!"