diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 131e7a8..8ef4675 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -20,8 +20,30 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu + + - name: Cache Rust build artifacts + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Install cross main + run: cargo install cross --git https://github.com/cross-rs/cross + + - name: Build x86_64 binary + run: make build-x86_64-unknown-linux-gnu + + - name: Build aarch64 binary + run: make build-aarch64-unknown-linux-gnu + + - name: Prepare binaries + run: | + mkdir -p dist/bin/amd64 dist/bin/arm64 + cp target/x86_64-unknown-linux-gnu/release/morph-reth dist/bin/amd64/morph-reth + cp target/aarch64-unknown-linux-gnu/release/morph-reth dist/bin/arm64/morph-reth - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -39,18 +61,16 @@ jobs: with: images: ${{ env.IMAGE_NAME }} tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha,prefix= + type=semver,pattern=v{{version}} type=raw,value=latest,enable=${{ !contains(github.ref, '-') }} - name: Build and push uses: docker/build-push-action@v6 with: context: . + file: ./Dockerfile.cross push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + provenance: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9f3a1ba..56e4c9b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -99,13 +99,11 @@ jobs: cache-on-failure: true key: ${{ matrix.target }} - - name: Install cross - uses: taiki-e/install-action@v2 - with: - tool: cross + - name: Install cross main + run: cargo install cross --git https://github.com/cross-rs/cross - name: Build binary - run: cross build --release --locked --target ${{ matrix.target }} --bin morph-reth + run: make build-${{ matrix.target }} - name: Package binary run: | @@ -153,22 +151,58 @@ jobs: else CHANGELOG=$(git log -n 20 --pretty=format:"- %s") fi - # Write to file to avoid escaping issues - echo "$CHANGELOG" > changelog.md + echo "CHANGELOG<> $GITHUB_OUTPUT + echo "$CHANGELOG" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT - name: Create draft release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ needs.extract-version.outputs.version }} + REPO_NAME: ${{ github.repository }} run: | - VERSION="${{ needs.extract-version.outputs.version }}" PRERELEASE="" if [[ "$VERSION" == *"alpha"* ]] || [[ "$VERSION" == *"beta"* ]] || [[ "$VERSION" == *"rc"* ]]; then PRERELEASE="--prerelease" fi + + cat < release_notes.md + ## Testing Checklist (DELETE ME) + + - [ ] Run on testnet for 1-3 days. + - [ ] Resync a node from genesis. + - [ ] Ensure all CI checks pass. + + ## Release Checklist (DELETE ME) + + - [ ] Ensure version has been bumped in \`Cargo.toml\`. + - [ ] Write the summary below. + - [ ] Ensure all binaries have been added. + + ## Summary + + + + ## All Changes + + ${{ steps.changelog.outputs.CHANGELOG }} + + ## Binaries + + | System | Architecture | Binary | + |:---:|:---:|:---:| + | | x86_64 | [morph-reth-${VERSION}-x86_64-linux.tar.gz](https://github.com/${REPO_NAME}/releases/download/v${VERSION}/morph-reth-${VERSION}-x86_64-linux.tar.gz) | + | | aarch64 | [morph-reth-${VERSION}-aarch64-linux.tar.gz](https://github.com/${REPO_NAME}/releases/download/v${VERSION}/morph-reth-${VERSION}-aarch64-linux.tar.gz) | + | | Docker | [ghcr.io/morph-l2/morph-reth:v${VERSION}](https://ghcr.io/morph-l2/morph-reth) | + ENDBODY + gh release create "v${VERSION}" \ --verify-tag \ --draft \ --title "v${VERSION}" \ - --notes-file changelog.md \ + --notes-file release_notes.md \ $PRERELEASE \ artifacts/* diff --git a/Cross.toml b/Cross.toml index 316255a..2a7689e 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,19 +1,2 @@ -[build] -pre-build = [ - # Use HTTPS for package sources - "apt-get update && apt-get install --assume-yes --no-install-recommends ca-certificates", - "find /etc/apt/ -type f \\( -name '*.list' -o -name '*.sources' \\) -exec sed -i 's|http://|https://|g' {} +", - - # Configure APT retries and timeouts to handle network issues - "echo 'Acquire::Retries \"3\";' > /etc/apt/apt.conf.d/80-retries", - "echo 'Acquire::http::Timeout \"60\";' >> /etc/apt/apt.conf.d/80-retries", - "echo 'Acquire::ftp::Timeout \"60\";' >> /etc/apt/apt.conf.d/80-retries", - - # rust-bindgen dependencies: llvm-dev libclang-dev (>= 10) clang (>= 10) - # Required for reth-mdbx-sys compilation. - # See: https://github.com/cross-rs/cross/wiki/FAQ#using-clang--bindgen - "apt-get update && apt-get install --assume-yes --no-install-recommends llvm-dev libclang-dev clang", -] - [build.env] passthrough = ["JEMALLOC_SYS_WITH_LG_PAGE"] diff --git a/Dockerfile.cross b/Dockerfile.cross new file mode 100644 index 0000000..ec255f1 --- /dev/null +++ b/Dockerfile.cross @@ -0,0 +1,21 @@ +# Cross-compilation image: assumes the morph-reth binary has already been +# compiled for $TARGETPLATFORM and placed in ./dist/bin/$TARGETARCH/ +FROM --platform=$TARGETPLATFORM ubuntu:22.04 + +LABEL org.opencontainers.image.source=https://github.com/morph-l2/morph-reth +LABEL org.opencontainers.image.licenses="MIT OR Apache-2.0" + +# Filled by docker buildx +ARG TARGETARCH + +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && \ + useradd --system --create-home --home-dir /var/lib/morph-reth --shell /usr/sbin/nologin morph-reth && \ + rm -rf /var/lib/apt/lists/* + +COPY ./dist/bin/$TARGETARCH/morph-reth /usr/local/bin/morph-reth + +EXPOSE 8545 8546 8551 30303 30303/udp + +WORKDIR /var/lib/morph-reth +USER morph-reth +ENTRYPOINT ["/usr/local/bin/morph-reth"] diff --git a/Makefile b/Makefile index 8cf29ef..7d6be40 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,17 @@ install: ## Build and install the morph-reth binary under `$(CARGO_HOME)/bin`. --profile "$(PROFILE)" \ $(CARGO_INSTALL_EXTRA_FLAGS) +##@ Cross Build (requires Docker + cross: cargo install cross --git https://github.com/cross-rs/cross) + +# Pattern rule: cross-build for any target, e.g. `make build-x86_64-unknown-linux-gnu` +# See: https://github.com/cross-rs/cross/wiki/FAQ#undefined-reference-with-build-std +build-%: ## Cross-build morph-reth for a specific target (e.g. build-x86_64-unknown-linux-gnu). + RUSTFLAGS="-C link-arg=-lgcc -Clink-arg=-static-libgcc" \ + cross build --locked --bin morph-reth --target $* --profile "$(PROFILE)" + +# aarch64 needs larger jemalloc page size (64KB pages on some ARM systems) +build-aarch64-unknown-linux-gnu: export JEMALLOC_SYS_WITH_LG_PAGE=16 + # Create a `.tar.gz` containing the morph-reth binary for a specific target. define tarball_release_binary cp $(CARGO_TARGET_DIR)/$(PROFILE)/morph-reth $(BIN_DIR)/morph-reth @@ -114,9 +125,19 @@ docker-build-push-latest: ## Build and push a Docker image tagged with the lates docker-build-push-git-sha: ## Build and push a Docker image tagged with the latest git sha. $(call docker_build_push,$(GIT_SHA),$(GIT_SHA)) +# Cross-compile binaries for both platforms, then build a multi-arch image +# using Dockerfile.cross (no QEMU needed). define docker_build_push - docker buildx build --file ./Dockerfile . \ - --platform linux/amd64 \ + $(MAKE) build-x86_64-unknown-linux-gnu + mkdir -p $(BIN_DIR)/amd64 + cp $(CARGO_TARGET_DIR)/x86_64-unknown-linux-gnu/$(PROFILE)/morph-reth $(BIN_DIR)/amd64/morph-reth + + $(MAKE) build-aarch64-unknown-linux-gnu + mkdir -p $(BIN_DIR)/arm64 + cp $(CARGO_TARGET_DIR)/aarch64-unknown-linux-gnu/$(PROFILE)/morph-reth $(BIN_DIR)/arm64/morph-reth + + docker buildx build --file ./Dockerfile.cross . \ + --platform linux/amd64,linux/arm64 \ --tag $(DOCKER_IMAGE_NAME):$(1) \ --tag $(DOCKER_IMAGE_NAME):$(2) \ --provenance=false \