diff --git a/.github/workflows/container_release_unified.yml b/.github/workflows/container_release_unified.yml index 71d5697a0..032afd1e9 100644 --- a/.github/workflows/container_release_unified.yml +++ b/.github/workflows/container_release_unified.yml @@ -118,8 +118,9 @@ jobs: needs: [build-rust-binaries] runs-on: ubuntu-latest strategy: - # Build sequentially to avoid rate limits - max-parallel: 2 + # All variants at once: pulls hit mirror.gcr.io and pushes go to GHCR only, + # so docker.io limits don't apply. Watch the 10 GB gha cache budget. + max-parallel: 5 matrix: include: # Normal volume - multi-arch @@ -272,93 +273,52 @@ jobs: BRANCH=${{ github.sha }} ${{ matrix.variant == 'rocksdb' && format('ROCKSDB_VERSION={0}', github.event.inputs.rocksdb_version || 'v10.10.1') || '' }} - - name: Clean up build artifacts - if: always() && (github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant) - run: | - sudo docker system prune -f - sudo rm -rf /tmp/go-build* - - copy-to-dockerhub: - runs-on: ubuntu-latest - needs: [build] - if: github.event_name != 'pull_request' - strategy: - matrix: - variant: [normal, large_disk, full, large_disk_full, rocksdb] - include: - - variant: normal - tag_suffix: "" - - variant: large_disk - tag_suffix: _large_disk - - variant: full - tag_suffix: _full - - variant: large_disk_full - tag_suffix: _large_disk_full - - variant: rocksdb - tag_suffix: _large_disk_rocksdb - - steps: - - name: Login to Docker Hub - if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - uses: docker/login-action@v4.2.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Login to GHCR - if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant - uses: docker/login-action@v4.2.0 - with: - registry: ghcr.io - username: ${{ secrets.GHCR_USERNAME }} - password: ${{ secrets.GHCR_TOKEN }} - + # Copy GHCR -> Docker Hub here, per variant, so it overlaps with the other + # variants still building instead of waiting on the whole matrix. - name: Install crane - if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant + if: (github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant) && github.event_name != 'pull_request' run: | cd $(mktemp -d) curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz" | tar xz sudo mv crane /usr/local/bin/ crane version - - - name: Copy ${{ matrix.variant }} from GHCR to Docker Hub - if: github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant + + - name: Copy ${{ matrix.variant }} to Docker Hub + if: (github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant) && github.event_name != 'pull_request' run: | - # Function to retry with exponential backoff retry_with_backoff() { local max_attempts=5 local timeout=1 local attempt=1 local exit_code=0 - while [ $attempt -le $max_attempts ]; do if "$@"; then return 0 else exit_code=$? fi - if [ $attempt -lt $max_attempts ]; then echo "Attempt $attempt failed. Retrying in ${timeout}s..." >&2 sleep $timeout timeout=$((timeout * 2)) fi - attempt=$((attempt + 1)) done - echo "Command failed after $max_attempts attempts" >&2 return $exit_code } - - # Copy multi-arch image from GHCR to Docker Hub with retry - # This is much more efficient than pulling/pushing individual arch images + echo "Copying ${{ matrix.variant }} from GHCR to Docker Hub..." retry_with_backoff crane copy \ ghcr.io/chrislusf/seaweedfs:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }} \ chrislusf/seaweedfs:${{ env.RELEASE_TAG }}${{ matrix.tag_suffix }} - - echo "Successfully copied ${{ matrix.variant }} to Docker Hub" + echo "Copied ${{ matrix.variant }} to Docker Hub" + + - name: Clean up build artifacts + if: always() && (github.event_name != 'workflow_dispatch' || github.event.inputs.variant == 'all' || github.event.inputs.variant == matrix.variant) + run: | + sudo docker system prune -f + sudo rm -rf /tmp/go-build* # Report-only trivy scan: uploads fixable HIGH/CRITICAL findings to GitHub # Security for visibility, but never blocks the release. Releases (including @@ -418,7 +378,7 @@ jobs: # trivy-scan: vuln findings are reported but do not block `latest`. tag-latest: runs-on: ubuntu-latest - needs: [copy-to-dockerhub] + needs: [build] if: github.event_name == 'push' strategy: matrix: @@ -483,7 +443,7 @@ jobs: helm-release: runs-on: ubuntu-latest - needs: [copy-to-dockerhub] + needs: [build] if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' permissions: contents: write diff --git a/docker/Dockerfile.go_build b/docker/Dockerfile.go_build index 6aed44bd0..285748298 100644 --- a/docker/Dockerfile.go_build +++ b/docker/Dockerfile.go_build @@ -1,4 +1,6 @@ -FROM golang:1.25-alpine AS builder +# Pin the builder to the host arch and cross-compile the (CGO-free) Go binary, +# so arm64/arm/386 targets skip QEMU emulation of the whole compile. +FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS builder RUN apk add git g++ fuse RUN mkdir -p /go/src/github.com/seaweedfs/ ARG BRANCH=${BRANCH:-master} @@ -12,9 +14,12 @@ RUN cd /go/src/github.com/seaweedfs/seaweedfs && \ git checkout $BRANCH) || \ (echo "ERROR: Branch/commit $BRANCH not found in repository" && \ echo "Available branches:" && git branch -a && exit 1)) +ARG TARGETOS TARGETARCH TARGETVARIANT RUN cd /go/src/github.com/seaweedfs/seaweedfs/weed \ && export LDFLAGS="-X github.com/seaweedfs/seaweedfs/weed/util/version.COMMIT=$(git rev-parse --short HEAD)" \ - && CGO_ENABLED=0 go install -tags "$TAGS" -ldflags "-extldflags -static ${LDFLAGS}" + && export GOOS=$TARGETOS GOARCH=$TARGETARCH \ + && case "$TARGETARCH" in arm) export GOARM="${TARGETVARIANT#v}";; esac \ + && CGO_ENABLED=0 go build -tags "$TAGS" -ldflags "-extldflags -static ${LDFLAGS}" -o /go/bin/weed . # Rust volume server: use pre-built binary from CI when available (placed in # weed-volume-prebuilt/ by the build-rust-binaries job), otherwise compile