Skip to content

feat: Add reproducible builds release workflows and push images to DockerHub #12

feat: Add reproducible builds release workflows and push images to DockerHub

feat: Add reproducible builds release workflows and push images to DockerHub #12

name: reproducible-build
on:
workflow_dispatch: {}
schedule:
- cron: "0 1 */2 * *" # Every 2 days to catch issues early
pull_request:
types: [opened, synchronize, labeled]
paths:
- "Makefile"
- "Dockerfile.reproducible"
- ".github/workflows/reproducible-build.yml"
- "Cargo.toml"
- "Cargo.lock"
jobs:
build-x86_64:
name: test reproducible builds (x86_64)
runs-on: ubuntu-latest
# Run on schedule, workflow_dispatch, or PRs with the 'test-reproducible' label
if: >
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.pull_request.labels.*.name, 'test-reproducible')
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker # Use docker driver instead of docker-container for reproducibility
- name: Build first reproducible Docker image
run: |
echo "=== Building first Docker image (x86_64) ==="
docker build -f Dockerfile.reproducible \
--build-arg RUST_TARGET="x86_64-unknown-linux-gnu" \
--build-arg RUST_IMAGE="rust:1.86-bullseye@sha256:1110399f568f1dbe838e58f15b4162d899cb95f450f5f0ffa739614f3a4c32f1" \
-t build-lighthouse-1 .
echo "=== Extracting binary from first build ==="
docker create --name extract-lighthouse-1 build-lighthouse-1
docker cp extract-lighthouse-1:/lighthouse ./lighthouse-build-1
docker rm extract-lighthouse-1
echo "=== First build info ==="
ls -la lighthouse-build-1
sha256sum lighthouse-build-1
file lighthouse-build-1
- name: Clean Docker state completely
run: |
echo "=== Cleaning Docker state ==="
# Remove the first image
docker rmi build-lighthouse-1 || true
# Remove all build cache (important for reproducibility testing)
docker buildx prune -f || true
docker system prune -f || true
# Clear any remaining containers
docker container prune -f || true
echo "=== Docker state cleaned ==="
docker images
docker ps -a
- name: Build second reproducible Docker image
run: |
echo "=== Building second Docker image (x86_64) ==="
docker build -f Dockerfile.reproducible \
--build-arg RUST_TARGET="x86_64-unknown-linux-gnu" \
--build-arg RUST_IMAGE="rust:1.86-bullseye@sha256:1110399f568f1dbe838e58f15b4162d899cb95f450f5f0ffa739614f3a4c32f1" \
-t build-lighthouse-2 .
echo "=== Extracting binary from second build ==="
docker create --name extract-lighthouse-2 build-lighthouse-2
docker cp extract-lighthouse-2:/lighthouse ./lighthouse-build-2
docker rm extract-lighthouse-2
echo "=== Second build info ==="
ls -la lighthouse-build-2
sha256sum lighthouse-build-2
file lighthouse-build-2
- name: Compare Docker-built binaries
run: |
echo "=== Comparing Docker-built binaries (x86_64) ==="
echo "Build 1 info:"
ls -la lighthouse-build-1
echo "Build 2 info:"
ls -la lighthouse-build-2
echo "=== SHA256 checksums ==="
sha256sum lighthouse-build-*
echo "=== Binary comparison ==="
if cmp lighthouse-build-1 lighthouse-build-2; then
echo "✅ SUCCESS: Docker-built binaries are identical!"
echo "✅ Reproducible Docker build PASSED for x86_64"
else
echo "❌ FAILED: Docker-built binaries differ"
echo "First 10 differences:"
cmp -l lighthouse-build-1 lighthouse-build-2 | head -10
exit 1
fi
build-aarch64:
name: test reproducible builds (aarch64)
runs-on: ubuntu-24.04-arm
# Run on schedule, workflow_dispatch, or PRs with the 'test-reproducible' label
if: >
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.pull_request.labels.*.name, 'test-reproducible')
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Build first reproducible Docker image
run: |
echo "=== Building first Docker image (aarch64) ==="
docker build -f Dockerfile.reproducible \
--platform linux/arm64 \
--build-arg RUST_TARGET="aarch64-unknown-linux-gnu" \
--build-arg RUST_IMAGE="rust:1.86-bullseye@sha256:36053eabadeb701e3e0406610a2ce72ccfa10b7828963cd08cffdcf660518b27" \
-t build-lighthouse-1-arm64 .
echo "=== Extracting binary from first build ==="
docker create --name extract-lighthouse-1-arm64 build-lighthouse-1-arm64
docker cp extract-lighthouse-1-arm64:/lighthouse ./lighthouse-build-1-arm64
docker rm extract-lighthouse-1-arm64
echo "=== First build info ==="
ls -la lighthouse-build-1-arm64
sha256sum lighthouse-build-1-arm64
file lighthouse-build-1-arm64
- name: Clean Docker state completely
run: |
echo "=== Cleaning Docker state ==="
docker rmi build-lighthouse-1-arm64 || true
docker buildx prune -f || true
docker system prune -f || true
docker container prune -f || true
echo "=== Docker state cleaned ==="
docker images
docker ps -a
- name: Build second reproducible Docker image
run: |
echo "=== Building second Docker image (aarch64) ==="
docker build -f Dockerfile.reproducible \
--platform linux/arm64 \
--build-arg RUST_TARGET="aarch64-unknown-linux-gnu" \
--build-arg RUST_IMAGE="rust:1.86-bullseye@sha256:36053eabadeb701e3e0406610a2ce72ccfa10b7828963cd08cffdcf660518b27" \
-t build-lighthouse-2-arm64 .
echo "=== Extracting binary from second build ==="
docker create --name extract-lighthouse-2-arm64 build-lighthouse-2-arm64
docker cp extract-lighthouse-2-arm64:/lighthouse ./lighthouse-build-2-arm64
docker rm extract-lighthouse-2-arm64
echo "=== Second build info ==="
ls -la lighthouse-build-2-arm64
sha256sum lighthouse-build-2-arm64
file lighthouse-build-2-arm64
- name: Compare Docker-built binaries
run: |
echo "=== Comparing Docker-built binaries (aarch64) ==="
echo "Build 1 info:"
ls -la lighthouse-build-1-arm64
echo "Build 2 info:"
ls -la lighthouse-build-2-arm64
echo "=== SHA256 checksums ==="
sha256sum lighthouse-build-*-arm64
echo "=== Binary comparison ==="
if cmp lighthouse-build-1-arm64 lighthouse-build-2-arm64; then
echo "✅ SUCCESS: Docker-built binaries are identical!"
echo "✅ Reproducible Docker build PASSED for aarch64"
else
echo "❌ FAILED: Docker-built binaries differ"
echo "First 10 differences:"
cmp -l lighthouse-build-1-arm64 lighthouse-build-2-arm64 | head -10
exit 1
fi
summary:
name: reproducible build summary
runs-on: ubuntu-latest
needs: [build-x86_64, build-aarch64]
if: always()
steps:
- name: Report results
run: |
echo "## 🔄 Reproducible Build Test Results"
echo ""
# Show trigger reason
if [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "**Trigger**: Scheduled check (every 2 days)"
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "**Trigger**: Manual run"
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "**Trigger**: PR with 'test-reproducible' label"
fi
echo ""
if [[ "${{ needs.build-x86_64.result }}" == "success" ]]; then
echo "✅ **x86_64**: Reproducible builds PASSED"
elif [[ "${{ needs.build-x86_64.result }}" == "skipped" ]]; then
echo "⏭️ **x86_64**: Skipped (no label or wrong trigger)"
else
echo "❌ **x86_64**: Reproducible builds FAILED"
fi
if [[ "${{ needs.build-aarch64.result }}" == "success" ]]; then
echo "✅ **aarch64**: Reproducible builds PASSED"
elif [[ "${{ needs.build-aarch64.result }}" == "skipped" ]]; then
echo "⏭️ **aarch64**: Skipped (no label or wrong trigger)"
else
echo "❌ **aarch64**: Reproducible builds FAILED"
fi
echo ""
if [[ "${{ needs.build-x86_64.result }}" == "success" ]] \
&& [[ "${{ needs.build-aarch64.result }}" == "success" ]]; then
echo "🎉 **Overall**: All reproducible builds are working correctly!"
echo "Docker containers are reproducible."
elif [[ "${{ needs.build-x86_64.result }}" == "skipped" ]] \
&& [[ "${{ needs.build-aarch64.result }}" == "skipped" ]]; then
echo "⏭️ **Overall**: Tests were skipped (add 'test-reproducible' label to run on PRs)"
else
echo "⚠️ **Overall**: Some reproducible builds failed"
echo "Check the logs above for details"
exit 1
fi