Skip to content

Conversation

@MoeMahhouk
Copy link
Contributor

@MoeMahhouk MoeMahhouk commented Jun 16, 2025

Issue Addressed

This pull request introduces workflows and updates to ensure reproducible builds for the Lighthouse project. It adds two GitHub Actions workflows for building and testing reproducible Docker images and binaries, updates the Makefile to streamline reproducible build configurations, and modifies the Dockerfile.reproducible to align with the new build process. Additionally, it removes the reproducible profile from Cargo.toml.

Proposed Changes

New GitHub Actions Workflows:

Build Configuration Updates:

  • Makefile: Refactors reproducible build targets, centralizes environment variables for reproducibility, and updates Docker build arguments for x86_64 and aarch64 architectures.
  • Dockerfile.reproducible: Updates the base Rust image to version 1.86, removes hardcoded reproducibility settings, and delegates build logic to the Makefile.

Profile Removal:

  • Cargo.toml: Removes the reproducible profile, simplifying build configurations and relying on external tooling for reproducibility.

Additional Info

This is mainly a follow up to this work #6799 where I refine the reproducible build configuration to simplify the CI workflow to generate the reproducible images and pushes them to DockerHub. I also added a cron job workflow (inspired from the Reth repo) that checks every two days or pull requests that touches files that might affect reproducibility to catch potential regressions.
In case, this is too much, let me know and I can create a separate PR for this to be merged later when necessary

close #7486
close #7485

@cla-assistant
Copy link

cla-assistant bot commented Jun 16, 2025

CLA assistant check
All committers have signed the CLA.

@cla-assistant
Copy link

cla-assistant bot commented Jun 16, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ MoeMahhouk
❌ Ubuntu


Ubuntu seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@MoeMahhouk MoeMahhouk force-pushed the unstable branch 2 times, most recently from 82dcfef to 238fbaa Compare June 17, 2025 10:39
@chong-he
Copy link
Member

Doing some testing on this, will post the comment when ready

@mergify
Copy link

mergify bot commented Jun 23, 2025

Some required checks have failed. Could you please take a look @MoeMahhouk? 🙏

@mergify mergify bot added waiting-on-author The reviewer has suggested changes and awaits thier implementation. and removed ready-for-review The code is ready for review labels Jun 23, 2025
Copy link
Member

@chong-he chong-he left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I left some comments after doing some testing

@MoeMahhouk MoeMahhouk marked this pull request as draft June 24, 2025 15:56
@MoeMahhouk
Copy link
Contributor Author

Thanks for the PR. I left some comments after doing some testing

Thanks for reviewing it.
I will do some rework and refinements to this PR to fix the issues and address your comments.

@MoeMahhouk MoeMahhouk requested a review from chong-he June 30, 2025 15:55
@chong-he
Copy link
Member

chong-he commented Jul 1, 2025

Thanks for the PR. I left some comments after doing some testing

Thanks for reviewing it. I will do some rework and refinements to this PR to fix the issues and address your comments.

Is there a reason why is this PR still a draft?

@MoeMahhouk
Copy link
Contributor Author

Thanks for the PR. I left some comments after doing some testing

Thanks for reviewing it. I will do some rework and refinements to this PR to fix the issues and address your comments.

Is there a reason why is this PR still a draft?

Not really, I am waiting for your final feedback to open it for review/merge.
I will open it now for review and if you find anything needed for iteration, we can switch it back again.

@MoeMahhouk MoeMahhouk marked this pull request as ready for review July 1, 2025 15:30
@chong-he chong-he added the test-reproducible for testing reproducible builds label Jul 2, 2025
Copy link
Member

@chong-he chong-he left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested this and it is working. Would be great to get some comments from the devs

I have added a label test-reproducible, that will trigger the reproducible builds CI to run. When we have release PR, we can add this label
to run the check and ensure that the binaries are reproducible.

@chong-he chong-he requested a review from antondlr July 2, 2025 12:37
@MoeMahhouk
Copy link
Contributor Author

@chong-he , I just wanted to double check if this is waiting on me for anything else so far?

@chong-he
Copy link
Member

chong-he commented Jul 9, 2025

@chong-he , I just wanted to double check if this is waiting on me for anything else so far?

No

The PR is now waiting for other team members to review

@mergify mergify bot closed this Aug 1, 2025
@mergify
Copy link

mergify bot commented Aug 1, 2025

Hi @MoeMahhouk, this pull request has been closed automatically due to 30 days of inactivity. If you’d like to continue working on it, feel free to reopen at any time.

@mergify mergify bot added the stale Stale PRs that have been inactive and is now outdated label Aug 1, 2025
@jimmygchen jimmygchen reopened this Aug 6, 2025
@jimmygchen
Copy link
Member

Re-opening this PR as it was awaiting review.

@jimmygchen jimmygchen removed the stale Stale PRs that have been inactive and is now outdated label Aug 6, 2025
@antondlr
Copy link
Member

antondlr commented Aug 6, 2025

I like this idea but would like it to be less maintenance-intensive.
One thing that immediately stands out:
we should not have granular versions like RUST_IMAGE="rust:1.86-bullseye@sha256:1110399f568f1dbe838e58f15b4162d899cb95f450f5f0ffa739614f3a4c32f1 in the workflow/dockerfile but rather provide them as parameters.

@MoeMahhouk
Copy link
Contributor Author

I like this idea but would like it to be less maintenance-intensive. One thing that immediately stands out: we should not have granular versions like RUST_IMAGE="rust:1.86-bullseye@sha256:1110399f568f1dbe838e58f15b4162d899cb95f450f5f0ffa739614f3a4c32f1 in the workflow/dockerfile but rather provide them as parameters.

good idea, could you provide an example on that suggestion? do you have a reference link or would you like to take that up and refine it to be a parameter instead?

@mergify mergify bot closed this Sep 5, 2025
@mergify
Copy link

mergify bot commented Sep 5, 2025

Hi @MoeMahhouk, this pull request has been closed automatically due to 30 days of inactivity. If you’d like to continue working on it, feel free to reopen at any time.

@mergify mergify bot added the stale Stale PRs that have been inactive and is now outdated label Sep 5, 2025
@MoeMahhouk
Copy link
Contributor Author

Hey folks, @chong-he @jimmygchen ,this PR got auto-closed due to inactivity, but the changes are current and needs review. Could we reopen this for another pass?

@chong-he chong-he reopened this Oct 6, 2025
@chong-he
Copy link
Member

chong-he commented Oct 6, 2025

Hey folks, @chong-he @jimmygchen ,this PR got auto-closed due to inactivity, but the changes are current and needs review. Could we reopen this for another pass?

Reopening, could you solve some conflicts in the branch?
I will try to give this another review

@MoeMahhouk
Copy link
Contributor Author

Hey folks, @chong-he @jimmygchen ,this PR got auto-closed due to inactivity, but the changes are current and needs review. Could we reopen this for another pass?

Reopening, could you solve some conflicts in the branch? I will try to give this another review

solved the conflicts and merged. Let me know if you want me to do any other change

Copy link
Member

@chong-he chong-he left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at this a second time and try to suggest some simplifications so that it is easier to maintain and make the code cleaner.

Also, I would prefer to not have the symbol (green tick, cross etc) to keep the code clean.

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.88-bullseye@sha256:8e3c421122bf4cd3b2a866af41a4dd52d87ad9e315fd2cb5100e87a7187a9816" \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this line and instead just let it read from Dockerfile.reproducible for the RUST_IMAGE. I have tested it on my local repo and it works, see: https://github.com/chong-he/lighthouse/pull/9/files#diff-587298ff141278ce3be7c54a559f9f31472cc5b384e285e2105b3dee319ba31d

This also applies to all other instances that uses this RUST_IMAGE. Taking the idea from Dockerfile:

FROM rust:1.88.0-bullseye AS builder

We can also remove the sha256 in the RUST_IMAGE in Dockerfile.reproducible. That will make it much easier to maintain.

We also do not need a separate image on x86_64 or arm64 from my understanding, as docker is able to select the image based on the host: https://docs.docker.com/build/building/multi-platform/#difference-between-single-platform-and-multi-platform-images, so that will make things simpler

Suggested change
--build-arg RUST_IMAGE="rust:1.88-bullseye@sha256:8e3c421122bf4cd3b2a866af41a4dd52d87ad9e315fd2cb5100e87a7187a9816" \

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pinning the sha256 for better tracking and reproducibility stability because if any dependency gets updated for that specific image version of rust:1.88, it would also changes its hash history and eventually also impact the reproducibility of the generated lighthouse binary.
If you are ok to proceed with such trade-off, I can remove the sha256 pinning to the rust image.

Regarding removing the whole build-arg, I believe that would be necessary since we are not passing the --platform to the docker build command for the image to identify which one to select.
Nonetheless, if you decide to keep the sha256 for stable reproducibility tracking, then I believe we can't remove this line as it wouldn't be able to detect which sha256 to fetch for which platform, right?

echo "🔄 Verifying reproducible builds for ${{ matrix.arch }}..."

# Build first image
echo "=== Building first verification image ==="
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I raised this before to have a reproducible check before publishing the image. I am sorry, thinking about it now, we already have the reproducible-CI checks, and this seems repetitive now. In the interest of making things simpler, should we remove the check? I am trying to make the changes as minimal as possible, so that it is easier to read and maintain. After all, the checks for reproducibility is running every 2 days so if anything, we can catch it earlier.

I am just considering about the consequence - if without the checks and the docker images are pushed, then it could be that the docker images are not reproducible in the worse outcome?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove the check but then we would have the scenario that the reproducible-build CI might break but this workflow still builds and publishes a "reproducible" docker build despite being broken.
Do you still want to remove the reproducibility check?

Yes, I recall we discussed this before and decided to add this check here despite repetitiveness to avoid such misleading scenario where shipped reproducible docker builds aren't actually reproducible

FROM gcr.io/distroless/cc-debian12:nonroot-6755e21ccd99ddead6edc8106ba03888cbeed41a
COPY --from=builder /lighthouse /lighthouse

EXPOSE 30303 30303/udp 9001 8545 8546
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is necessary? The ports 8545, 8546, 30303 are for the EL

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, which ones do you recommend to replace them with?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just delete this line, can't we? When running the image, users will usually specify the port themselves, so this feels redundant

@chong-he chong-he removed the stale Stale PRs that have been inactive and is now outdated label Nov 4, 2025
echo "🔄 Verifying reproducible builds for ${{ matrix.arch }}..."

# Build first image
echo "=== Building first verification image ==="
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove the check but then we would have the scenario that the reproducible-build CI might break but this workflow still builds and publishes a "reproducible" docker build despite being broken.
Do you still want to remove the reproducibility check?

Yes, I recall we discussed this before and decided to add this check here despite repetitiveness to avoid such misleading scenario where shipped reproducible docker builds aren't actually reproducible

Comment on lines 191 to 253
release-summary:
name: release summary
runs-on: ubuntu-latest
needs: [extract-version, verify-and-build, create-manifest]
if: always()
steps:
- name: Report release results
run: |
VERSION=${{ needs.extract-version.outputs.VERSION }}
IMAGE_NAME=${{ env.DOCKER_REPRODUCIBLE_IMAGE_NAME }}

echo "## 🚀 Reproducible Release Summary for ${VERSION}"
echo ""

if [[ "${{ needs.verify-and-build.result }}" == "success" ]]; then
echo "✅ **Reproducibility Verification & Build**: SUCCESS"
echo "- All architectures produce identical binaries"
echo "- Images built and ready for publishing"
else
echo "❌ **Reproducibility Verification & Build**: FAILED"
echo "- Builds are not reproducible OR build failed"
echo "- Release was blocked"
fi

echo ""
if [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then
echo "🧪 **Mode**: DRY RUN"
echo "- Images were built and verified but NOT pushed"
echo "- Ready for real release"
elif [[ "${{ needs.create-manifest.result }}" == "success" ]]; then
echo "✅ **Publication**: SUCCESS"
echo "- Images published to Docker Hub"
echo "- Multi-arch manifests created"
echo ""
echo "### 📦 Published Images"
echo "- \`${IMAGE_NAME}:${VERSION}\`"
echo "- \`${IMAGE_NAME}:latest\`"
echo ""
echo "### 🏗️ Architectures"
echo "- linux/amd64 (\`${IMAGE_NAME}:${VERSION}-amd64\`)"
echo "- linux/arm64 (\`${IMAGE_NAME}:${VERSION}-arm64\`)"
else
echo "❌ **Publication**: FAILED"
echo "- Images were verified but failed to publish"
fi

echo ""
if [[ "${{ needs.verify-and-build.result }}" == "success" ]] && [[ "${{ needs.create-manifest.result }}" == "success" ]] && [[ "${{ github.event.inputs.dry_run }}" != "true" ]]; then
echo "🎉 **Overall**: Secure release completed successfully!"
echo ""
echo "### 🔒 Security Guarantees"
echo "- ✅ Reproducible builds verified"
echo "- ✅ Identical binaries across architectures"
echo "- ✅ No build artifacts tampering"
echo "- ✅ Deterministic build process"
elif [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then
echo "🧪 **Overall**: Dry run completed successfully!"
echo "- Reproducibility verified ✅"
echo "- Ready for real release ✅"
else
echo "🚨 **Overall**: Release failed or incomplete"
echo "- Check logs above for details"
fi
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chong-he do you also want me to remove the release summary here too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I think we can remove the release summary here as well, thanks

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.88-bullseye@sha256:8e3c421122bf4cd3b2a866af41a4dd52d87ad9e315fd2cb5100e87a7187a9816" \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pinning the sha256 for better tracking and reproducibility stability because if any dependency gets updated for that specific image version of rust:1.88, it would also changes its hash history and eventually also impact the reproducibility of the generated lighthouse binary.
If you are ok to proceed with such trade-off, I can remove the sha256 pinning to the rust image.

Regarding removing the whole build-arg, I believe that would be necessary since we are not passing the --platform to the docker build command for the image to identify which one to select.
Nonetheless, if you decide to keep the sha256 for stable reproducibility tracking, then I believe we can't remove this line as it wouldn't be able to detect which sha256 to fetch for which platform, right?

FROM gcr.io/distroless/cc-debian12:nonroot-6755e21ccd99ddead6edc8106ba03888cbeed41a
COPY --from=builder /lighthouse /lighthouse

EXPOSE 30303 30303/udp 9001 8545 8546
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, which ones do you recommend to replace them with?

@MoeMahhouk MoeMahhouk requested a review from chong-he November 5, 2025 16:05
# Remove build ID from the binary to ensure reproducibility across builds
RUST_BUILD_FLAGS += -C link-arg=-Wl,--build-id=none
# Remove metadata hash from symbol names to ensure reproducible builds
RUST_BUILD_FLAGS += -C metadata=''
Copy link
Member

@chong-he chong-he Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need 3 RUST_BUILD_FLAGS here?

(I had this comment in the same time as 2 days ago but probably I forgot to click to publish the comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infra-ci test-reproducible for testing reproducible builds waiting-on-author The reviewer has suggested changes and awaits thier implementation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants