From 8e0aeb4fdcafe297c2047bd86b0d1ac99a14c96f Mon Sep 17 00:00:00 2001 From: loverustfs Date: Fri, 19 Dec 2025 23:22:45 +0800 Subject: [PATCH] Optimize ci ubicloud (#1208) --- .github/actions/setup/action.yml | 26 +++++ .github/workflows/build.yml | 27 +++-- .github/workflows/ci.yml | 30 ++++-- .github/workflows/docker.yml | 172 +++++++++++++++++++++++-------- 4 files changed, 197 insertions(+), 58 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 7a2171b9..ca80dc79 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -55,6 +55,32 @@ runs: pkg-config \ libssl-dev + - name: Install mold linker (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + # Install mold for faster linking + MOLD_VERSION="2.34.1" + ARCH=$(uname -m) + + if [[ "$ARCH" == "x86_64" ]]; then + MOLD_ARCH="x86_64" + elif [[ "$ARCH" == "aarch64" ]]; then + MOLD_ARCH="aarch64" + else + echo "Unsupported architecture: $ARCH" + exit 0 + fi + + curl -L "https://github.com/rui314/mold/releases/download/v${MOLD_VERSION}/mold-${MOLD_VERSION}-${MOLD_ARCH}-linux.tar.gz" | tar xzf - + sudo cp mold-${MOLD_VERSION}-${MOLD_ARCH}-linux/bin/mold /usr/local/bin/ + sudo mkdir -p /usr/local/libexec + sudo cp mold-${MOLD_VERSION}-${MOLD_ARCH}-linux/libexec/mold /usr/local/libexec/ || true + rm -rf mold-${MOLD_VERSION}-${MOLD_ARCH}-linux + + # Verify installation + mold --version || echo "mold installation verification failed" + - name: Install protoc uses: arduino/setup-protoc@v3 with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a70e6aab..dc66fff9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -166,23 +166,28 @@ jobs: fail-fast: false matrix: include: - # Linux builds + # Linux x86_64 builds on x86 runners - os: ubicloud-standard-4 target: x86_64-unknown-linux-musl cross: false platform: linux - - os: ubicloud-standard-4 - target: aarch64-unknown-linux-musl - cross: true - platform: linux + arch: x86_64 - os: ubicloud-standard-4 target: x86_64-unknown-linux-gnu cross: false platform: linux - - os: ubicloud-standard-4 - target: aarch64-unknown-linux-gnu - cross: true + arch: x86_64 + # Linux aarch64 builds on ARM runners (native compilation) + - os: ubicloud-standard-4-arm + target: aarch64-unknown-linux-musl + cross: false platform: linux + arch: aarch64 + - os: ubicloud-standard-4-arm + target: aarch64-unknown-linux-gnu + cross: false + platform: linux + arch: aarch64 # macOS builds - os: macos-latest target: aarch64-apple-darwin @@ -212,7 +217,7 @@ jobs: with: rust-version: stable target: ${{ matrix.target }} - cache-shared-key: build-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }} + cache-shared-key: build-${{ matrix.arch }}-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }} github-token: ${{ secrets.GITHUB_TOKEN }} cache-save-if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} install-cross-tools: ${{ matrix.cross }} @@ -259,6 +264,10 @@ jobs: cargo zigbuild --release --target ${{ matrix.target }} -p rustfs --bins fi else + # Native compilation - use mold linker on Linux for faster linking + if [[ "${{ matrix.platform }}" == "linux" ]]; then + export RUSTFLAGS="${RUSTFLAGS} -C link-arg=-fuse-ld=mold" + fi cargo build --release --target ${{ matrix.target }} -p rustfs --bins fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c7e7662..ca5f1104 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,11 +101,19 @@ jobs: uses: crate-ci/typos@master test-and-lint: - name: Test and Lint + name: Test and Lint (${{ matrix.arch }}) needs: skip-check if: needs.skip-check.outputs.should_skip != 'true' - runs-on: ubicloud-standard-4 + runs-on: ${{ matrix.runner }} timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + runner: ubicloud-standard-4 + - arch: aarch64 + runner: ubicloud-standard-4-arm steps: - name: Checkout repository uses: actions/checkout@v6 @@ -114,7 +122,7 @@ jobs: uses: ./.github/actions/setup with: rust-version: stable - cache-shared-key: ci-test-${{ hashFiles('**/Cargo.lock') }} + cache-shared-key: ci-test-${{ matrix.arch }}-${{ hashFiles('**/Cargo.lock') }} github-token: ${{ secrets.GITHUB_TOKEN }} cache-save-if: ${{ github.ref == 'refs/heads/main' }} @@ -133,17 +141,25 @@ jobs: run: cargo clippy --all-targets --all-features -- -D warnings e2e-tests: - name: End-to-End Tests + name: End-to-End Tests (${{ matrix.arch }}) needs: skip-check if: needs.skip-check.outputs.should_skip != 'true' - runs-on: ubicloud-standard-4 + runs-on: ${{ matrix.runner }} timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + runner: ubicloud-standard-4 + - arch: aarch64 + runner: ubicloud-standard-4-arm steps: - name: Checkout repository uses: actions/checkout@v6 - name: Clean up previous test run - run: | + run: |matrix.arch }}-${{ rm -rf /tmp/rustfs rm -f /tmp/rustfs.log @@ -169,7 +185,7 @@ jobs: cargo build -p rustfs --bins --jobs 4 - name: Run end-to-end tests - run: | + run: |matrix.arch }}-${{ s3s-e2e --version ./scripts/e2e-run.sh ./target/debug/rustfs /tmp/rustfs diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 37d41b50..308a1185 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -258,37 +258,21 @@ jobs: # Build multi-arch Docker images # Strategy: Build images using pre-built binaries from dl.rustfs.com - # Supports both release and dev channel binaries based on build context + # Optimization: Build each architecture on its native runner to avoid QEMU overhead # Only runs when should_build is true (which includes workflow success check) - build-docker: - name: Build Docker Images + + # Prepare metadata for both builds + prepare-metadata: + name: Prepare Docker Metadata needs: build-check if: needs.build-check.outputs.should_build == 'true' runs-on: ubicloud-standard-4 - timeout-minutes: 60 + outputs: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + docker_release: ${{ steps.meta.outputs.docker_release }} + docker_channel: ${{ steps.meta.outputs.docker_channel }} steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ env.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # - name: Login to GitHub Container Registry - # uses: docker/login-action@v3 - # with: - # registry: ghcr.io - # username: ${{ github.actor }} - # password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Extract metadata and generate tags id: meta run: | @@ -368,41 +352,143 @@ jobs: echo "📋 Build type: $BUILD_TYPE" echo "🔖 Version: $VERSION" - - name: Build and push Docker image + # Build amd64 image on x86 runner (native build) + build-docker-amd64: + name: Build Docker Image (amd64) + needs: [build-check, prepare-metadata] + if: needs.build-check.outputs.should_build == 'true' + runs-on: ubicloud-standard-4 + timeout-minutes: 30 + outputs: + digest: ${{ steps.build.outputs.digest }} + image_name: ${{ steps.build.outputs.imageid }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ env.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push (amd64) + id: build uses: docker/build-push-action@v6 with: context: . file: Dockerfile - platforms: ${{ env.DOCKER_PLATFORMS }} + platforms: linux/amd64 push: ${{ needs.build-check.outputs.should_push == 'true' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + labels: ${{ needs.prepare-metadata.outputs.labels }} cache-from: | - type=gha,scope=docker-binary + type=gha,scope=docker-amd64 cache-to: | - type=gha,mode=max,scope=docker-binary + type=gha,mode=max,scope=docker-amd64 build-args: | BUILDTIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=${{ needs.build-check.outputs.version }} BUILD_TYPE=${{ needs.build-check.outputs.build_type }} REVISION=${{ github.sha }} - RELEASE=${{ steps.meta.outputs.docker_release }} - CHANNEL=${{ steps.meta.outputs.docker_channel }} + RELEASE=${{ needs.prepare-metadata.outputs.docker_release }} + CHANNEL=${{ needs.prepare-metadata.outputs.docker_channel }} BUILDKIT_INLINE_CACHE=1 - # Enable advanced BuildKit features for better performance provenance: false sbom: false - # Add retry mechanism by splitting the build process - no-cache: false - pull: true + outputs: type=image,name=${{ env.REGISTRY_DOCKERHUB }},push-by-digest=true,name-canonical=true,push=${{ needs.build-check.outputs.should_push == 'true' }} - # Note: Manifest creation is no longer needed as we only build one variant - # Multi-arch manifests are automatically created by docker/build-push-action + # Build arm64 image on ARM runner (native build) + build-docker-arm64: + name: Build Docker Image (arm64) + needs: [build-check, prepare-metadata] + if: needs.build-check.outputs.should_build == 'true' + runs-on: ubicloud-standard-4-arm + timeout-minutes: 30 + outputs: + digest: ${{ steps.build.outputs.digest }} + image_name: ${{ steps.build.outputs.imageid }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ env.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push (arm64) + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + platforms: linux/arm64 + push: ${{ needs.build-check.outputs.should_push == 'true' }} + labels: ${{ needs.prepare-metadata.outputs.labels }} + cache-from: | + type=gha,scope=docker-arm64 + cache-to: | + type=gha,mode=max,scope=docker-arm64 + build-args: | + BUILDTIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') + VERSION=${{ needs.build-check.outputs.version }} + BUILD_TYPE=${{ needs.build-check.outputs.build_type }} + REVISION=${{ github.sha }} + RELEASE=${{ needs.prepare-metadata.outputs.docker_release }} + CHANNEL=${{ needs.prepare-metadata.outputs.docker_channel }} + BUILDKIT_INLINE_CACHE=1 + provenance: false + sbom: false + outputs: type=image,name=${{ env.REGISTRY_DOCKERHUB }},push-by-digest=true,name-canonical=true,push=${{ needs.build-check.outputs.should_push == 'true' }} + + # Merge manifests to create multi-arch image + merge-manifests: + name: Create Multi-Arch Manifest + needs: [build-check, prepare-metadata, build-docker-amd64, build-docker-arm64] + if: needs.build-check.outputs.should_build == 'true' && needs.build-check.outputs.should_push == 'true' + runs-on: ubicloud-standard-4 + steps: + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ env.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Create and push multi-arch manifest + run: | + TAGS="${{ needs.prepare-metadata.outputs.tags }}" + + echo "🐳 Creating multi-arch manifest for tags:" + echo "$TAGS" | tr ',' '\n' | sed 's/^/ - /' + + # Convert comma-separated tags to array + IFS=',' read -ra TAG_ARRAY <<< "$TAGS" + + # Create manifest for each tag + for TAG in "${TAG_ARRAY[@]}"; do + echo "Creating manifest for: $TAG" + docker buildx imagetools create \ + -t "$TAG" \ + "${{ env.REGISTRY_DOCKERHUB }}@${{ needs.build-docker-amd64.outputs.digest }}" \ + "${{ env.REGISTRY_DOCKERHUB }}@${{ needs.build-docker-arm64.outputs.digest }}" + done + + echo "✅ Multi-arch manifest created and pushed successfully" # Docker build summary docker-summary: name: Docker Build Summary - needs: [ build-check, build-docker ] + needs: [ build-check, prepare-metadata, build-docker-amd64, build-docker-arm64, merge-manifests ] if: always() && needs.build-check.outputs.should_build == 'true' runs-on: ubicloud-standard-4 steps: @@ -415,7 +501,9 @@ jobs: echo "🐳 Docker build completed successfully!" echo "📦 Build type: $BUILD_TYPE" echo "🔢 Version: $VERSION" - echo "🚀 Strategy: Images using pre-built binaries (release channel only)" + echo "🚀 Strategy: Native builds on each architecture (no QEMU overhead)" + echo " - amd64: Built on x86 runner" + echo " - arm64: Built on ARM runner" echo "" case "$BUILD_TYPE" in