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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 906c01f3..5be42110 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,12 +97,12 @@ 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 + # package-suffix: x86-64 - target: aarch64-apple-darwin os: macos-latest + package-suffix: arm64 runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -41,6 +116,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 +144,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' + - 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 ../../../ - - - 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 + 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 }}.${{ runner.os == 'Windows' && 'zip' || 'tar.gz' }} + ${{ matrix.name }}-${{ github.ref_name }}-darwin_${{ matrix.package-suffix }}.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 +172,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,15 +205,16 @@ 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' || '' }} - 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 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,16 +257,18 @@ 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' || '' }} - 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 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/.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/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/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 } } diff --git a/docs/docs/get_started/building.md b/docs/docs/get_started/building.md new file mode 100644 index 00000000..a00b36cf --- /dev/null +++ b/docs/docs/get_started/building.md @@ -0,0 +1,174 @@ +# 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. 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 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`). +::: + +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. + +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 `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. + +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 + +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 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 +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 +``` + +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 diff --git a/justfile b/justfile index d13e76ae..ee5f4c2d 100644 --- a/justfile +++ b/justfile @@ -12,16 +12,186 @@ 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 === +# ================= + +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 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/build.Dockerfile b/provisioning/build.Dockerfile new file mode 100644 index 00000000..43713cc5 --- /dev/null +++ b/provisioning/build.Dockerfile @@ -0,0 +1,90 @@ +# This will be the main build image +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 +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM --platform=${BUILDPLATFORM} chef AS builder +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 + +# 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 && \ + dpkg --add-architecture arm64 && \ + 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} && \ + 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 && \ + 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} && \ + 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 +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 && \ + 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 +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 . . + +# 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 && \ + export GIT_HASH=$(git rev-parse HEAD) && \ + 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}; \ + 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/pbs.Dockerfile b/provisioning/pbs.Dockerfile index 200c95d2..6b9496ec 100644 --- a/provisioning/pbs.Dockerfile +++ b/provisioning/pbs.Dockerfile @@ -1,40 +1,19 @@ -FROM lukemathwalker/cargo-chef:latest-rust-1.83 AS chef -WORKDIR /app - -FROM chef AS planner -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -FROM chef AS builder -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-pbs - - -FROM debian:bookworm-20240904-slim AS runtime -WORKDIR /app - +FROM debian:bookworm-slim +ARG BINARIES_PATH TARGETOS TARGETARCH +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 \ 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/protoc.sh b/provisioning/protoc.sh new file mode 100755 index 00000000..a727a7c1 --- /dev/null +++ b/provisioning/protoc.sh @@ -0,0 +1,60 @@ +#!/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 + 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 ;; +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" +${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 diff --git a/provisioning/signer.Dockerfile b/provisioning/signer.Dockerfile index 85c2be43..5ea619b2 100644 --- a/provisioning/signer.Dockerfile +++ b/provisioning/signer.Dockerfile @@ -1,40 +1,19 @@ -FROM lukemathwalker/cargo-chef:latest-rust-1.83 AS chef -WORKDIR /app - -FROM chef AS planner -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -FROM chef AS builder -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 - - -FROM debian:bookworm-20240904-slim AS runtime -WORKDIR /app - +FROM debian:bookworm-slim +ARG BINARIES_PATH TARGETOS TARGETARCH +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 \ 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 -ENTRYPOINT ["/usr/local/bin/commit-boost-signer"] - - - +ENTRYPOINT ["/usr/local/bin/commit-boost-signer"] \ No newline at end of file