From c68125d48d8e546bf2dce27ca311da6896b47b13 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Wed, 2 Apr 2025 15:03:57 +0100 Subject: [PATCH 01/19] bump version --- crates/signer/src/proto/v1.rs | 205 +++++++++++++++++++++++----------- 1 file changed, 141 insertions(+), 64 deletions(-) diff --git a/crates/signer/src/proto/v1.rs b/crates/signer/src/proto/v1.rs index ba8012c3..36984aa0 100644 --- a/crates/signer/src/proto/v1.rs +++ b/crates/signer/src/proto/v1.rs @@ -24,8 +24,7 @@ impl ResponseState { /// String value of the enum field names used in the ProtoBuf definition. /// /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic - /// use. + /// (if the ProtoBuf definition does not change) and safe for programmatic use. pub fn as_str_name(&self) -> &'static str { match self { Self::Unknown => "UNKNOWN", @@ -90,9 +89,10 @@ pub mod lister_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value + clippy::let_unit_value, )] - use tonic::codegen::{http::Uri, *}; + use tonic::codegen::*; + use tonic::codegen::http::Uri; #[derive(Debug, Clone)] pub struct ListerClient { inner: tonic::client::Grpc, @@ -136,15 +136,16 @@ pub mod lister_client { >::ResponseBody, >, >, - >>::Error: - Into + std::marker::Send + std::marker::Sync, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, { ListerClient::new(InterceptedService::new(inner, interceptor)) } /// Compress requests with the given encoding. /// - /// This requires the server to support it otherwise it might respond - /// with an error. + /// This requires the server to support it otherwise it might respond with an + /// error. #[must_use] pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { self.inner = self.inner.send_compressed(encoding); @@ -175,11 +176,18 @@ pub mod lister_client { pub async fn list_accounts( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/v1.Lister/ListAccounts"); let mut req = request.into_request(); @@ -239,9 +247,10 @@ pub mod account_manager_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value + clippy::let_unit_value, )] - use tonic::codegen::{http::Uri, *}; + use tonic::codegen::*; + use tonic::codegen::http::Uri; #[derive(Debug, Clone)] pub struct AccountManagerClient { inner: tonic::client::Grpc, @@ -285,15 +294,16 @@ pub mod account_manager_client { >::ResponseBody, >, >, - >>::Error: - Into + std::marker::Send + std::marker::Sync, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, { AccountManagerClient::new(InterceptedService::new(inner, interceptor)) } /// Compress requests with the given encoding. /// - /// This requires the server to support it otherwise it might respond - /// with an error. + /// This requires the server to support it otherwise it might respond with an + /// error. #[must_use] pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { self.inner = self.inner.send_compressed(encoding); @@ -324,11 +334,18 @@ pub mod account_manager_client { pub async fn unlock( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/v1.AccountManager/Unlock"); let mut req = request.into_request(); @@ -338,11 +355,18 @@ pub mod account_manager_client { pub async fn lock( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> - { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/v1.AccountManager/Lock"); let mut req = request.into_request(); @@ -352,14 +376,25 @@ pub mod account_manager_client { pub async fn generate( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/v1.AccountManager/Generate"); + let path = http::uri::PathAndQuery::from_static( + "/v1.AccountManager/Generate", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("v1.AccountManager", "Generate")); + req.extensions_mut() + .insert(GrpcMethod::new("v1.AccountManager", "Generate")); self.inner.unary(req, path, codec).await } } @@ -486,9 +521,10 @@ pub mod signer_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value + clippy::let_unit_value, )] - use tonic::codegen::{http::Uri, *}; + use tonic::codegen::*; + use tonic::codegen::http::Uri; #[derive(Debug, Clone)] pub struct SignerClient { inner: tonic::client::Grpc, @@ -532,15 +568,16 @@ pub mod signer_client { >::ResponseBody, >, >, - >>::Error: - Into + std::marker::Send + std::marker::Sync, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, { SignerClient::new(InterceptedService::new(inner, interceptor)) } /// Compress requests with the given encoding. /// - /// This requires the server to support it otherwise it might respond - /// with an error. + /// This requires the server to support it otherwise it might respond with an + /// error. #[must_use] pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { self.inner = self.inner.send_compressed(encoding); @@ -572,9 +609,14 @@ pub mod signer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/v1.Signer/Sign"); let mut req = request.into_request(); @@ -584,10 +626,18 @@ pub mod signer_client { pub async fn multisign( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static("/v1.Signer/Multisign"); let mut req = request.into_request(); @@ -598,39 +648,66 @@ pub mod signer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/v1.Signer/SignBeaconAttestation"); + let path = http::uri::PathAndQuery::from_static( + "/v1.Signer/SignBeaconAttestation", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("v1.Signer", "SignBeaconAttestation")); + req.extensions_mut() + .insert(GrpcMethod::new("v1.Signer", "SignBeaconAttestation")); self.inner.unary(req, path, codec).await } pub async fn sign_beacon_attestations( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/v1.Signer/SignBeaconAttestations"); + let path = http::uri::PathAndQuery::from_static( + "/v1.Signer/SignBeaconAttestations", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("v1.Signer", "SignBeaconAttestations")); + req.extensions_mut() + .insert(GrpcMethod::new("v1.Signer", "SignBeaconAttestations")); self.inner.unary(req, path, codec).await } pub async fn sign_beacon_proposal( &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner.ready().await.map_err(|e| { - tonic::Status::unknown(format!("Service was not ready: {}", e.into())) - })?; + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; let codec = tonic::codec::ProstCodec::default(); - let path = http::uri::PathAndQuery::from_static("/v1.Signer/SignBeaconProposal"); + let path = http::uri::PathAndQuery::from_static( + "/v1.Signer/SignBeaconProposal", + ); let mut req = request.into_request(); - req.extensions_mut().insert(GrpcMethod::new("v1.Signer", "SignBeaconProposal")); + req.extensions_mut() + .insert(GrpcMethod::new("v1.Signer", "SignBeaconProposal")); self.inner.unary(req, path, codec).await } } From d9979a239eaf6fc0365a30c39cf81264d34d9edd Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Mon, 5 May 2025 17:13:43 -0400 Subject: [PATCH 02/19] Successful cross-compilation, but runtime has memory allocation issues --- provisioning/signer.Dockerfile | 70 +++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 85c2be43..bc258b47 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -1,22 +1,72 @@ -FROM lukemathwalker/cargo-chef:latest-rust-1.83 AS chef +# This will be the main build image +FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef +ARG TARGETOS TARGETARCH BUILDPLATFORM WORKDIR /app -FROM chef AS planner +# Planner stage +FROM --platform=${BUILDPLATFORM} chef AS planner +ARG TARGETOS TARGETARCH BUILDPLATFORM COPY . . RUN cargo chef prepare --recipe-path recipe.json -FROM chef AS builder +# Builder stage +FROM --platform=${BUILDPLATFORM} chef AS builder +ARG TARGETOS TARGETARCH BUILDPLATFORM COPY --from=planner /app/recipe.json recipe.json - -RUN cargo chef cook --release --recipe-path recipe.json - -RUN apt-get update && apt-get install -y protobuf-compiler - COPY . . -RUN cargo build --release --bin commit-boost-signer +# Get the latest Protoc since the one in the Debian repo is incredibly old +RUN apt update && apt install -y unzip curl ca-certificates && \ + PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ + if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ + PROTOC_ARCH=x86_64; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ + PROTOC_ARCH=aarch_64; \ + else \ + echo "${BUILDPLATFORM} is not supported."; \ + exit 1; \ + fi && \ + curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ + unzip -q protoc.zip bin/protoc -d /usr && \ + unzip -q protoc.zip "include/google/*" -d /usr && \ + chmod a+x /usr/bin/protoc && \ + rm -rf protoc.zip + +# Build the application +RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ + # We're on x64, cross-compiling for arm64 - get OpenSSL and zlib for arm64, and set up the GCC vars + dpkg --add-architecture arm64 && \ + apt update && \ + apt install -y gcc-aarch64-linux-gnu libssl-dev:arm64 zlib1g-dev:arm64 && \ + rustup target add aarch64-unknown-linux-gnu && \ + TARGET="aarch64-unknown-linux-gnu" && \ + TARGET_FLAG="--target=${TARGET}" && \ + export PKG_CONFIG_ALLOW_CROSS="true" && \ + export PKG_CONFIG_PATH="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ + export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/aarch64-linux-gnu-ld" && \ + export RUSTFLAGS="-L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))"; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ + # We're on arm64, cross-compiling for x64 - get OpenSSL and zlib for x64, and set up the GCC vars + dpkg --add-architecture amd64 && \ + apt update && \ + apt install -y gcc-x86-64-linux-gnu libssl-dev:amd64 zlib1g-dev:amd64 && \ + rustup target add x86_64-unknown-linux-gnu && \ + TARGET="x86_64-unknown-linux-gnu" && \ + TARGET_FLAG="--target=${TARGET}" && \ + export PKG_CONFIG_ALLOW_CROSS="true" && \ + export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig"; \ + export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/x86_64-linux-gnu-ld"; \ + export RUSTFLAGS="-L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))"; \ + fi && \ + # Build the signer - general setup that works with or without cross-compilation + cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json && \ + cargo build ${TARGET_FLAG} --release --bin commit-boost-signer && \ + if [ ! -z "$TARGET" ]; then \ + # If we're cross-compiling, we need to move the binary out of the target dir + mv target/${TARGET}/release/commit-boost-signer target/release/commit-boost-signer; \ + fi -FROM debian:bookworm-20240904-slim AS runtime +FROM debian:bookworm-slim AS runtime WORKDIR /app RUN apt-get update && apt-get install -y \ From 97ef653d602dbf9397de54abdc48ba21f063eb9e Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 6 May 2025 04:09:49 -0400 Subject: [PATCH 03/19] Working with OpenSSL static-linked --- Cargo.lock | 12 ++++++++++++ Cargo.toml | 3 +++ crates/common/Cargo.toml | 4 ++++ crates/common/build.rs | 8 ++++++++ provisioning/signer.Dockerfile | 20 +++++++++++--------- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ebc811a..436d3b65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1494,6 +1494,8 @@ dependencies = [ "ethereum_ssz_derive", "eyre", "jsonwebtoken", + "k256", + "openssl", "pbkdf2 0.12.2", "rand 0.9.0", "reqwest", @@ -3550,6 +3552,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-src" +version = "300.5.0+3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.106" @@ -3558,6 +3569,7 @@ checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] diff --git a/Cargo.toml b/Cargo.toml index aef26a94..14cddf82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,9 @@ edition = "2021" rust-version = "1.83" version = "0.7.0-rc.2" +[workspace.features] +openssl-vendored = ["crates/common/openssl-vendored"] + [workspace.dependencies] aes = "0.8" alloy = { version = "0.12", features = [ diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index df78b046..15c0b8d1 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -41,3 +41,7 @@ tree_hash_derive.workspace = true unicode-normalization.workspace = true url.workspace = true jsonwebtoken.workspace = true +openssl = { version = "0.10", optional = true, features = ["vendored"] } + +[features] +openssl-vendored = ["openssl/vendored"] diff --git a/crates/common/build.rs b/crates/common/build.rs index 9bd10ecb..c24a54cb 100644 --- a/crates/common/build.rs +++ b/crates/common/build.rs @@ -1,6 +1,14 @@ use std::process::Command; fn main() { + let target = std::env::var("TARGET").unwrap(); + let host = std::env::var("HOST").unwrap(); + + if target != host { + println!("cargo:warning=Skipping build script because TARGET != HOST"); + return; + } + let output = Command::new("git").args(["rev-parse", "HEAD"]).output().unwrap(); let git_hash = String::from_utf8(output.stdout).unwrap(); println!("cargo:rustc-env=GIT_HASH={git_hash}"); diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index bc258b47..523a2ff4 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -35,16 +35,17 @@ RUN apt update && apt install -y unzip curl ca-certificates && \ # Build the application RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ # We're on x64, cross-compiling for arm64 - get OpenSSL and zlib for arm64, and set up the GCC vars - dpkg --add-architecture arm64 && \ + rustup target add aarch64-unknown-linux-gnu && \ + #dpkg --add-architecture arm64 && \ apt update && \ apt install -y gcc-aarch64-linux-gnu libssl-dev:arm64 zlib1g-dev:arm64 && \ - rustup target add aarch64-unknown-linux-gnu && \ TARGET="aarch64-unknown-linux-gnu" && \ TARGET_FLAG="--target=${TARGET}" && \ - export PKG_CONFIG_ALLOW_CROSS="true" && \ - export PKG_CONFIG_PATH="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ - export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/aarch64-linux-gnu-ld" && \ - export RUSTFLAGS="-L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))"; \ + # export PKG_CONFIG_ALLOW_CROSS="true" && \ + # export PKG_CONFIG_LIBDIR="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ + export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/aarch64-linux-gnu-gcc" && \ + export RUSTFLAGS="-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))" && \ + FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ # We're on arm64, cross-compiling for x64 - get OpenSSL and zlib for x64, and set up the GCC vars dpkg --add-architecture amd64 && \ @@ -55,12 +56,13 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ TARGET_FLAG="--target=${TARGET}" && \ export PKG_CONFIG_ALLOW_CROSS="true" && \ export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig"; \ - export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/x86_64-linux-gnu-ld"; \ + export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/x86_64-linux-gnu-gcc"; \ export RUSTFLAGS="-L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))"; \ fi && \ # Build the signer - general setup that works with or without cross-compilation - cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json && \ - cargo build ${TARGET_FLAG} --release --bin commit-boost-signer && \ + # cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + cargo build ${TARGET_FLAG} --release --bin commit-boost-signer ${FEATURE_OPENSSL_VENDORED} && \ if [ ! -z "$TARGET" ]; then \ # If we're cross-compiling, we need to move the binary out of the target dir mv target/${TARGET}/release/commit-boost-signer target/release/commit-boost-signer; \ From 91eefe2de57a28c6ddbda38666046cbc711f93d6 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 6 May 2025 04:43:02 -0400 Subject: [PATCH 04/19] Got dynamic linking working, added a feature flag to toggle dynamic vs. static --- provisioning/signer.Dockerfile | 49 ++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 523a2ff4..3c29075d 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -1,17 +1,17 @@ # This will be the main build image FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef -ARG TARGETOS TARGETARCH BUILDPLATFORM +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED WORKDIR /app # Planner stage FROM --platform=${BUILDPLATFORM} chef AS planner -ARG TARGETOS TARGETARCH BUILDPLATFORM +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED COPY . . RUN cargo chef prepare --recipe-path recipe.json # Builder stage FROM --platform=${BUILDPLATFORM} chef AS builder -ARG TARGETOS TARGETARCH BUILDPLATFORM +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED COPY --from=planner /app/recipe.json recipe.json COPY . . @@ -34,30 +34,45 @@ RUN apt update && apt install -y unzip curl ca-certificates && \ # Build the application RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ - # We're on x64, cross-compiling for arm64 - get OpenSSL and zlib for arm64, and set up the GCC vars + # We're on x64, cross-compiling for arm64 rustup target add aarch64-unknown-linux-gnu && \ - #dpkg --add-architecture arm64 && \ apt update && \ - apt install -y gcc-aarch64-linux-gnu libssl-dev:arm64 zlib1g-dev:arm64 && \ + apt install -y gcc-aarch64-linux-gnu && \ + if [ "$OPENSSL_VENDORED" != "true" ]; then \ + # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation + dpkg --add-architecture arm64 && \ + apt update && \ + apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ + export PKG_CONFIG_ALLOW_CROSS="true" && \ + export PKG_CONFIG_LIBDIR="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ + export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu && \ + export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu && \ + FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ + fi && \ TARGET="aarch64-unknown-linux-gnu" && \ TARGET_FLAG="--target=${TARGET}" && \ - # export PKG_CONFIG_ALLOW_CROSS="true" && \ - # export PKG_CONFIG_LIBDIR="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/aarch64-linux-gnu-gcc" && \ - export RUSTFLAGS="-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))" && \ - FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ + export RUSTFLAGS="-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))"; \ elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ - # We're on arm64, cross-compiling for x64 - get OpenSSL and zlib for x64, and set up the GCC vars - dpkg --add-architecture amd64 && \ - apt update && \ - apt install -y gcc-x86-64-linux-gnu libssl-dev:amd64 zlib1g-dev:amd64 && \ + # We're on arm64, cross-compiling for x64 rustup target add x86_64-unknown-linux-gnu && \ + apt update && \ + apt install -y gcc-x86-64-linux-gnu && \ + if [ "$OPENSSL_VENDORED" != "true" ]; then \ + # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation + dpkg --add-architecture amd64 && \ + apt update && \ + apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ + export PKG_CONFIG_ALLOW_CROSS="true" && \ + export PKG_CONFIG_LIBDIR="/usr/lib/x86_64-linux-gnu/pkgconfig" && \ + export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu && \ + export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu && \ + FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ + fi && \ TARGET="x86_64-unknown-linux-gnu" && \ TARGET_FLAG="--target=${TARGET}" && \ - export PKG_CONFIG_ALLOW_CROSS="true" && \ - export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig"; \ export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/x86_64-linux-gnu-gcc"; \ - export RUSTFLAGS="-L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))"; \ + export RUSTFLAGS="-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))"; \ fi && \ # Build the signer - general setup that works with or without cross-compilation # cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json && \ From de09415b8fd994f1b74ed772787aabfd4ac52234 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 6 May 2025 13:13:55 -0400 Subject: [PATCH 05/19] Fixed the vendored build arg --- provisioning/signer.Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 3c29075d..984ba9b4 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -46,7 +46,8 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ export PKG_CONFIG_ALLOW_CROSS="true" && \ export PKG_CONFIG_LIBDIR="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu && \ - export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu && \ + export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu; \ + else \ FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ fi && \ TARGET="aarch64-unknown-linux-gnu" && \ @@ -66,7 +67,8 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ export PKG_CONFIG_ALLOW_CROSS="true" && \ export PKG_CONFIG_LIBDIR="/usr/lib/x86_64-linux-gnu/pkgconfig" && \ export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu && \ - export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu && \ + export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu; \ + else \ FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ fi && \ TARGET="x86_64-unknown-linux-gnu" && \ From 3aee63d1a00c70fce4e86a1a1600f134a2437b41 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 6 May 2025 15:35:58 -0400 Subject: [PATCH 06/19] Reintroduced the cargo chef setup --- provisioning/signer.Dockerfile | 104 ++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 984ba9b4..6de707f0 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -12,72 +12,94 @@ RUN cargo chef prepare --recipe-path recipe.json # Builder stage FROM --platform=${BUILDPLATFORM} chef AS builder ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED +ENV BUILD_VAR_SCRIPT=/tmp/env.sh COPY --from=planner /app/recipe.json recipe.json -COPY . . - -# Get the latest Protoc since the one in the Debian repo is incredibly old -RUN apt update && apt install -y unzip curl ca-certificates && \ - PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ - if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ - PROTOC_ARCH=x86_64; \ - elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ - PROTOC_ARCH=aarch_64; \ - else \ - echo "${BUILDPLATFORM} is not supported."; \ - exit 1; \ - fi && \ - curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ - unzip -q protoc.zip bin/protoc -d /usr && \ - unzip -q protoc.zip "include/google/*" -d /usr && \ - chmod a+x /usr/bin/protoc && \ - rm -rf protoc.zip -# Build the application +# Set up the build environment for cross-compilation if needed RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ # We're on x64, cross-compiling for arm64 rustup target add aarch64-unknown-linux-gnu && \ apt update && \ apt install -y gcc-aarch64-linux-gnu && \ + echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ + echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ if [ "$OPENSSL_VENDORED" != "true" ]; then \ # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation dpkg --add-architecture arm64 && \ apt update && \ apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ - export PKG_CONFIG_ALLOW_CROSS="true" && \ - export PKG_CONFIG_LIBDIR="/usr/lib/aarch64-linux-gnu/pkgconfig" && \ - export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu && \ - export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu; \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ else \ - FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ - fi && \ - TARGET="aarch64-unknown-linux-gnu" && \ - TARGET_FLAG="--target=${TARGET}" && \ - export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/aarch64-linux-gnu-gcc" && \ - export RUSTFLAGS="-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))"; \ + echo "export FEATURE_OPENSSL_VENDORED='--features openssl-vendored'" >> ${BUILD_VAR_SCRIPT}; \ + fi; \ elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ # We're on arm64, cross-compiling for x64 rustup target add x86_64-unknown-linux-gnu && \ apt update && \ apt install -y gcc-x86-64-linux-gnu && \ + echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ + echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ if [ "$OPENSSL_VENDORED" != "true" ]; then \ # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation dpkg --add-architecture amd64 && \ apt update && \ apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ - export PKG_CONFIG_ALLOW_CROSS="true" && \ - export PKG_CONFIG_LIBDIR="/usr/lib/x86_64-linux-gnu/pkgconfig" && \ - export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu && \ - export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu; \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ else \ - FEATURE_OPENSSL_VENDORED="--features openssl-vendored"; \ - fi && \ - TARGET="x86_64-unknown-linux-gnu" && \ - TARGET_FLAG="--target=${TARGET}" && \ - export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/x86_64-linux-gnu-gcc"; \ - export RUSTFLAGS="-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))"; \ + echo "export FEATURE_OPENSSL_VENDORED='--features openssl-vendored'" >> ${BUILD_VAR_SCRIPT}; \ + fi; \ + fi + +# Run cook to prep the build +RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + source ${BUILD_VAR_SCRIPT}; \ + echo "Cross-compilation environment set up for ${TARGET}"; \ + else \ + echo "No cross-compilation needed"; \ + fi && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} + +# Now we can copy the source files +COPY . . + +# Get the latest Protoc since the one in the Debian repo is incredibly old +RUN apt update && apt install -y unzip curl ca-certificates && \ + PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ + if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ + PROTOC_ARCH=x86_64; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ + PROTOC_ARCH=aarch_64; \ + else \ + echo "${BUILDPLATFORM} is not supported."; \ + exit 1; \ + fi && \ + curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ + unzip -q protoc.zip bin/protoc -d /usr && \ + unzip -q protoc.zip "include/google/*" -d /usr && \ + chmod a+x /usr/bin/protoc && \ + rm -rf protoc.zip + +# Build the application +RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + chmod +x ${BUILD_VAR_SCRIPT} && \ + . ${BUILD_VAR_SCRIPT}; \ + echo "Cross-compilation environment set up for ${TARGET}"; \ + else \ + echo "No cross-compilation needed"; \ fi && \ - # Build the signer - general setup that works with or without cross-compilation - # cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json && \ export GIT_HASH=$(git rev-parse HEAD) && \ cargo build ${TARGET_FLAG} --release --bin commit-boost-signer ${FEATURE_OPENSSL_VENDORED} && \ if [ ! -z "$TARGET" ]; then \ From c07c71784ee4c557f8fb778f9db2ef0b328624ae Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 6 May 2025 16:36:57 -0400 Subject: [PATCH 07/19] Ported the cross-compilation stuff into PBS --- provisioning/pbs.Dockerfile | 112 ++++++++++++++++++++++++++++++--- provisioning/signer.Dockerfile | 22 ++++--- 2 files changed, 120 insertions(+), 14 deletions(-) diff --git a/provisioning/pbs.Dockerfile b/provisioning/pbs.Dockerfile index 200c95d2..cac14de0 100644 --- a/provisioning/pbs.Dockerfile +++ b/provisioning/pbs.Dockerfile @@ -1,22 +1,120 @@ -FROM lukemathwalker/cargo-chef:latest-rust-1.83 AS chef +# This will be the main build image +FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED WORKDIR /app -FROM chef AS planner +FROM --platform=${BUILDPLATFORM} chef AS planner +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED COPY . . RUN cargo chef prepare --recipe-path recipe.json -FROM chef AS builder +FROM --platform=${BUILDPLATFORM} chef AS builder +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED +ENV BUILD_VAR_SCRIPT=/tmp/env.sh COPY --from=planner /app/recipe.json recipe.json -RUN cargo chef cook --release --recipe-path recipe.json +# Set up the build environment for cross-compilation if needed +RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ + # We're on x64, cross-compiling for arm64 + rustup target add aarch64-unknown-linux-gnu && \ + apt update && \ + apt install -y gcc-aarch64-linux-gnu && \ + echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ + echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ + if [ "$OPENSSL_VENDORED" != "true" ]; then \ + # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation + dpkg --add-architecture arm64 && \ + apt update && \ + apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ + fi; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ + # We're on arm64, cross-compiling for x64 + rustup target add x86_64-unknown-linux-gnu && \ + apt update && \ + apt install -y gcc-x86-64-linux-gnu && \ + echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ + echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ + if [ "$OPENSSL_VENDORED" != "true" ]; then \ + # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation + dpkg --add-architecture amd64 && \ + apt update && \ + apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ + fi; \ + fi -RUN apt-get update && apt-get install -y protobuf-compiler +# Run cook to prep the build +RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + . ${BUILD_VAR_SCRIPT} && \ + echo "Cross-compilation environment set up for ${TARGET}"; \ + else \ + echo "No cross-compilation needed"; \ + fi && \ + if [ "$OPENSSL_VENDORED" = "true" ]; then \ + echo "Using vendored OpenSSL" && \ + FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ + else \ + echo "Using system OpenSSL"; \ + fi && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} +# Now we can copy the source files - chef cook wants to run before this step COPY . . -RUN cargo build --release --bin commit-boost-pbs +# Get the latest Protoc since the one in the Debian repo is incredibly old +RUN apt update && apt install -y unzip curl ca-certificates && \ + PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ + if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ + PROTOC_ARCH=x86_64; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ + PROTOC_ARCH=aarch_64; \ + else \ + echo "${BUILDPLATFORM} is not supported."; \ + exit 1; \ + fi && \ + curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ + unzip -q protoc.zip bin/protoc -d /usr && \ + unzip -q protoc.zip "include/google/*" -d /usr && \ + chmod a+x /usr/bin/protoc && \ + rm -rf protoc.zip -FROM debian:bookworm-20240904-slim AS runtime +# Build the application +RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + chmod +x ${BUILD_VAR_SCRIPT} && \ + . ${BUILD_VAR_SCRIPT} && \ + echo "Cross-compilation environment set up for ${TARGET}"; \ + else \ + echo "No cross-compilation needed"; \ + fi && \ + if [ "$OPENSSL_VENDORED" = "true" ]; then \ + echo "Using vendored OpenSSL" && \ + FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ + else \ + echo "Using system OpenSSL"; \ + fi && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + cargo build ${TARGET_FLAG} --release --bin commit-boost-pbs ${FEATURE_OPENSSL_VENDORED} && \ + if [ ! -z "$TARGET" ]; then \ + # If we're cross-compiling, we need to move the binary out of the target dir + mv target/${TARGET}/release/commit-boost-pbs target/release/commit-boost-pbs; \ + fi + +# Assemble the runner image +FROM debian:bookworm-slim AS runtime WORKDIR /app RUN apt-get update && apt-get install -y \ diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 6de707f0..354afee0 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -35,8 +35,6 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - else \ - echo "export FEATURE_OPENSSL_VENDORED='--features openssl-vendored'" >> ${BUILD_VAR_SCRIPT}; \ fi; \ elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ # We're on arm64, cross-compiling for x64 @@ -57,22 +55,26 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - else \ - echo "export FEATURE_OPENSSL_VENDORED='--features openssl-vendored'" >> ${BUILD_VAR_SCRIPT}; \ fi; \ fi # Run cook to prep the build RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ - source ${BUILD_VAR_SCRIPT}; \ + . ${BUILD_VAR_SCRIPT} && \ echo "Cross-compilation environment set up for ${TARGET}"; \ else \ echo "No cross-compilation needed"; \ fi && \ + if [ "$OPENSSL_VENDORED" = "true" ]; then \ + echo "Using vendored OpenSSL" && \ + FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ + else \ + echo "Using system OpenSSL"; \ + fi && \ export GIT_HASH=$(git rev-parse HEAD) && \ cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} -# Now we can copy the source files +# Now we can copy the source files - chef cook wants to run before this step COPY . . # Get the latest Protoc since the one in the Debian repo is incredibly old @@ -95,11 +97,17 @@ RUN apt update && apt install -y unzip curl ca-certificates && \ # Build the application RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ chmod +x ${BUILD_VAR_SCRIPT} && \ - . ${BUILD_VAR_SCRIPT}; \ + . ${BUILD_VAR_SCRIPT} && \ echo "Cross-compilation environment set up for ${TARGET}"; \ else \ echo "No cross-compilation needed"; \ fi && \ + if [ "$OPENSSL_VENDORED" = "true" ]; then \ + echo "Using vendored OpenSSL" && \ + FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ + else \ + echo "Using system OpenSSL"; \ + fi && \ export GIT_HASH=$(git rev-parse HEAD) && \ cargo build ${TARGET_FLAG} --release --bin commit-boost-signer ${FEATURE_OPENSSL_VENDORED} && \ if [ ! -z "$TARGET" ]; then \ From 699b7ec9eeb4fe2c5d1398095047b82df81afc26 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 7 May 2025 13:52:08 -0400 Subject: [PATCH 08/19] Split the dockerfiles into separate builder / image definitions --- .gitignore | 3 +- build-linux.sh | 144 +++++++++++++++++++++++++++++++++ provisioning/build.Dockerfile | 120 +++++++++++++++++++++++++++ provisioning/cli.Dockerfile | 0 provisioning/pbs.Dockerfile | 137 +++---------------------------- provisioning/signer.Dockerfile | 6 +- 6 files changed, 277 insertions(+), 133 deletions(-) create mode 100755 build-linux.sh create mode 100644 provisioning/build.Dockerfile create mode 100644 provisioning/cli.Dockerfile diff --git a/.gitignore b/.gitignore index b8eaa77a..e48792b4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # will have compiled files and executables debug/ target/ +build/ # These are backup files generated by rustfmt **/*.rs.bk @@ -14,4 +15,4 @@ cb.docker-compose.yml targets.json .idea/ logs -.vscode/ \ No newline at end of file +.vscode/ diff --git a/build-linux.sh b/build-linux.sh new file mode 100755 index 00000000..a7266bd9 --- /dev/null +++ b/build-linux.sh @@ -0,0 +1,144 @@ +#!/bin/bash + +# This script will build the Commit-Boost applications and modules for local Linux development. + +# ================= +# === Functions === +# ================= + +# Print a failure message to stderr and exit +fail() { + MESSAGE=$1 + RED='\033[0;31m' + RESET='\033[;0m' + >&2 echo -e "\n${RED}**ERROR**\n$MESSAGE${RESET}\n" + exit 1 +} + + +# Builds the CLI binaries for Linux +# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static +build_cli() { + echo "Building CLI binaries..." + docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-cli . || fail "Error building CLI." + echo "done!" + + # Flatten the folder structure for easier referencing + mv build/$VERSION/linux_amd64/commit-boost-cli build/$VERSION/commit-boost-cli-linux-amd64 + mv build/$VERSION/linux_arm64/commit-boost-cli build/$VERSION/commit-boost-cli-linux-arm64 + + # Clean up the empty directories + rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64 + echo "done!" +} + + +# Builds the PBS module binaries for Linux and the Docker image(s) +# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static +build_pbs() { + echo "Building PBS binaries..." + docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-pbs . || fail "Error building PBS binaries." + echo "done!" + + # Flatten the folder structure for easier referencing + mv build/$VERSION/linux_amd64/commit-boost-pbs build/$VERSION/commit-boost-pbs-linux-amd64 + mv build/$VERSION/linux_arm64/commit-boost-pbs build/$VERSION/commit-boost-pbs-linux-arm64 + + # Clean up the empty directories + rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64 + + echo "Building PBS Docker image..." + # If uploading, make and push a manifest + if [ "$LOCAL_UPLOAD" = true ]; then + if [ -z "$LOCAL_DOCKER_REGISTRY" ]; then + fail "LOCAL_DOCKER_REGISTRY must be set to upload to a local registry." + fi + docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/$VERSION -t $LOCAL_DOCKER_REGISTRY/commit-boost/pbs:$VERSION -f provisioning/pbs.Dockerfile --push . || fail "Error building PBS image." + else + docker buildx build --rm --load --build-arg BINARIES_PATH=build/$VERSION -t commit-boost/pbs:$VERSION -f provisioning/pbs.Dockerfile . || fail "Error building PBS image." + fi + echo "done!" +} + + +# Builds the Signer module binaries for Linux and the Docker image(s) +# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static +build_signer() { + echo "Building Signer binaries..." + docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-signer . || fail "Error building Signer binaries." + echo "done!" + + # Flatten the folder structure for easier referencing + mv build/$VERSION/linux_amd64/commit-boost-signer build/$VERSION/commit-boost-signer-linux-amd64 + mv build/$VERSION/linux_arm64/commit-boost-signer build/$VERSION/commit-boost-signer-linux-arm64 + + # Clean up the empty directories + rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64 + + echo "Building Signer Docker image..." + # If uploading, make and push a manifest + if [ "$LOCAL_UPLOAD" = true ]; then + if [ -z "$LOCAL_DOCKER_REGISTRY" ]; then + fail "LOCAL_DOCKER_REGISTRY must be set to upload to a local registry." + fi + docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/$VERSION -t $LOCAL_DOCKER_REGISTRY/commit-boost/signer:$VERSION -f provisioning/signer.Dockerfile --push . || fail "Error building Signer image." + else + docker buildx build --rm --load --build-arg BINARIES_PATH=build/$VERSION -t commit-boost/signer:$VERSION -f provisioning/signer.Dockerfile . || fail "Error building Signer image." + fi + echo "done!" +} + + +# Print usage +usage() { + echo "Usage: build.sh [options] -v " + echo "This script assumes it is in the commit-boost-client repository directory." + echo "Options:" + echo $'\t-a\tBuild all of the artifacts (CLI, PBS, and Signer, along with Docker images)' + echo $'\t-c\tBuild the Commit-Boost CLI binaries' + echo $'\t-p\tBuild the PBS module binary and its Docker container' + echo $'\t-s\tBuild the Signer module binary and its Docker container' + echo $'\t-o\tWhen passed with a build, upload the resulting image tags to a local Docker registry specified in $LOCAL_DOCKER_REGISTRY' + exit 0 +} + + +# ================= +# === Main Body === +# ================= + +# Parse arguments +while getopts "acpsov:" FLAG; do + case "$FLAG" in + a) CLI=true PBS=true SIGNER=true ;; + c) CLI=true ;; + p) PBS=true ;; + s) SIGNER=true ;; + o) LOCAL_UPLOAD=true ;; + v) VERSION="$OPTARG" ;; + *) usage ;; + esac +done +if [ -z "$VERSION" ]; then + usage +fi + +# Cleanup old artifacts +rm -rf build/$VERSION/* +mkdir -p build/$VERSION + +# Make a multiarch builder, ignore if it's already there +docker buildx create --name multiarch-builder --driver docker-container --use > /dev/null 2>&1 +# NOTE: if using a local repo with a private CA, you will have to follow these steps to add the CA to the builder: +# https://stackoverflow.com/a/73585243 + +# Build the artifacts +if [ "$CLI" = true ]; then + build_cli +fi +if [ "$PBS" = true ]; then + build_pbs +fi +if [ "$SIGNER" = true ]; then + build_signer +fi diff --git a/provisioning/build.Dockerfile b/provisioning/build.Dockerfile new file mode 100644 index 00000000..83679ed5 --- /dev/null +++ b/provisioning/build.Dockerfile @@ -0,0 +1,120 @@ +# This will be the main build image +FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE +WORKDIR /app + +FROM --platform=${BUILDPLATFORM} chef AS planner +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM --platform=${BUILDPLATFORM} chef AS builder +ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE +RUN test -n "$TARGET_CRATE" || (echo "TARGET_CRATE must be set to the service / binary you want to build" && false) +ENV BUILD_VAR_SCRIPT=/tmp/env.sh +COPY --from=planner /app/recipe.json recipe.json + +# Get the latest Protoc since the one in the Debian repo is incredibly old +RUN apt update && apt install -y unzip curl ca-certificates && \ + PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ + if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ + PROTOC_ARCH=x86_64; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ + PROTOC_ARCH=aarch_64; \ + else \ + echo "${BUILDPLATFORM} is not supported."; \ + exit 1; \ + fi && \ + curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ + unzip -q protoc.zip bin/protoc -d /usr && \ + unzip -q protoc.zip "include/google/*" -d /usr && \ + chmod a+x /usr/bin/protoc && \ + rm -rf protoc.zip + +# Set up the build environment for cross-compilation if needed +RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ + # We're on x64, cross-compiling for arm64 + rustup target add aarch64-unknown-linux-gnu && \ + apt update && \ + apt install -y gcc-aarch64-linux-gnu && \ + echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ + echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ + if [ "$OPENSSL_VENDORED" != "true" ]; then \ + # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation + dpkg --add-architecture arm64 && \ + apt update && \ + apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ + fi; \ + elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ + # We're on arm64, cross-compiling for x64 + rustup target add x86_64-unknown-linux-gnu && \ + apt update && \ + apt install -y gcc-x86-64-linux-gnu && \ + echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ + echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ + if [ "$OPENSSL_VENDORED" != "true" ]; then \ + # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation + dpkg --add-architecture amd64 && \ + apt update && \ + apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ + fi; \ + fi + +# Run cook to prep the build +RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + . ${BUILD_VAR_SCRIPT} && \ + echo "Cross-compilation environment set up for ${TARGET}"; \ + else \ + echo "No cross-compilation needed"; \ + fi && \ + if [ "$OPENSSL_VENDORED" = "true" ]; then \ + echo "Using vendored OpenSSL" && \ + FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ + else \ + echo "Using system OpenSSL"; \ + fi && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} + +# Now we can copy the source files - chef cook wants to run before this step +COPY . . + +# Build the application +RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + chmod +x ${BUILD_VAR_SCRIPT} && \ + . ${BUILD_VAR_SCRIPT} && \ + echo "Cross-compilation environment set up for ${TARGET}"; \ + else \ + echo "No cross-compilation needed"; \ + fi && \ + if [ "$OPENSSL_VENDORED" = "true" ]; then \ + echo "Using vendored OpenSSL" && \ + FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ + else \ + echo "Using system OpenSSL"; \ + fi && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + cargo build ${TARGET_FLAG} --release --bin ${TARGET_CRATE} ${FEATURE_OPENSSL_VENDORED} && \ + if [ ! -z "$TARGET" ]; then \ + # If we're cross-compiling, we need to move the binary out of the target dir + mv target/${TARGET}/release/${TARGET_CRATE} target/release/${TARGET_CRATE}; \ + fi + +# Copy the output +FROM scratch AS output +ARG TARGET_CRATE +COPY --from=builder /app/target/release/${TARGET_CRATE} /${TARGET_CRATE} diff --git a/provisioning/cli.Dockerfile b/provisioning/cli.Dockerfile new file mode 100644 index 00000000..e69de29b diff --git a/provisioning/pbs.Dockerfile b/provisioning/pbs.Dockerfile index cac14de0..9eff5890 100644 --- a/provisioning/pbs.Dockerfile +++ b/provisioning/pbs.Dockerfile @@ -1,138 +1,19 @@ -# This will be the main build image -FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED -WORKDIR /app - -FROM --platform=${BUILDPLATFORM} chef AS planner -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -FROM --platform=${BUILDPLATFORM} chef AS builder -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED -ENV BUILD_VAR_SCRIPT=/tmp/env.sh -COPY --from=planner /app/recipe.json recipe.json - -# Set up the build environment for cross-compilation if needed -RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ - # We're on x64, cross-compiling for arm64 - rustup target add aarch64-unknown-linux-gnu && \ - apt update && \ - apt install -y gcc-aarch64-linux-gnu && \ - echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ - echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ - if [ "$OPENSSL_VENDORED" != "true" ]; then \ - # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation - dpkg --add-architecture arm64 && \ - apt update && \ - apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ - echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ - echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - fi; \ - elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ - # We're on arm64, cross-compiling for x64 - rustup target add x86_64-unknown-linux-gnu && \ - apt update && \ - apt install -y gcc-x86-64-linux-gnu && \ - echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ - echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ - if [ "$OPENSSL_VENDORED" != "true" ]; then \ - # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation - dpkg --add-architecture amd64 && \ - apt update && \ - apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ - echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ - echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - fi; \ - fi - -# Run cook to prep the build -RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ - . ${BUILD_VAR_SCRIPT} && \ - echo "Cross-compilation environment set up for ${TARGET}"; \ - else \ - echo "No cross-compilation needed"; \ - fi && \ - if [ "$OPENSSL_VENDORED" = "true" ]; then \ - echo "Using vendored OpenSSL" && \ - FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ - else \ - echo "Using system OpenSSL"; \ - fi && \ - export GIT_HASH=$(git rev-parse HEAD) && \ - cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} - -# Now we can copy the source files - chef cook wants to run before this step -COPY . . - -# Get the latest Protoc since the one in the Debian repo is incredibly old -RUN apt update && apt install -y unzip curl ca-certificates && \ - PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ - if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ - PROTOC_ARCH=x86_64; \ - elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ - PROTOC_ARCH=aarch_64; \ - else \ - echo "${BUILDPLATFORM} is not supported."; \ - exit 1; \ - fi && \ - curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ - unzip -q protoc.zip bin/protoc -d /usr && \ - unzip -q protoc.zip "include/google/*" -d /usr && \ - chmod a+x /usr/bin/protoc && \ - rm -rf protoc.zip - -# Build the application -RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ - chmod +x ${BUILD_VAR_SCRIPT} && \ - . ${BUILD_VAR_SCRIPT} && \ - echo "Cross-compilation environment set up for ${TARGET}"; \ - else \ - echo "No cross-compilation needed"; \ - fi && \ - if [ "$OPENSSL_VENDORED" = "true" ]; then \ - echo "Using vendored OpenSSL" && \ - FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ - else \ - echo "Using system OpenSSL"; \ - fi && \ - export GIT_HASH=$(git rev-parse HEAD) && \ - cargo build ${TARGET_FLAG} --release --bin commit-boost-pbs ${FEATURE_OPENSSL_VENDORED} && \ - if [ ! -z "$TARGET" ]; then \ - # If we're cross-compiling, we need to move the binary out of the target dir - mv target/${TARGET}/release/commit-boost-pbs target/release/commit-boost-pbs; \ - fi - -# Assemble the runner image -FROM debian:bookworm-slim AS runtime -WORKDIR /app - +FROM debian:bookworm-slim +ARG BINARIES_PATH TARGETOS TARGETARCH +COPY ${BINARIES_PATH}/commit-boost-pbs-${TARGETOS}-${TARGETARCH} /usr/local/bin RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ libssl3 \ libssl-dev \ - curl \ - && apt-get clean autoclean \ - && rm -rf /var/lib/apt/lists/* - -COPY --from=builder /app/target/release/commit-boost-pbs /usr/local/bin + curl && \ + # Cleanup + apt-get clean autoclean && \ + rm -rf /var/lib/apt/lists/* +# Create a non-root user to run the application RUN groupadd -g 10001 commitboost && \ useradd -u 10001 -g commitboost -s /sbin/nologin commitboost USER commitboost -ENTRYPOINT ["/usr/local/bin/commit-boost-pbs"] - - - +ENTRYPOINT ["/usr/local/bin/commit-boost-pbs"] \ No newline at end of file diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 354afee0..6c5ac045 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -115,6 +115,7 @@ RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ mv target/${TARGET}/release/commit-boost-signer target/release/commit-boost-signer; \ fi +# Assemble the runner image FROM debian:bookworm-slim AS runtime WORKDIR /app @@ -133,7 +134,4 @@ RUN groupadd -g 10001 commitboost && \ useradd -u 10001 -g commitboost -s /sbin/nologin commitboost USER commitboost -ENTRYPOINT ["/usr/local/bin/commit-boost-signer"] - - - +ENTRYPOINT ["/usr/local/bin/commit-boost-signer"] \ No newline at end of file From 7165f129ae7a299b69649c7904ef3b30787ee86e Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 7 May 2025 17:48:42 -0400 Subject: [PATCH 09/19] Added a build guide --- docs/docs/get_started/building.md | 185 ++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 docs/docs/get_started/building.md diff --git a/docs/docs/get_started/building.md b/docs/docs/get_started/building.md new file mode 100644 index 00000000..d38b447f --- /dev/null +++ b/docs/docs/get_started/building.md @@ -0,0 +1,185 @@ +# Building Commit-Boost from Source + +Commit-Boost's components are all written in [Rust](https://www.rust-lang.org/). This guide will walk you through the setup required to build them from source. It assumes you are on a Debian or Debian-based system (e.g., Ubuntu, Linux Mint, Pop OS). For other systems, please adapt the steps for your system's package manager accordingly. + + +## Building via the Docker Builder + +For convenience, Commit-Boost has Dockerized the build environment for Linux `x64` and `arm64` platforms. All of the prerequisites, cross-compilation tooling, and configuration are handled by the builder image. If you would like to build the CLI, PBS module, or Signer binaries and Docker images from source, you are welcome to use the Docker builder process. + +To use the builder, you will need to have [Docker Engine](https://docs.docker.com/engine/install/) installed on your system. Please follow the instructions to install it first. + +:::note +The build script assumes that you've added your user account to the `docker` group with the Linux [post-install steps](https://docs.docker.com/engine/install/linux-postinstall/). If you haven't, then you'll need to run the build script below as `root` or modify it so each call to `docker` within it is run as the root user (e.g., with `sudo`). +::: + +We provide a build script called `build-linux.sh` to automate the process: + +``` +$ ./build-linux.sh +Usage: build.sh [options] -v +This script assumes it is in the commit-boost-client repository directory. +Options: + -a Build all of the artifacts (CLI, PBS, and Signer, along with Docker images) + -c Build the Commit-Boost CLI binaries + -p Build the PBS module binary and its Docker container + -s Build the Signer module binary and its Docker container + -o When passed with a build, upload the resulting image tags to a local Docker registry specified in $LOCAL_DOCKER_REGISTRY +``` + +The script utilizes Docker's [buildx](https://docs.docker.com/reference/cli/docker/buildx/) system to both create a multiarch-capable builder and cross-compile for both Linux architectures. You are free to modify it to produce only the artifacts relevant to you if so desired. + +The `version` provided will be used to house the output binaries in `./build/$VERSION`, and act as the version tag for the Docker images when they're added to your local system or uploaded to your local Docker repository. + + +## Building Manually + +If you don't want to use the Docker builder, you can compile the Commit-Boost artifacts locally. The following instructions assume a Debian or Debian-based system (e.g., Ubuntu, Linux Mint, Pop OS) for simplicity. For other systems, please adapt any relevant instructions to your environment accordingly. + + +### Prerequisites + +Requirements: + +- Rust 1.83+ +- GCC (or another C compiler of your choice) +- OpenSSL development libraries +- Protobuf Compiler (`protoc`) + +Start by installing Rust if you don't already have it. Follow [the official directions](https://www.rust-lang.org/learn/get-started) to install it and bring it up to date. + +Install the dependencies: + +```bash +sudo apt update && sudo apt install -y openssl ca-certificates libssl3 libssl-dev build-essential pkg-config curl +``` + +Install the Protobuf compiler: + +:::note +While many package repositories provide a `protobuf-compiler` package in lieu of manually installing protoc, we've found at the time of this writing that most of them use v3.21 which is quite out of date. We recommend getting the latest version manually. +::: + +```bash +PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') +MACHINE_ARCH=$(uname -m) +case "${MACHINE_ARCH}" in + aarch64) PROTOC_ARCH=aarch_64;; + x86_64) PROTOC_ARCH=x86_64;; + *) echo "${MACHINE_ARCH} is not supported."; exit 1;; +esac +curl -sLo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip +sudo unzip -q protoc.zip bin/protoc -d /usr +sudo unzip -q protoc.zip "include/google/*" -d /usr +sudo chmod a+x /usr/bin/protoc +rm -rf protoc.zip +``` + +With the prerequisites set up, pull the repository: +```bash +git clone https://github.com/Commit-Boost/commit-boost-client +``` + +Check out the `stable` branch which houses the latest release: +```bash +cd commit-boost-client && git checkout stable +``` + +Finally, update the submodules: +``` +git submodule update --init --recursive +``` + +Your build environment should now be ready to use. + + +### Building the CLI + +To build the CLI, run: +``` +cargo build --release --bin commit-boost-cli +``` + +This will create a binary in `./target/release/commit-boost-cli`. Confirm that it works: +``` +./target/release/commit-boost-cli --version +``` + +You can now use this to generate the Docker Compose file to drive the other modules if desired. See the [configuration](./configuration.md) guide for more information. + + +### Building the PBS Module + +To build PBS, run: +``` +cargo build --release --bin commit-boost-pbs +``` + +This will create a binary in `./target/release/commit-boost-pbs`. To verify it works, create [a TOML configuration](./configuration.md) for the PBS module (e.g., `cb-config.toml`). + +As a quick example, we'll use this configuration that connects to the Flashbots relay on the Hoodi network: +```toml +chain = "Hoodi" + +[pbs] +port = 18550 +with_signer = true + +[[relays]] +url = "https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net" + +[metrics] +enabled = true + +[signer] +[signer.local.loader] +format = "lighthouse" +keys_path = "/tmp/keys" +secrets_path = "/tmp/secrets" +``` + +Set the path to it in the `CB_CONFIG` environment variable and run the binary: +``` +CB_CONFIG=cb-config.toml ./target/release/commit-boost-pbs +``` + +If it works, you should see output like this: +``` +2025-05-07T21:09:17.407245Z WARN No metrics server configured +2025-05-07T21:09:17.407257Z INFO starting PBS service version="0.7.0" commit_hash="58082edb1213596667afe8c3950cd997ab85f4f3" addr=127.0.0.1:18550 events_subs=0 chain=Hoodi +2025-05-07T21:09:17.746855Z INFO : new request ua="" relay_check=true method=/eth/v1/builder/status req_id=5c405c33-0496-42ea-a35d-a7a01dbba356 +2025-05-07T21:09:17.896196Z INFO : relay check successful method=/eth/v1/builder/status req_id=5c405c33-0496-42ea-a35d-a7a01dbba356 +``` + +If you do, then the binary works. + + +### Building the Signer Module + +To build the Signer, run: +``` +cargo build --release --bin commit-boost-signer +``` + +This will create a binary in `./target/release/commit-boost-signer`. To verify it works, create [a TOML configuration](./configuration.md) for the Signer module (e.g., `cb-config.toml`). We'll use the example in the PBS build section above. + +The signer needs the following environment variables set: +- `CB_CONFIG` = path of your config file. +- `CB_JWTS` = a dummy key-value pair of [JWT](https://en.wikipedia.org/wiki/JSON_Web_Token) values for various services. Since we don't need them for the sake of just testing the binary, we can use something like `"test_jwts=dummy"`. +- `CB_SIGNER_PORT` = the network port to listen for signer requests on. Default is `20000`. + +Set these values, create the `keys` and `secrets` directories listed in the configuration file, and run the binary: + +``` +mkdir -p /tmp/keys && mkdir -p /tmp/secrets +CB_CONFIG=cb-config.toml CB_JWTS="test_jwts=dummy" CB_SIGNER_PORT=20000 ./target/release/commit-boost-signer +``` + +You should see output like this: +``` +2025-05-07T21:43:46.385535Z WARN Proxy store not configured. Proxies keys and delegations will not be persisted +2025-05-07T21:43:46.393507Z INFO Starting signing service version="0.7.0" commit_hash="58082edb1213596667afe8c3950cd997ab85f4f3" modules=["test_jwts"] port=20000 loaded_consensus=0 loaded_proxies=0 +2025-05-07T21:43:46.393574Z WARN No metrics server configured +``` + +If you do, then the binary works. \ No newline at end of file From 9438dae97bbb5d13032519c34ca9ad4e7c468137 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 13 May 2025 02:25:24 -0400 Subject: [PATCH 10/19] Refactored the Github release action to use the Docker builder --- .github/workflows/release.yml | 159 ++++++++++++++++++++++++++------- provisioning/build.Dockerfile | 21 +---- provisioning/cli.Dockerfile | 0 provisioning/protoc.sh | 57 ++++++++++++ provisioning/signer.Dockerfile | 134 ++------------------------- 5 files changed, 194 insertions(+), 177 deletions(-) delete mode 100644 provisioning/cli.Dockerfile create mode 100755 provisioning/protoc.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 906c01f3..40745fbb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,11 +10,86 @@ permissions: packages: write jobs: - build-binaries: + # Builds the x64 and arm64 binaries for Linux, for all 3 crates, via the Docker builder + build-binaries-linux: strategy: matrix: target: - - x86_64-unknown-linux-gnu + - amd64 + - arm64 + name: + - commit-boost-cli + - commit-boost-pbs + - commit-boost-signer + include: + - target: amd64 + package-suffix: x86-64 + - target: arm64 + package-suffix: arm64 + - name: commit-boost-cli + target-crate: cli + - name: commit-boost-pbs + target-crate: pbs + - name: commit-boost-signer + target-crate: signer + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: "stable" + fetch-depth: 0 + submodules: true + + - name: Log commit hash + run: | + echo "Releasing commit: $(git rev-parse HEAD)" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build binary (Linux) + uses: docker/build-push-action@v6 + with: + context: . + push: false + platforms: linux/amd64,linux/arm64 + cache-from: type=registry,ref=ghcr.io/commit-boost/buildcache:${{ matrix.target-crate}} + cache-to: type=registry,ref=ghcr.io/commit-boost/buildcache:${{ matrix.target-crate }},mode=max + file: provisioning/build.Dockerfile + outputs: type=local,dest=build + build-args: | + TARGET_CRATE=${{ matrix.name }} + + - name: Package binary (Linux) + run: | + cd build/linux_${{ matrix.target }} + tar -czvf ${{ matrix.name }}-${{ github.ref_name }}-linux_${{ matrix.package-suffix }}.tar.gz ${{ matrix.name }} + mv ${{ matrix.name }}-${{ github.ref_name }}-linux_${{ matrix.package-suffix }}.tar.gz ../../ + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }}-${{ github.ref_name }}-linux_${{ matrix.package-suffix }} + path: | + ${{ matrix.name }}-${{ github.ref_name }}-linux_${{ matrix.package-suffix }}.tar.gz + + # Builds the arm64 binaries for Darwin, for all 3 crates, natively + build-binaries-darwin: + strategy: + matrix: + target: + # x64 requires macos-latest-large which is not available in the free tier # - x86_64-apple-darwin - aarch64-apple-darwin name: @@ -22,10 +97,8 @@ jobs: - commit-boost-pbs - commit-boost-signer include: - - target: x86_64-unknown-linux-gnu - os: ubuntu-latest # - target: x86_64-apple-darwin - # os: macos-latest + # os: macos-latest-large - target: aarch64-apple-darwin os: macos-latest runs-on: ${{ matrix.os }} @@ -41,6 +114,12 @@ jobs: run: | echo "Releasing commit: $(git rev-parse HEAD)" + - name: Install Protoc + run: + # Brew's version is much more up to date than the Linux ones, and installing the latest via script runs into curl issues so for now, brew's easier to use + # provisioning/protoc.sh + brew install protobuf + - name: Cache Cargo registry uses: actions/cache@v3 with: @@ -63,48 +142,25 @@ jobs: ${{ runner.os }}-cargo-build-${{ matrix.target }}- ${{ runner.os }}-cargo-build- - - name: Install protoc (Ubuntu) - if: runner.os == 'Linux' - run: sudo apt-get install protobuf-compiler - - - name: Install protoc (macOS) - if: runner.os == 'macOS' - run: brew install protobuf - - - name: Set up Rust - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - target: ${{ matrix.target }} - - - name: Build binary + - name: Build binary (Darwin) run: cargo build --release --target ${{ matrix.target }} --bin ${{ matrix.name }} - env: - CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: gcc - name: Package binary (Unix) - if: runner.os != 'Windows' run: | cd target/${{ matrix.target }}/release tar -czvf ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.tar.gz ${{ matrix.name }} mv ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.tar.gz ../../../ - - name: Package binary (Windows) - if: runner.os == 'Windows' - run: | - 7z a ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.zip target\${{ matrix.target }}\release\${{ matrix.name }}.exe - - name: Upload artifact uses: actions/upload-artifact@v4 with: name: ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }} path: | - ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.${{ runner.os == 'Windows' && 'zip' || 'tar.gz' }} + ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.tar.gz + # Builds the PBS Docker image build-and-push-pbs-docker: - needs: [build-binaries] + needs: [build-binaries-linux] runs-on: ubuntu-latest steps: - name: Checkout code @@ -114,6 +170,20 @@ jobs: fetch-depth: 0 submodules: true + - name: Download binary archives + uses: actions/download-artifact@v4 + with: + path: ./artifacts + pattern: "commit-boost-*" + + - name: Extract binaries + run: | + mkdir -p ./artifacts/bin + tar -xzf ./artifacts/commit-boost-pbs-${{ github.ref_name }}-linux_x86-64/commit-boost-pbs-${{ github.ref_name }}-linux_x86-64.tar.gz -C ./artifacts/bin + mv ./artifacts/bin/commit-boost-pbs ./artifacts/bin/commit-boost-pbs-linux-amd64 + tar -xzf ./artifacts/commit-boost-pbs-${{ github.ref_name }}-linux_arm64/commit-boost-pbs-${{ github.ref_name }}-linux_arm64.tar.gz -C ./artifacts/bin + mv ./artifacts/bin/commit-boost-pbs ./artifacts/bin/commit-boost-pbs-linux-arm64 + - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -133,6 +203,8 @@ jobs: context: . push: true platforms: linux/amd64,linux/arm64 + build-args: | + BINARIES_PATH=./artifacts/bin tags: | ghcr.io/commit-boost/pbs:${{ github.ref_name }} ${{ !contains(github.ref_name, 'rc') && 'ghcr.io/commit-boost/pbs:latest' || '' }} @@ -140,8 +212,9 @@ jobs: cache-to: type=registry,ref=ghcr.io/commit-boost/pbs:buildcache,mode=max file: provisioning/pbs.Dockerfile + # Builds the Signer Docker image build-and-push-signer-docker: - needs: [build-binaries] + needs: [build-binaries-linux] runs-on: ubuntu-latest steps: - name: Checkout code @@ -151,6 +224,20 @@ jobs: fetch-depth: 0 submodules: true + - name: Download binary archives + uses: actions/download-artifact@v4 + with: + path: ./artifacts + pattern: "commit-boost-*" + + - name: Extract binaries + run: | + mkdir -p ./artifacts/bin + tar -xzf ./artifacts/commit-boost-signer-${{ github.ref_name }}-linux_x86-64/commit-boost-signer-${{ github.ref_name }}-linux_x86-64.tar.gz -C ./artifacts/bin + mv ./artifacts/bin/commit-boost-signer ./artifacts/bin/commit-boost-signer-linux-amd64 + tar -xzf ./artifacts/commit-boost-signer-${{ github.ref_name }}-linux_arm64/commit-boost-signer-${{ github.ref_name }}-linux_arm64.tar.gz -C ./artifacts/bin + mv ./artifacts/bin/commit-boost-signer ./artifacts/bin/commit-boost-signer-linux-arm64 + - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -170,6 +257,8 @@ jobs: context: . push: true platforms: linux/amd64,linux/arm64 + build-args: | + BINARIES_PATH=./artifacts/bin tags: | ghcr.io/commit-boost/signer:${{ github.ref_name }} ${{ !contains(github.ref_name, 'rc') && 'ghcr.io/commit-boost/signer:latest' || '' }} @@ -177,9 +266,11 @@ jobs: cache-to: type=registry,ref=ghcr.io/commit-boost/signer:buildcache,mode=max file: provisioning/signer.Dockerfile + # Creates a draft release on GitHub with the binaries finalize-release: needs: - - build-binaries + - build-binaries-linux + - build-binaries-darwin - build-and-push-pbs-docker - build-and-push-signer-docker runs-on: ubuntu-latest diff --git a/provisioning/build.Dockerfile b/provisioning/build.Dockerfile index 83679ed5..a4eb3723 100644 --- a/provisioning/build.Dockerfile +++ b/provisioning/build.Dockerfile @@ -14,23 +14,6 @@ RUN test -n "$TARGET_CRATE" || (echo "TARGET_CRATE must be set to the service / ENV BUILD_VAR_SCRIPT=/tmp/env.sh COPY --from=planner /app/recipe.json recipe.json -# Get the latest Protoc since the one in the Debian repo is incredibly old -RUN apt update && apt install -y unzip curl ca-certificates && \ - PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ - if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ - PROTOC_ARCH=x86_64; \ - elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ - PROTOC_ARCH=aarch_64; \ - else \ - echo "${BUILDPLATFORM} is not supported."; \ - exit 1; \ - fi && \ - curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ - unzip -q protoc.zip bin/protoc -d /usr && \ - unzip -q protoc.zip "include/google/*" -d /usr && \ - chmod a+x /usr/bin/protoc && \ - rm -rf protoc.zip - # Set up the build environment for cross-compilation if needed RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ # We're on x64, cross-compiling for arm64 @@ -90,6 +73,10 @@ RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ export GIT_HASH=$(git rev-parse HEAD) && \ cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} +# Get the latest Protoc since the one in the Debian repo is incredibly old +COPY provisioning/protoc.sh provisioning/protoc.sh +RUN provisioning/protoc.sh + # Now we can copy the source files - chef cook wants to run before this step COPY . . diff --git a/provisioning/cli.Dockerfile b/provisioning/cli.Dockerfile deleted file mode 100644 index e69de29b..00000000 diff --git a/provisioning/protoc.sh b/provisioning/protoc.sh new file mode 100755 index 00000000..7f66a656 --- /dev/null +++ b/provisioning/protoc.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# This script installs the latest version of protoc (Protocol Buffers Compiler) from the official GitHub repository. + +# Print a failure message to stderr and exit +fail() { + MESSAGE=$1 + RED='\033[0;31m' + RESET='\033[;0m' + >&2 echo -e "\n${RED}**ERROR**\n$MESSAGE${RESET}\n" + exit 1 +} + +# Get the OS +case "$(uname)" in + Darwin*) + PROTOC_OS="osx" ; + TARGET_DIR="/opt/homebrew" ; # Emulating a homebrew install so we don't need elevated permissions + # Darwin comes with unzip and curl already + brew install jq ;; + Linux*) + PROTOC_OS="linux" ; + TARGET_DIR="/usr" ; # Assumes the script is run as root or the user can do it manually + apt update && apt install -y unzip curl ca-certificates jq ;; + *) + echo "Unsupported OS: $(uname)" ; + exit 1 ;; +esac + +# Get the architecture +case "$(uname -m)" in + x86_64) PROTOC_ARCH="x86_64" ;; + aarch64) PROTOC_ARCH="aarch_64" ;; + arm64) PROTOC_ARCH="aarch_64" ;; + *) echo "Unsupported architecture: [$(uname -m)]"; exit 1 ;; +esac + +# Get the latest version +PROTOC_RAW_VERSION=$(curl --retry 10 --retry-delay 2 --retry-all-errors -fsL "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | jq -r .tag_name) || fail "Failed to get the latest version of protoc" +if [ "$PROTOC_RAW_VERSION" = "null" ]; then + fail "Failed to get the latest version of protoc" +fi +echo "Latest version of protoc: [$PROTOC_RAW_VERSION]" +PROTOC_VERSION=$(echo $PROTOC_RAW_VERSION | sed 's/^v//') || fail "Failed to parse the latest version of protoc" +if [ -z "$PROTOC_VERSION" ]; then + fail "Latest version of protoc was empty" +fi + +echo "Installing protoc: $PROTOC_VERSION-$PROTOC_OS-$PROTOC_ARCH" + +# Download and install protoc +curl --retry 10 --retry-delay 2 --retry-all-errors -fsLo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-$PROTOC_OS-$PROTOC_ARCH.zip || fail "Failed to download protoc" +unzip -q protoc.zip bin/protoc -d $TARGET_DIR || fail "Failed to unzip protoc" +unzip -q protoc.zip "include/google/*" -d $TARGET_DIR || fail "Failed to unzip protoc includes" +chmod a+x $TARGET_DIR/bin/protoc || fail "Failed to set executable permissions for protoc" +rm -rf protoc.zip || fail "Failed to remove protoc zip file" +echo "protoc ${PROTOC_VERSION} installed successfully for ${PROTOC_OS} ${PROTOC_ARCH}" \ No newline at end of file diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 6c5ac045..f9824e7a 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -1,135 +1,17 @@ -# This will be the main build image -FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED -WORKDIR /app - -# Planner stage -FROM --platform=${BUILDPLATFORM} chef AS planner -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -# Builder stage -FROM --platform=${BUILDPLATFORM} chef AS builder -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED -ENV BUILD_VAR_SCRIPT=/tmp/env.sh -COPY --from=planner /app/recipe.json recipe.json - -# Set up the build environment for cross-compilation if needed -RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ - # We're on x64, cross-compiling for arm64 - rustup target add aarch64-unknown-linux-gnu && \ - apt update && \ - apt install -y gcc-aarch64-linux-gnu && \ - echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ - echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ - if [ "$OPENSSL_VENDORED" != "true" ]; then \ - # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation - dpkg --add-architecture arm64 && \ - apt update && \ - apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ - echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ - echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - fi; \ - elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ - # We're on arm64, cross-compiling for x64 - rustup target add x86_64-unknown-linux-gnu && \ - apt update && \ - apt install -y gcc-x86-64-linux-gnu && \ - echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ - echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ - if [ "$OPENSSL_VENDORED" != "true" ]; then \ - # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation - dpkg --add-architecture amd64 && \ - apt update && \ - apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ - echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ - echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - fi; \ - fi - -# Run cook to prep the build -RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ - . ${BUILD_VAR_SCRIPT} && \ - echo "Cross-compilation environment set up for ${TARGET}"; \ - else \ - echo "No cross-compilation needed"; \ - fi && \ - if [ "$OPENSSL_VENDORED" = "true" ]; then \ - echo "Using vendored OpenSSL" && \ - FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ - else \ - echo "Using system OpenSSL"; \ - fi && \ - export GIT_HASH=$(git rev-parse HEAD) && \ - cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} - -# Now we can copy the source files - chef cook wants to run before this step -COPY . . - -# Get the latest Protoc since the one in the Debian repo is incredibly old -RUN apt update && apt install -y unzip curl ca-certificates && \ - PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \ - if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \ - PROTOC_ARCH=x86_64; \ - elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \ - PROTOC_ARCH=aarch_64; \ - else \ - echo "${BUILDPLATFORM} is not supported."; \ - exit 1; \ - fi && \ - curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \ - unzip -q protoc.zip bin/protoc -d /usr && \ - unzip -q protoc.zip "include/google/*" -d /usr && \ - chmod a+x /usr/bin/protoc && \ - rm -rf protoc.zip - -# Build the application -RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ - chmod +x ${BUILD_VAR_SCRIPT} && \ - . ${BUILD_VAR_SCRIPT} && \ - echo "Cross-compilation environment set up for ${TARGET}"; \ - else \ - echo "No cross-compilation needed"; \ - fi && \ - if [ "$OPENSSL_VENDORED" = "true" ]; then \ - echo "Using vendored OpenSSL" && \ - FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ - else \ - echo "Using system OpenSSL"; \ - fi && \ - export GIT_HASH=$(git rev-parse HEAD) && \ - cargo build ${TARGET_FLAG} --release --bin commit-boost-signer ${FEATURE_OPENSSL_VENDORED} && \ - if [ ! -z "$TARGET" ]; then \ - # If we're cross-compiling, we need to move the binary out of the target dir - mv target/${TARGET}/release/commit-boost-signer target/release/commit-boost-signer; \ - fi - -# Assemble the runner image -FROM debian:bookworm-slim AS runtime -WORKDIR /app - +FROM debian:bookworm-slim +ARG BINARIES_PATH TARGETOS TARGETARCH +COPY ${BINARIES_PATH}/commit-boost-signer-${TARGETOS}-${TARGETARCH} /usr/local/bin RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ libssl3 \ libssl-dev \ - curl \ - && apt-get clean autoclean \ - && rm -rf /var/lib/apt/lists/* - -COPY --from=builder /app/target/release/commit-boost-signer /usr/local/bin + curl && \ + # Cleanup + apt-get clean autoclean && \ + rm -rf /var/lib/apt/lists/* +# Create a non-root user to run the application RUN groupadd -g 10001 commitboost && \ useradd -u 10001 -g commitboost -s /sbin/nologin commitboost USER commitboost From 12c020a20af91f673e348b12f2bc561fe57a6ae4 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 13 May 2025 02:53:02 -0400 Subject: [PATCH 11/19] Fixed the Docker image binary filenames --- provisioning/pbs.Dockerfile | 2 +- provisioning/signer.Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/provisioning/pbs.Dockerfile b/provisioning/pbs.Dockerfile index 9eff5890..9eb72702 100644 --- a/provisioning/pbs.Dockerfile +++ b/provisioning/pbs.Dockerfile @@ -1,6 +1,6 @@ FROM debian:bookworm-slim ARG BINARIES_PATH TARGETOS TARGETARCH -COPY ${BINARIES_PATH}/commit-boost-pbs-${TARGETOS}-${TARGETARCH} /usr/local/bin +COPY ${BINARIES_PATH}/commit-boost-pbs-${TARGETOS}-${TARGETARCH} /usr/local/bin/commit-boost-pbs RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index f9824e7a..05679762 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -1,6 +1,6 @@ FROM debian:bookworm-slim ARG BINARIES_PATH TARGETOS TARGETARCH -COPY ${BINARIES_PATH}/commit-boost-signer-${TARGETOS}-${TARGETARCH} /usr/local/bin +COPY ${BINARIES_PATH}/commit-boost-signer-${TARGETOS}-${TARGETARCH} /usr/local/bin/commit-boost-signer RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ From 53cafc039a747e61a92b9fb41a9a53a395f1a1a0 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 13 May 2025 17:42:28 -0400 Subject: [PATCH 12/19] Cleaned up the Darwin artifact step --- .github/workflows/release.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 40745fbb..5be42110 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,9 +98,11 @@ jobs: - commit-boost-signer include: # - target: x86_64-apple-darwin - # os: macos-latest-large + # os: macos-latest-large + # package-suffix: x86-64 - target: aarch64-apple-darwin os: macos-latest + package-suffix: arm64 runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -145,18 +147,18 @@ jobs: - name: Build binary (Darwin) run: cargo build --release --target ${{ matrix.target }} --bin ${{ matrix.name }} - - name: Package binary (Unix) + - name: Package binary (Darwin) run: | cd target/${{ matrix.target }}/release - tar -czvf ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.tar.gz ${{ matrix.name }} - mv ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.tar.gz ../../../ + tar -czvf ${{ matrix.name }}-${{ github.ref_name }}-darwin_${{ matrix.package-suffix }}.tar.gz ${{ matrix.name }} + mv ${{ matrix.name }}-${{ github.ref_name }}-darwin_${{ matrix.package-suffix }}.tar.gz ../../../ - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }} + name: ${{ matrix.name }}-${{ github.ref_name }}-darwin_${{ matrix.package-suffix }} path: | - ${{ matrix.name }}-${{ github.ref_name }}-${{ matrix.target }}.tar.gz + ${{ matrix.name }}-${{ github.ref_name }}-darwin_${{ matrix.package-suffix }}.tar.gz # Builds the PBS Docker image build-and-push-pbs-docker: @@ -208,8 +210,6 @@ jobs: tags: | ghcr.io/commit-boost/pbs:${{ github.ref_name }} ${{ !contains(github.ref_name, 'rc') && 'ghcr.io/commit-boost/pbs:latest' || '' }} - cache-from: type=registry,ref=ghcr.io/commit-boost/pbs:buildcache - cache-to: type=registry,ref=ghcr.io/commit-boost/pbs:buildcache,mode=max file: provisioning/pbs.Dockerfile # Builds the Signer Docker image @@ -262,8 +262,6 @@ jobs: tags: | ghcr.io/commit-boost/signer:${{ github.ref_name }} ${{ !contains(github.ref_name, 'rc') && 'ghcr.io/commit-boost/signer:latest' || '' }} - cache-from: type=registry,ref=ghcr.io/commit-boost/signer:buildcache - cache-to: type=registry,ref=ghcr.io/commit-boost/signer:buildcache,mode=max file: provisioning/signer.Dockerfile # Creates a draft release on GitHub with the binaries From 58c61174c138f61a775031c2c28b00dac5038c64 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 14 May 2025 00:24:35 -0400 Subject: [PATCH 13/19] Made the CI workflow and justfile use the same toolchain as the source --- .github/workflows/ci.yml | 4 ++-- justfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 894d13da..ae9bad89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2025-02-26 + toolchain: 1.83 components: clippy, rustfmt - name: Install protoc - run: sudo apt-get install protobuf-compiler + run: sudo provisioning/protoc.sh - name: Setup just uses: extractions/setup-just@v2 diff --git a/justfile b/justfile index e6d11f62..b9250870 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,5 @@ -# Makes sure the nightly-2025-02-26 toolchain is installed -toolchain := "nightly-2025-02-26" +# Makes sure the same toolchain as the source is installed +toolchain := 1.83 fmt: rustup toolchain install {{toolchain}} > /dev/null 2>&1 && \ From 45e581baabbed9ba7987c3260b286a877a22480b Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 14 May 2025 01:06:05 -0400 Subject: [PATCH 14/19] Revert "Made the CI workflow and justfile use the same toolchain as the source" This reverts commit 58c61174c138f61a775031c2c28b00dac5038c64. --- .github/workflows/ci.yml | 4 ++-- justfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae9bad89..894d13da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: 1.83 + toolchain: nightly-2025-02-26 components: clippy, rustfmt - name: Install protoc - run: sudo provisioning/protoc.sh + run: sudo apt-get install protobuf-compiler - name: Setup just uses: extractions/setup-just@v2 diff --git a/justfile b/justfile index b9250870..e6d11f62 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,5 @@ -# Makes sure the same toolchain as the source is installed -toolchain := 1.83 +# Makes sure the nightly-2025-02-26 toolchain is installed +toolchain := "nightly-2025-02-26" fmt: rustup toolchain install {{toolchain}} > /dev/null 2>&1 && \ From 24a10c55f3bd558ad976852255b351bed31ef641 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 14 May 2025 02:26:15 -0400 Subject: [PATCH 15/19] Testing removal of OpenSSL vendored option --- Cargo.lock | 12 -------- Cargo.toml | 3 -- crates/common/Cargo.toml | 4 --- provisioning/build.Dockerfile | 56 +++++++++++------------------------ 4 files changed, 17 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 436d3b65..5ebc811a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1494,8 +1494,6 @@ dependencies = [ "ethereum_ssz_derive", "eyre", "jsonwebtoken", - "k256", - "openssl", "pbkdf2 0.12.2", "rand 0.9.0", "reqwest", @@ -3552,15 +3550,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-src" -version = "300.5.0+3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" -dependencies = [ - "cc", -] - [[package]] name = "openssl-sys" version = "0.9.106" @@ -3569,7 +3558,6 @@ checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] diff --git a/Cargo.toml b/Cargo.toml index 14cddf82..aef26a94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,6 @@ edition = "2021" rust-version = "1.83" version = "0.7.0-rc.2" -[workspace.features] -openssl-vendored = ["crates/common/openssl-vendored"] - [workspace.dependencies] aes = "0.8" alloy = { version = "0.12", features = [ diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 15c0b8d1..df78b046 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -41,7 +41,3 @@ tree_hash_derive.workspace = true unicode-normalization.workspace = true url.workspace = true jsonwebtoken.workspace = true -openssl = { version = "0.10", optional = true, features = ["vendored"] } - -[features] -openssl-vendored = ["openssl/vendored"] diff --git a/provisioning/build.Dockerfile b/provisioning/build.Dockerfile index a4eb3723..34ad27a5 100644 --- a/provisioning/build.Dockerfile +++ b/provisioning/build.Dockerfile @@ -1,15 +1,15 @@ # This will be the main build image FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE +ARG TARGETOS TARGETARCH BUILDPLATFORM TARGET_CRATE WORKDIR /app FROM --platform=${BUILDPLATFORM} chef AS planner -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE +ARG TARGETOS TARGETARCH BUILDPLATFORM TARGET_CRATE COPY . . RUN cargo chef prepare --recipe-path recipe.json FROM --platform=${BUILDPLATFORM} chef AS builder -ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE +ARG TARGETOS TARGETARCH BUILDPLATFORM TARGET_CRATE RUN test -n "$TARGET_CRATE" || (echo "TARGET_CRATE must be set to the service / binary you want to build" && false) ENV BUILD_VAR_SCRIPT=/tmp/env.sh COPY --from=planner /app/recipe.json recipe.json @@ -18,43 +18,33 @@ COPY --from=planner /app/recipe.json recipe.json RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ # We're on x64, cross-compiling for arm64 rustup target add aarch64-unknown-linux-gnu && \ + dpkg --add-architecture arm64 && \ apt update && \ - apt install -y gcc-aarch64-linux-gnu && \ + apt install -y gcc-aarch64-linux-gnu libssl-dev:arm64 zlib1g-dev:arm64 && \ echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ - if [ "$OPENSSL_VENDORED" != "true" ]; then \ - # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation - dpkg --add-architecture arm64 && \ - apt update && \ - apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \ - echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ - echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - fi; \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \ # We're on arm64, cross-compiling for x64 rustup target add x86_64-unknown-linux-gnu && \ + dpkg --add-architecture amd64 && \ apt update && \ - apt install -y gcc-x86-64-linux-gnu && \ + apt install -y gcc-x86-64-linux-gnu libssl-dev:amd64 zlib1g-dev:amd64 && \ echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \ - if [ "$OPENSSL_VENDORED" != "true" ]; then \ - # If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation - dpkg --add-architecture amd64 && \ - apt update && \ - apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \ - echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ - echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ - echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ - fi; \ + echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \ + echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ + echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \ fi # Run cook to prep the build @@ -64,14 +54,8 @@ RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ else \ echo "No cross-compilation needed"; \ fi && \ - if [ "$OPENSSL_VENDORED" = "true" ]; then \ - echo "Using vendored OpenSSL" && \ - FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ - else \ - echo "Using system OpenSSL"; \ - fi && \ export GIT_HASH=$(git rev-parse HEAD) && \ - cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED} + cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json # Get the latest Protoc since the one in the Debian repo is incredibly old COPY provisioning/protoc.sh provisioning/protoc.sh @@ -88,14 +72,8 @@ RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ else \ echo "No cross-compilation needed"; \ fi && \ - if [ "$OPENSSL_VENDORED" = "true" ]; then \ - echo "Using vendored OpenSSL" && \ - FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \ - else \ - echo "Using system OpenSSL"; \ - fi && \ export GIT_HASH=$(git rev-parse HEAD) && \ - cargo build ${TARGET_FLAG} --release --bin ${TARGET_CRATE} ${FEATURE_OPENSSL_VENDORED} && \ + cargo build ${TARGET_FLAG} --release --bin ${TARGET_CRATE} && \ if [ ! -z "$TARGET" ]; then \ # If we're cross-compiling, we need to move the binary out of the target dir mv target/${TARGET}/release/${TARGET_CRATE} target/release/${TARGET_CRATE}; \ From e36da545b00929146efbfa60eac1df0efb512d5e Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 14 May 2025 02:59:32 -0400 Subject: [PATCH 16/19] Updating just in the CI workflow --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 894d13da..0b15367f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,12 +30,12 @@ jobs: components: clippy, rustfmt - name: Install protoc - run: sudo apt-get install protobuf-compiler + run: sudo provisioning/protoc.sh - name: Setup just - uses: extractions/setup-just@v2 + uses: extractions/setup-just@v3 with: - just-version: 1.5.0 + just-version: 1.40.0 - name: Check compilation run: cargo check From 346eea4c0ee7c6e7e53ec1f6c950e3289be214dd Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 28 May 2025 16:36:11 -0400 Subject: [PATCH 17/19] Cleaned up the build Dockerfile and removed an extra dependency layer --- provisioning/build.Dockerfile | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/provisioning/build.Dockerfile b/provisioning/build.Dockerfile index 34ad27a5..43713cc5 100644 --- a/provisioning/build.Dockerfile +++ b/provisioning/build.Dockerfile @@ -1,7 +1,10 @@ # This will be the main build image -FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef +FROM --platform=${BUILDPLATFORM} rust:1.83-slim-bookworm AS chef ARG TARGETOS TARGETARCH BUILDPLATFORM TARGET_CRATE +ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse WORKDIR /app +RUN cargo install cargo-chef --locked && \ + rm -rf $CARGO_HOME/registry/ FROM --platform=${BUILDPLATFORM} chef AS planner ARG TARGETOS TARGETARCH BUILDPLATFORM TARGET_CRATE @@ -20,8 +23,8 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ rustup target add aarch64-unknown-linux-gnu && \ dpkg --add-architecture arm64 && \ apt update && \ - apt install -y gcc-aarch64-linux-gnu libssl-dev:arm64 zlib1g-dev:arm64 && \ - echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + apt install -y gcc-aarch64-linux-gnu && \ + echo '#!/bin/sh' > ${BUILD_VAR_SCRIPT} && \ echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ @@ -35,8 +38,8 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ rustup target add x86_64-unknown-linux-gnu && \ dpkg --add-architecture amd64 && \ apt update && \ - apt install -y gcc-x86-64-linux-gnu libssl-dev:amd64 zlib1g-dev:amd64 && \ - echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \ + apt install -y gcc-x86-64-linux-gnu && \ + echo '#!/bin/sh' > ${BUILD_VAR_SCRIPT} && \ echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \ echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \ @@ -49,12 +52,14 @@ RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \ # Run cook to prep the build RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ + chmod +x ${BUILD_VAR_SCRIPT} && \ . ${BUILD_VAR_SCRIPT} && \ echo "Cross-compilation environment set up for ${TARGET}"; \ else \ echo "No cross-compilation needed"; \ fi && \ - export GIT_HASH=$(git rev-parse HEAD) && \ + apt update && \ + apt install -y git libssl-dev:${TARGETARCH} zlib1g-dev:${TARGETARCH} pkg-config && \ cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json # Get the latest Protoc since the one in the Debian repo is incredibly old From 7b20d2f885efa8591d834d1deebb7b550d89683d Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Thu, 29 May 2025 05:03:25 -0400 Subject: [PATCH 18/19] Ported the build script over to the justfile --- build-linux.sh | 144 ------------------------ docs/docs/get_started/building.md | 28 ++--- justfile | 175 +++++++++++++++++++++++++++++- provisioning/pbs.Dockerfile | 2 +- provisioning/signer.Dockerfile | 2 +- 5 files changed, 185 insertions(+), 166 deletions(-) delete mode 100755 build-linux.sh diff --git a/build-linux.sh b/build-linux.sh deleted file mode 100755 index a7266bd9..00000000 --- a/build-linux.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash - -# This script will build the Commit-Boost applications and modules for local Linux development. - -# ================= -# === Functions === -# ================= - -# Print a failure message to stderr and exit -fail() { - MESSAGE=$1 - RED='\033[0;31m' - RESET='\033[;0m' - >&2 echo -e "\n${RED}**ERROR**\n$MESSAGE${RESET}\n" - exit 1 -} - - -# Builds the CLI binaries for Linux -# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static -build_cli() { - echo "Building CLI binaries..." - docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-cli . || fail "Error building CLI." - echo "done!" - - # Flatten the folder structure for easier referencing - mv build/$VERSION/linux_amd64/commit-boost-cli build/$VERSION/commit-boost-cli-linux-amd64 - mv build/$VERSION/linux_arm64/commit-boost-cli build/$VERSION/commit-boost-cli-linux-arm64 - - # Clean up the empty directories - rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64 - echo "done!" -} - - -# Builds the PBS module binaries for Linux and the Docker image(s) -# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static -build_pbs() { - echo "Building PBS binaries..." - docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-pbs . || fail "Error building PBS binaries." - echo "done!" - - # Flatten the folder structure for easier referencing - mv build/$VERSION/linux_amd64/commit-boost-pbs build/$VERSION/commit-boost-pbs-linux-amd64 - mv build/$VERSION/linux_arm64/commit-boost-pbs build/$VERSION/commit-boost-pbs-linux-arm64 - - # Clean up the empty directories - rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64 - - echo "Building PBS Docker image..." - # If uploading, make and push a manifest - if [ "$LOCAL_UPLOAD" = true ]; then - if [ -z "$LOCAL_DOCKER_REGISTRY" ]; then - fail "LOCAL_DOCKER_REGISTRY must be set to upload to a local registry." - fi - docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/$VERSION -t $LOCAL_DOCKER_REGISTRY/commit-boost/pbs:$VERSION -f provisioning/pbs.Dockerfile --push . || fail "Error building PBS image." - else - docker buildx build --rm --load --build-arg BINARIES_PATH=build/$VERSION -t commit-boost/pbs:$VERSION -f provisioning/pbs.Dockerfile . || fail "Error building PBS image." - fi - echo "done!" -} - - -# Builds the Signer module binaries for Linux and the Docker image(s) -# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static -build_signer() { - echo "Building Signer binaries..." - docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-signer . || fail "Error building Signer binaries." - echo "done!" - - # Flatten the folder structure for easier referencing - mv build/$VERSION/linux_amd64/commit-boost-signer build/$VERSION/commit-boost-signer-linux-amd64 - mv build/$VERSION/linux_arm64/commit-boost-signer build/$VERSION/commit-boost-signer-linux-arm64 - - # Clean up the empty directories - rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64 - - echo "Building Signer Docker image..." - # If uploading, make and push a manifest - if [ "$LOCAL_UPLOAD" = true ]; then - if [ -z "$LOCAL_DOCKER_REGISTRY" ]; then - fail "LOCAL_DOCKER_REGISTRY must be set to upload to a local registry." - fi - docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/$VERSION -t $LOCAL_DOCKER_REGISTRY/commit-boost/signer:$VERSION -f provisioning/signer.Dockerfile --push . || fail "Error building Signer image." - else - docker buildx build --rm --load --build-arg BINARIES_PATH=build/$VERSION -t commit-boost/signer:$VERSION -f provisioning/signer.Dockerfile . || fail "Error building Signer image." - fi - echo "done!" -} - - -# Print usage -usage() { - echo "Usage: build.sh [options] -v " - echo "This script assumes it is in the commit-boost-client repository directory." - echo "Options:" - echo $'\t-a\tBuild all of the artifacts (CLI, PBS, and Signer, along with Docker images)' - echo $'\t-c\tBuild the Commit-Boost CLI binaries' - echo $'\t-p\tBuild the PBS module binary and its Docker container' - echo $'\t-s\tBuild the Signer module binary and its Docker container' - echo $'\t-o\tWhen passed with a build, upload the resulting image tags to a local Docker registry specified in $LOCAL_DOCKER_REGISTRY' - exit 0 -} - - -# ================= -# === Main Body === -# ================= - -# Parse arguments -while getopts "acpsov:" FLAG; do - case "$FLAG" in - a) CLI=true PBS=true SIGNER=true ;; - c) CLI=true ;; - p) PBS=true ;; - s) SIGNER=true ;; - o) LOCAL_UPLOAD=true ;; - v) VERSION="$OPTARG" ;; - *) usage ;; - esac -done -if [ -z "$VERSION" ]; then - usage -fi - -# Cleanup old artifacts -rm -rf build/$VERSION/* -mkdir -p build/$VERSION - -# Make a multiarch builder, ignore if it's already there -docker buildx create --name multiarch-builder --driver docker-container --use > /dev/null 2>&1 -# NOTE: if using a local repo with a private CA, you will have to follow these steps to add the CA to the builder: -# https://stackoverflow.com/a/73585243 - -# Build the artifacts -if [ "$CLI" = true ]; then - build_cli -fi -if [ "$PBS" = true ]; then - build_pbs -fi -if [ "$SIGNER" = true ]; then - build_signer -fi diff --git a/docs/docs/get_started/building.md b/docs/docs/get_started/building.md index d38b447f..edf795b2 100644 --- a/docs/docs/get_started/building.md +++ b/docs/docs/get_started/building.md @@ -5,31 +5,27 @@ Commit-Boost's components are all written in [Rust](https://www.rust-lang.org/). ## Building via the Docker Builder -For convenience, Commit-Boost has Dockerized the build environment for Linux `x64` and `arm64` platforms. All of the prerequisites, cross-compilation tooling, and configuration are handled by the builder image. If you would like to build the CLI, PBS module, or Signer binaries and Docker images from source, you are welcome to use the Docker builder process. +For convenience, Commit-Boost has Dockerized the build environment for Linux `x64` and `arm64` platforms. It utilizes Docker's powerful [buildx](https://docs.docker.com/reference/cli/docker/buildx/) system. All of the prerequisites, cross-compilation tooling, and configuration are handled by the builder image. If you would like to build the CLI, PBS module, or Signer binaries and Docker images from source, you are welcome to use the Docker builder process. To use the builder, you will need to have [Docker Engine](https://docs.docker.com/engine/install/) installed on your system. Please follow the instructions to install it first. :::note -The build script assumes that you've added your user account to the `docker` group with the Linux [post-install steps](https://docs.docker.com/engine/install/linux-postinstall/). If you haven't, then you'll need to run the build script below as `root` or modify it so each call to `docker` within it is run as the root user (e.g., with `sudo`). +The build system assumes that you've added your user account to the `docker` group with the Linux [post-install steps](https://docs.docker.com/engine/install/linux-postinstall/). If you haven't, then you'll need to run the build script below as `root` or modify it so each call to `docker` within it is run as the root user (e.g., with `sudo`). ::: -We provide a build script called `build-linux.sh` to automate the process: +The Docker builder is built into the project's `justfile` which is used to invoke many facets of Commit Boost development. To use it, you'll need to install [Just](https://github.com/casey/just) on your system. -``` -$ ./build-linux.sh -Usage: build.sh [options] -v -This script assumes it is in the commit-boost-client repository directory. -Options: - -a Build all of the artifacts (CLI, PBS, and Signer, along with Docker images) - -c Build the Commit-Boost CLI binaries - -p Build the PBS module binary and its Docker container - -s Build the Signer module binary and its Docker container - -o When passed with a build, upload the resulting image tags to a local Docker registry specified in $LOCAL_DOCKER_REGISTRY -``` +Use `just --list` to show all of the actions - there are many. The `justfile` provides granular actions, called "recipes", for building just the binaries of a specific crate (such as the CLI, `pbs`, or `signer`), as well as actions to build the Docker images for the PBS and Signer modules. + +Below is a brief summary of the relevant ones for building the Commit-Boost artifacts: + +- `build-all ` will build the `commit-boost-cli`, `commit-boost-pbs`, and `commit-boost-signer` binaries for your local system architecture. It will also create Docker images called `commit-boost/pbs:` and `commit-boost/signer:` and load them into your local Docker registry for use. +- `build-cli-bin `, `build-pbs-bin `, and `build-signer-bin ` can be used to create the `commit-boost-cli`, `commit-boost-pbs`, and `commit-boost-signer` binaries, respectively. +- `build-pbs-img ` and `build-signer-img ` can be used to create the Docker images for the PBS and Signer modules, respectively. -The script utilizes Docker's [buildx](https://docs.docker.com/reference/cli/docker/buildx/) system to both create a multiarch-capable builder and cross-compile for both Linux architectures. You are free to modify it to produce only the artifacts relevant to you if so desired. +The `version` provided will be used to house the output binaries in `./build/`, and act as the version tag for the Docker images when they're added to your local system or uploaded to your local Docker repository. -The `version` provided will be used to house the output binaries in `./build/$VERSION`, and act as the version tag for the Docker images when they're added to your local system or uploaded to your local Docker repository. +If you're interested in building the binaries and/or Docker images for multiple architectures (currently Linux `amd64` and `arm64`), use the variants of those recipes that have the `-multiarch` suffix. Note that building a multiarch Docker image manifest will require the use of a [custom Docker registry](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-20-04), as the local registry built into Docker does not have multiarch manifest support. ## Building Manually diff --git a/justfile b/justfile index d13e76ae..ac1314fc 100644 --- a/justfile +++ b/justfile @@ -12,16 +12,183 @@ fmt-check: clippy: cargo +{{toolchain}} clippy --all-features --no-deps -- -D warnings -docker-build-pbs: - docker build -t commitboost_pbs_default . -f ./provisioning/pbs.Dockerfile +# =================================== +# === Build Commands for Services === +# =================================== -docker-build-signer: - docker build -t commitboost_signer . -f ./provisioning/signer.Dockerfile +[doc(""" + Builds the commit-boost-cli binary to './build/'. +""")] +build-cli version: \ + (_docker-build-binary version "cli") + +[doc(""" + Builds amd64 and arm64 binaries for the commit-boost-cli crate to './build//', where '' is + the OS / arch platform of the binary (linux_amd64 and linux_arm64). +""")] +build-cli-multiarch version: \ + (_docker-build-binary-multiarch version "cli") + +[doc(""" + Builds the commit-boost-pbs binary to './build/'. +""")] +build-pbs-bin version: \ + (_docker-build-binary version "pbs") + +[doc(""" + Creates a Docker image named 'commit-boost/pbs:' and loads it to the local Docker repository. + Requires the binary to be built first, but this command won't build it automatically if you just need to build the + Docker image without recompiling the binary. +""")] +build-pbs-img version: \ + (_docker-build-image version "pbs") + +[doc(""" + Builds the commit-boost-pbs binary to './build/' and creates a Docker image named 'commit-boost/pbs:'. +""")] +build-pbs version: \ + (build-pbs-bin version) \ + (build-pbs-img version) + +[doc(""" + Builds amd64 and arm64 binaries for the commit-boost-pbs crate to './build//', where '' is the + OS / arch platform of the binary (linux_amd64 and linux_arm64). + Used when creating the pbs Docker image. +""")] +build-pbs-bin-multiarch version: \ + (_docker-build-binary-multiarch version "pbs") + +[doc(""" + Creates a multiarch Docker image manifest named 'commit-boost/pbs:' and pushes it to a custom Docker registry + (such as '192.168.1.10:5000'). + Used for testing multiarch images locally instead of using a public registry like GHCR or Docker Hub. +""")] +build-pbs-img-multiarch version local-docker-registry: \ + (_docker-build-image-multiarch version "pbs" local-docker-registry) + +[doc(""" + Builds amd64 and arm64 binaries for the commit-boost-pbs crate to './build//', where '' is the + OS / arch platform of the binary (linux_amd64 and linux_arm64). + Creates a multiarch Docker image manifest named 'commit-boost/pbs:' and pushes it to a custom Docker registry + (such as '192.168.1.10:5000'). + Used for testing multiarch images locally instead of using a public registry like GHCR or Docker Hub. +""")] +build-pbs-multiarch version local-docker-registry: \ + (build-pbs-bin-multiarch version) \ + (build-pbs-img-multiarch version local-docker-registry) + +[doc(""" + Builds the commit-boost-signer binary to './build/'. +""")] +build-signer-bin version: \ + (_docker-build-binary version "signer") + +[doc(""" + Creates a Docker image named 'commit-boost/signer:' and loads it to the local Docker repository. + Requires the binary to be built first, but this command won't build it automatically if you just need to build the + Docker image without recompiling the binary. +""")] +build-signer-img version: \ + (_docker-build-image version "signer") + +[doc(""" + Builds the commit-boost-signer binary to './build/' and creates a Docker image named 'commit-boost/signer:'. +""")] +build-signer version: \ + (build-signer-bin version) \ + (build-signer-img version) + +[doc(""" + Builds amd64 and arm64 binaries for the commit-boost-signer crate to './build//', where '' is + the OS / arch platform of the binary (linux_amd64 and linux_arm64). + Used when creating the signer Docker image. +""")] +build-signer-bin-multiarch version: \ + (_docker-build-binary-multiarch version "signer") + +[doc(""" + Creates a multiarch Docker image manifest named 'commit-boost/signer:' and pushes it to a custom Docker registry + (such as '192.168.1.10:5000'). + Used for testing multiarch images locally instead of using a public registry like GHCR or Docker Hub. +""")] +build-signer-img-multiarch version local-docker-registry: \ + (_docker-build-image-multiarch version "signer" local-docker-registry) + +[doc(""" + Builds amd64 and arm64 binaries for the commit-boost-signer crate to './build//', where '' is + the OS / arch platform of the binary (linux_amd64 and linux_arm64). + Creates a multiarch Docker image manifest named 'commit-boost/signer:' and pushes it to a custom Docker registry + (such as '192.168.1.10:5000'). + Used for testing multiarch images locally instead of using a public registry like GHCR or Docker Hub. +""")] +build-signer-multiarch version local-docker-registry: \ + (build-signer-bin-multiarch version) \ + (build-signer-img-multiarch version local-docker-registry) + +[doc(""" + Builds the CLI, PBS, and Signer binaries and Docker images for the specified version. + The binaries will be placed in './build/'. + The Docker images will be named 'commit-boost/cli:', 'commit-boost/pbs:', and + 'commit-boost/signer:'. +""")] +build-all version: \ + (build-cli version) \ + (build-pbs version) \ + (build-signer version) + +[doc(""" + Builds amd64 and arm64 flavors of the CLI, PBS, and Signer binaries and Docker images for the specified version. + The binaries will be placed in './build//', where '' is the + OS / arch platform of the binary (linux_amd64 and linux_arm64). + Also creates multiarch Docker image manifests for each crate and pushes them to a custom Docker registry + (such as '192.168.1.10:5000'). + Used for testing multiarch images locally instead of using a public registry like GHCR or Docker Hub. +""")] +build-all-multiarch version local-docker-registry: \ + (build-cli-multiarch version) \ + (build-pbs-multiarch version local-docker-registry) \ + (build-signer-multiarch version local-docker-registry) + +# =============================== +# === Builder Implementations === +# =============================== + +# Creates a Docker buildx builder if it doesn't already exist +_create-docker-builder: + docker buildx create --name multiarch-builder --driver docker-container --use > /dev/null 2>&1 || true + +# Builds a binary for a specific crate and version +_docker-build-binary version crate: _create-docker-builder + export PLATFORM=$(docker buildx inspect --bootstrap | awk -F': ' '/Platforms/ {print $2}' | cut -d',' -f1 | xargs | tr '/' '_'); \ + docker buildx build --rm --platform=local -f provisioning/build.Dockerfile --output "build/{{version}}/$PLATFORM" --target output --build-arg TARGET_CRATE=commit-boost-{{crate}} . + +# Builds a Docker image for a specific crate and version +_docker-build-image version crate: _create-docker-builder + docker buildx build --rm --load --build-arg BINARIES_PATH=build/{{version}} -t commit-boost/{{crate}}:{{version}} -f provisioning/{{crate}}.Dockerfile . + +# Builds multiple binaries (for Linux amd64 and arm64 architectures) for a specific crate and version +_docker-build-binary-multiarch version crate: _create-docker-builder + docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/{{version}} --target output --build-arg TARGET_CRATE=commit-boost-{{crate}} . + +# Builds a multi-architecture (Linux amd64 and arm64) Docker manifest for a specific crate and version. +# Uploads to the custom Docker registry (such as '192.168.1.10:5000') instead of a public registry like GHCR or Docker Hub. +_docker-build-image-multiarch version crate local-docker-registry: _create-docker-builder + docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/{{version}} -t {{local-docker-registry}}/commit-boost/{{crate}}:{{version}} -f provisioning/{{crate}}.Dockerfile --push . + +# ================= +# === Utilities === +# ================= docker-build-test-modules: docker build -t test_da_commit . -f examples/da_commit/Dockerfile docker build -t test_builder_log . -f examples/builder_log/Dockerfile docker build -t test_status_api . -f examples/status_api/Dockerfile +# Cleans the build directory, removing all built binaries. +# Docker images are not removed by this command. +clean: + rm -rf build + +# Runs the suite of tests for all commit-boost crates. test: cargo test --all-features \ No newline at end of file diff --git a/provisioning/pbs.Dockerfile b/provisioning/pbs.Dockerfile index 9eb72702..6b9496ec 100644 --- a/provisioning/pbs.Dockerfile +++ b/provisioning/pbs.Dockerfile @@ -1,6 +1,6 @@ FROM debian:bookworm-slim ARG BINARIES_PATH TARGETOS TARGETARCH -COPY ${BINARIES_PATH}/commit-boost-pbs-${TARGETOS}-${TARGETARCH} /usr/local/bin/commit-boost-pbs +COPY ${BINARIES_PATH}/${TARGETOS}_${TARGETARCH}/commit-boost-pbs /usr/local/bin/commit-boost-pbs RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 05679762..5ea619b2 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -1,6 +1,6 @@ FROM debian:bookworm-slim ARG BINARIES_PATH TARGETOS TARGETARCH -COPY ${BINARIES_PATH}/commit-boost-signer-${TARGETOS}-${TARGETARCH} /usr/local/bin/commit-boost-signer +COPY ${BINARIES_PATH}/${TARGETOS}_${TARGETARCH}/commit-boost-signer /usr/local/bin/commit-boost-signer RUN apt-get update && apt-get install -y \ openssl \ ca-certificates \ From ca9f4a1997103e81427d3c9ca04a54317ce9fb2b Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Thu, 29 May 2025 16:08:50 -0400 Subject: [PATCH 19/19] Added a justfile recipe for installing protoc --- docs/docs/get_started/building.md | 19 ++++++------------- justfile | 3 +++ provisioning/protoc.sh | 11 +++++++---- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/docs/get_started/building.md b/docs/docs/get_started/building.md index edf795b2..a00b36cf 100644 --- a/docs/docs/get_started/building.md +++ b/docs/docs/get_started/building.md @@ -53,24 +53,17 @@ sudo apt update && sudo apt install -y openssl ca-certificates libssl3 libssl-de Install the Protobuf compiler: :::note -While many package repositories provide a `protobuf-compiler` package in lieu of manually installing protoc, we've found at the time of this writing that most of them use v3.21 which is quite out of date. We recommend getting the latest version manually. +While many package repositories provide a `protobuf-compiler` package in lieu of manually installing protoc, we've found at the time of this writing that Debian-based ones use v3.21 which is quite out of date. We recommend getting the latest version manually. ::: +We provide a convenient recipe to install the latest version directly from the GitHub releases page: + ```bash -PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') -MACHINE_ARCH=$(uname -m) -case "${MACHINE_ARCH}" in - aarch64) PROTOC_ARCH=aarch_64;; - x86_64) PROTOC_ARCH=x86_64;; - *) echo "${MACHINE_ARCH} is not supported."; exit 1;; -esac -curl -sLo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip -sudo unzip -q protoc.zip bin/protoc -d /usr -sudo unzip -q protoc.zip "include/google/*" -d /usr -sudo chmod a+x /usr/bin/protoc -rm -rf protoc.zip +just install-protoc ``` +This works on OSX and Linux systems, but you are welcome to download and install it manually as well. + With the prerequisites set up, pull the repository: ```bash git clone https://github.com/Commit-Boost/commit-boost-client diff --git a/justfile b/justfile index ac1314fc..ee5f4c2d 100644 --- a/justfile +++ b/justfile @@ -179,6 +179,9 @@ _docker-build-image-multiarch version crate local-docker-registry: _create-docke # === Utilities === # ================= +install-protoc: + provisioning/protoc.sh + docker-build-test-modules: docker build -t test_da_commit . -f examples/da_commit/Dockerfile docker build -t test_builder_log . -f examples/builder_log/Dockerfile diff --git a/provisioning/protoc.sh b/provisioning/protoc.sh index 7f66a656..a727a7c1 100755 --- a/provisioning/protoc.sh +++ b/provisioning/protoc.sh @@ -21,7 +21,10 @@ case "$(uname)" in Linux*) PROTOC_OS="linux" ; TARGET_DIR="/usr" ; # Assumes the script is run as root or the user can do it manually - apt update && apt install -y unzip curl ca-certificates jq ;; + if [ $(id -u) != "0" ]; then + CMD_PREFIX="sudo " ; + fi + ${CMD_PREFIX}apt update && ${CMD_PREFIX}apt install -y unzip curl ca-certificates jq ;; *) echo "Unsupported OS: $(uname)" ; exit 1 ;; @@ -50,8 +53,8 @@ echo "Installing protoc: $PROTOC_VERSION-$PROTOC_OS-$PROTOC_ARCH" # Download and install protoc curl --retry 10 --retry-delay 2 --retry-all-errors -fsLo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-$PROTOC_OS-$PROTOC_ARCH.zip || fail "Failed to download protoc" -unzip -q protoc.zip bin/protoc -d $TARGET_DIR || fail "Failed to unzip protoc" -unzip -q protoc.zip "include/google/*" -d $TARGET_DIR || fail "Failed to unzip protoc includes" -chmod a+x $TARGET_DIR/bin/protoc || fail "Failed to set executable permissions for protoc" +${CMD_PREFIX}unzip -qo protoc.zip bin/protoc -d $TARGET_DIR || fail "Failed to unzip protoc" +${CMD_PREFIX}unzip -qo protoc.zip "include/google/*" -d $TARGET_DIR || fail "Failed to unzip protoc includes" +${CMD_PREFIX}chmod a+x $TARGET_DIR/bin/protoc || fail "Failed to set executable permissions for protoc" rm -rf protoc.zip || fail "Failed to remove protoc zip file" echo "protoc ${PROTOC_VERSION} installed successfully for ${PROTOC_OS} ${PROTOC_ARCH}" \ No newline at end of file