Files
rustfs/.github/workflows/build.yml
2025-06-24 22:43:39 +08:00

529 lines
19 KiB
YAML

name: Build RustFS And GUI
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0" # at midnight of each sunday
push:
branches:
- main
tags: [ "v*", "*" ]
jobs:
build-rustfs:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
variant:
- {
profile: release,
target: x86_64-unknown-linux-musl,
glibc: "default",
}
- {
profile: release,
target: x86_64-unknown-linux-gnu,
glibc: "default",
}
- { profile: release, target: aarch64-apple-darwin, glibc: "default" }
#- { profile: release, target: aarch64-unknown-linux-gnu, glibc: "default" }
- {
profile: release,
target: aarch64-unknown-linux-musl,
glibc: "default",
}
#- { profile: release, target: x86_64-pc-windows-msvc, glibc: "default" }
exclude:
# Linux targets on non-Linux systems
- os: macos-latest
variant:
{
profile: release,
target: x86_64-unknown-linux-gnu,
glibc: "default",
}
- os: macos-latest
variant:
{
profile: release,
target: x86_64-unknown-linux-musl,
glibc: "default",
}
- os: macos-latest
variant:
{
profile: release,
target: aarch64-unknown-linux-gnu,
glibc: "default",
}
- os: macos-latest
variant:
{
profile: release,
target: aarch64-unknown-linux-musl,
glibc: "default",
}
- os: windows-latest
variant:
{
profile: release,
target: x86_64-unknown-linux-gnu,
glibc: "default",
}
- os: windows-latest
variant:
{
profile: release,
target: x86_64-unknown-linux-musl,
glibc: "default",
}
- os: windows-latest
variant:
{
profile: release,
target: aarch64-unknown-linux-gnu,
glibc: "default",
}
- os: windows-latest
variant:
{
profile: release,
target: aarch64-unknown-linux-musl,
glibc: "default",
}
# Apple targets on non-macOS systems
- os: ubuntu-latest
variant:
{
profile: release,
target: aarch64-apple-darwin,
glibc: "default",
}
- os: windows-latest
variant:
{
profile: release,
target: aarch64-apple-darwin,
glibc: "default",
}
# Windows targets on non-Windows systems
- os: ubuntu-latest
variant:
{
profile: release,
target: x86_64-pc-windows-msvc,
glibc: "default",
}
- os: macos-latest
variant:
{
profile: release,
target: x86_64-pc-windows-msvc,
glibc: "default",
}
steps:
- name: Checkout repository
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
# Installation system dependencies
- name: Install system dependencies (Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt update
sudo apt install -y musl-tools build-essential lld libdbus-1-dev libwayland-dev libwebkit2gtk-4.1-dev libxdo-dev
shell: bash
#Install Rust using dtolnay/rust-toolchain
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
targets: ${{ matrix.variant.target }}
components: rustfmt, clippy
# Install system dependencies
- name: Cache Protoc
id: cache-protoc
uses: actions/cache@v4.2.3
with:
path: /Users/runner/hostedtoolcache/protoc
key: protoc-${{ runner.os }}-31.1
restore-keys: |
protoc-${{ runner.os }}-
- name: Install Protoc
if: steps.cache-protoc.outputs.cache-hit != 'true'
uses: arduino/setup-protoc@v3
with:
version: "31.1"
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Flatc
uses: Nugine/setup-flatc@v1
with:
version: "25.2.10"
# Cache Cargo dependencies
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
cache-all-crates: true
shared-key: rustfs-${{ matrix.os }}-${{ matrix.variant.profile }}-${{ matrix.variant.target }}-${{ matrix.variant.glibc }}-${{ hashFiles('**/Cargo.lock') }}
save-if: ${{ github.event_name != 'pull_request' }}
# Set up Zig for cross-compilation
- uses: mlugg/setup-zig@v2
if: matrix.variant.glibc != 'default' || contains(matrix.variant.target, 'aarch64-unknown-linux')
- uses: taiki-e/install-action@cargo-zigbuild
if: matrix.variant.glibc != 'default' || contains(matrix.variant.target, 'aarch64-unknown-linux')
# Download static resources
- name: Download and Extract Static Assets
run: |
url="https://dl.rustfs.com/artifacts/console/rustfs-console-latest.zip"
# Create a static resource directory
mkdir -p ./rustfs/static
# Download static resources
echo "::group::Downloading static assets"
curl -L -o static_assets.zip "$url" --retry 3
# Unzip static resources
echo "::group::Extracting static assets"
if [ "${{ runner.os }}" = "Windows" ]; then
7z x static_assets.zip -o./rustfs/static
del static_assets.zip
else
unzip -o static_assets.zip -d ./rustfs/static
rm static_assets.zip
fi
echo "::group::Static assets content"
ls -la ./rustfs/static
shell: bash
# Build rustfs
- name: Build rustfs
id: build
shell: bash
run: |
echo "::group::Setting up build parameters"
PROFILE="${{ matrix.variant.profile }}"
TARGET="${{ matrix.variant.target }}"
GLIBC="${{ matrix.variant.glibc }}"
# Determine whether to use zigbuild
USE_ZIGBUILD=false
if [[ "$GLIBC" != "default" || "$TARGET" == *"aarch64-unknown-linux"* ]]; then
USE_ZIGBUILD=true
echo "Using zigbuild for cross-compilation"
fi
# Determine the target parameters
TARGET_ARG="$TARGET"
if [[ "$GLIBC" != "default" ]]; then
TARGET_ARG="${TARGET}.${GLIBC}"
echo "Using custom glibc target: $TARGET_ARG"
fi
# Confirm the profile directory name
if [[ "$PROFILE" == "dev" ]]; then
PROFILE_DIR="debug"
else
PROFILE_DIR="$PROFILE"
fi
# Determine the binary suffix
BIN_SUFFIX=""
if [[ "${{ matrix.variant.target }}" == *"windows"* ]]; then
BIN_SUFFIX=".exe"
fi
# Determine the binary name - Use the appropriate extension for Windows
BIN_NAME="rustfs.${PROFILE}.${TARGET}"
if [[ "$GLIBC" != "default" ]]; then
BIN_NAME="${BIN_NAME}.glibc${GLIBC}"
fi
# Windows systems use exe suffix, and other systems do not have suffix
if [[ "${{ matrix.variant.target }}" == *"windows"* ]]; then
BIN_NAME="${BIN_NAME}.exe"
else
BIN_NAME="${BIN_NAME}.bin"
fi
echo "Binary name will be: $BIN_NAME"
echo "::group::Building rustfs"
# Refresh build information
touch rustfs/build.rs
# Identify the build command and execute it
if [[ "$USE_ZIGBUILD" == "true" ]]; then
echo "Build command: cargo zigbuild --profile $PROFILE --target $TARGET_ARG -p rustfs --bins"
cargo zigbuild --profile $PROFILE --target $TARGET_ARG -p rustfs --bins
else
echo "Build command: cargo build --profile $PROFILE --target $TARGET_ARG -p rustfs --bins"
cargo build --profile $PROFILE --target $TARGET_ARG -p rustfs --bins
fi
# Determine the binary path and output path
BIN_PATH="target/${TARGET_ARG}/${PROFILE_DIR}/rustfs${BIN_SUFFIX}"
OUT_PATH="target/artifacts/${BIN_NAME}"
# Create a target directory
mkdir -p target/artifacts
echo "Copying binary from ${BIN_PATH} to ${OUT_PATH}"
cp "${BIN_PATH}" "${OUT_PATH}"
# Record the output path for use in the next steps
echo "bin_path=${OUT_PATH}" >> $GITHUB_OUTPUT
echo "bin_name=${BIN_NAME}" >> $GITHUB_OUTPUT
- name: Package Binary and Static Assets
id: package
run: |
# Create component file name
ARTIFACT_NAME="rustfs-${{ matrix.variant.profile }}-${{ matrix.variant.target }}"
if [ "${{ matrix.variant.glibc }}" != "default" ]; then
ARTIFACT_NAME="${ARTIFACT_NAME}-glibc${{ matrix.variant.glibc }}"
fi
echo "artifact_name=${ARTIFACT_NAME}" >> $GITHUB_OUTPUT
# Get the binary path
BIN_PATH="${{ steps.build.outputs.bin_path }}"
# Create a packaged directory structure - only contains bin and docs directories
mkdir -p ${ARTIFACT_NAME}/{bin,docs}
# Copy binary files (note the difference between Windows and other systems)
if [[ "${{ matrix.variant.target }}" == *"windows"* ]]; then
cp "${BIN_PATH}" ${ARTIFACT_NAME}/bin/rustfs.exe
else
cp "${BIN_PATH}" ${ARTIFACT_NAME}/bin/rustfs
fi
# copy documents and licenses
if [ -f "LICENSE" ]; then
cp LICENSE ${ARTIFACT_NAME}/docs/
fi
if [ -f "README.md" ]; then
cp README.md ${ARTIFACT_NAME}/docs/
fi
# Packaged as zip
if [ "${{ runner.os }}" = "Windows" ]; then
7z a ${ARTIFACT_NAME}.zip ${ARTIFACT_NAME}
else
zip -r ${ARTIFACT_NAME}.zip ${ARTIFACT_NAME}
fi
echo "Created artifact: ${ARTIFACT_NAME}.zip"
ls -la ${ARTIFACT_NAME}.zip
shell: bash
- uses: actions/upload-artifact@v4
with:
name: ${{ steps.package.outputs.artifact_name }}
path: ${{ steps.package.outputs.artifact_name }}.zip
retention-days: 7
# Install ossutil2 tool for OSS upload
- name: Install ossutil2
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
shell: bash
run: |
echo "::group::Installing ossutil2"
# Download and install ossutil based on platform
if [ "${{ runner.os }}" = "Linux" ]; then
curl -o ossutil.zip https://gosspublic.alicdn.com/ossutil/v2/2.1.1/ossutil-2.1.1-linux-amd64.zip
unzip -o ossutil.zip
chmod 755 ossutil-2.1.1-linux-amd64/ossutil
sudo mv ossutil-2.1.1-linux-amd64/ossutil /usr/local/bin/
rm -rf ossutil.zip ossutil-2.1.1-linux-amd64
elif [ "${{ runner.os }}" = "macOS" ]; then
if [ "$(uname -m)" = "arm64" ]; then
curl -o ossutil.zip https://gosspublic.alicdn.com/ossutil/v2/2.1.1/ossutil-2.1.1-mac-arm64.zip
else
curl -o ossutil.zip https://gosspublic.alicdn.com/ossutil/v2/2.1.1/ossutil-2.1.1-mac-amd64.zip
fi
unzip -o ossutil.zip
chmod 755 ossutil-*/ossutil
sudo mv ossutil-*/ossutil /usr/local/bin/
rm -rf ossutil.zip ossutil-*
elif [ "${{ runner.os }}" = "Windows" ]; then
curl -o ossutil.zip https://gosspublic.alicdn.com/ossutil/v2/2.1.1/ossutil-2.1.1-windows-amd64.zip
unzip -o ossutil.zip
mv ossutil-*/ossutil.exe /usr/bin/ossutil.exe
rm -rf ossutil.zip ossutil-*
fi
echo "ossutil2 installation completed"
# Set the OSS configuration
ossutil config set Region oss-cn-beijing
ossutil config set endpoint oss-cn-beijing.aliyuncs.com
ossutil config set accessKeyID ${{ secrets.ALICLOUDOSS_KEY_ID }}
ossutil config set accessKeySecret ${{ secrets.ALICLOUDOSS_KEY_SECRET }}
- name: Upload to Aliyun OSS
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
shell: bash
env:
OSSUTIL_ACCESS_KEY_ID: ${{ secrets.ALICLOUDOSS_KEY_ID }}
OSSUTIL_ACCESS_KEY_SECRET: ${{ secrets.ALICLOUDOSS_KEY_SECRET }}
OSSUTIL_ENDPOINT: https://oss-accelerate.aliyuncs.com
run: |
echo "::group::Uploading files to OSS"
# Upload the artifact file to two different paths
ossutil cp "${{ steps.package.outputs.artifact_name }}.zip" "oss://rustfs-artifacts/artifacts/rustfs/${{ steps.package.outputs.artifact_name }}.zip" --force
ossutil cp "${{ steps.package.outputs.artifact_name }}.zip" "oss://rustfs-artifacts/artifacts/rustfs/${{ steps.package.outputs.artifact_name }}.latest.zip" --force
echo "Successfully uploaded artifacts to OSS"
# Determine whether to perform GUI construction based on conditions
- name: Prepare for GUI build
if: startsWith(github.ref, 'refs/tags/')
id: prepare_gui
run: |
# Create a target directory
mkdir -p ./cli/rustfs-gui/embedded-rustfs/
# Copy the currently built binary to the embedded-rustfs directory
if [[ "${{ matrix.variant.target }}" == *"windows"* ]]; then
cp "${{ steps.build.outputs.bin_path }}" ./cli/rustfs-gui/embedded-rustfs/rustfs.exe
else
cp "${{ steps.build.outputs.bin_path }}" ./cli/rustfs-gui/embedded-rustfs/rustfs
fi
echo "Copied binary to embedded-rustfs directory"
ls -la ./cli/rustfs-gui/embedded-rustfs/
shell: bash
#Install the dioxus-cli tool
- uses: taiki-e/cache-cargo-install-action@v2
if: startsWith(github.ref, 'refs/tags/')
with:
tool: dioxus-cli
# Build and package GUI applications
- name: Build and Bundle rustfs-gui
if: startsWith(github.ref, 'refs/tags/')
id: build_gui
shell: bash
run: |
echo "::group::Setting up build parameters for GUI"
PROFILE="${{ matrix.variant.profile }}"
TARGET="${{ matrix.variant.target }}"
GLIBC="${{ matrix.variant.glibc }}"
RELEASE_PATH="target/artifacts/$TARGET"
# Make sure the output directory exists
mkdir -p ${RELEASE_PATH}
# Configure the target platform linker
echo "::group::Configuring linker for $TARGET"
case "$TARGET" in
"x86_64-unknown-linux-gnu")
export CC_x86_64_unknown_linux_gnu=gcc
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=gcc
;;
"x86_64-unknown-linux-musl")
export CC_x86_64_unknown_linux_musl=musl-gcc
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc
;;
"aarch64-unknown-linux-gnu")
export CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
;;
"aarch64-unknown-linux-musl")
export CC_aarch64_unknown_linux_musl=aarch64-linux-musl-gcc
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-musl-gcc
;;
"aarch64-apple-darwin")
export CC_aarch64_apple_darwin=clang
export CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER=clang
;;
"x86_64-pc-windows-msvc")
export CC_x86_64_pc_windows_msvc=cl
export CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER=link
;;
esac
echo "::group::Building GUI application"
cd cli/rustfs-gui
# Building according to the target platform
if [[ "$TARGET" == *"apple-darwin"* ]]; then
echo "Building for macOS"
dx bundle --platform macos --package-types "macos" --package-types "dmg" --release --profile ${PROFILE} --out-dir ../../${RELEASE_PATH}
elif [[ "$TARGET" == *"windows-msvc"* ]]; then
echo "Building for Windows"
dx bundle --platform windows --package-types "msi" --release --profile ${PROFILE} --out-dir ../../${RELEASE_PATH}
elif [[ "$TARGET" == *"linux"* ]]; then
echo "Building for Linux"
dx bundle --platform linux --package-types "deb" --package-types "rpm" --package-types "appimage" --release --profile ${PROFILE} --out-dir ../../${RELEASE_PATH}
fi
cd ../..
# Create component name
GUI_ARTIFACT_NAME="rustfs-gui-${PROFILE}-${TARGET}"
if [ "$GLIBC" != "default" ]; then
GUI_ARTIFACT_NAME="${GUI_ARTIFACT_NAME}-glibc${GLIBC}"
fi
echo "::group::Packaging GUI application"
# Select packaging method according to the operating system
if [ "${{ runner.os }}" = "Windows" ]; then
7z a ${GUI_ARTIFACT_NAME}.zip ${RELEASE_PATH}/*
else
zip -r ${GUI_ARTIFACT_NAME}.zip ${RELEASE_PATH}/*
fi
echo "gui_artifact_name=${GUI_ARTIFACT_NAME}" >> $GITHUB_OUTPUT
echo "Created GUI artifact: ${GUI_ARTIFACT_NAME}.zip"
ls -la ${GUI_ARTIFACT_NAME}.zip
# Upload GUI components
- uses: actions/upload-artifact@v4
if: startsWith(github.ref, 'refs/tags/')
with:
name: ${{ steps.build_gui.outputs.gui_artifact_name }}
path: ${{ steps.build_gui.outputs.gui_artifact_name }}.zip
retention-days: 7
# Upload GUI to Alibaba Cloud OSS
- name: Upload GUI to Aliyun OSS
if: startsWith(github.ref, 'refs/tags/')
shell: bash
env:
OSSUTIL_ACCESS_KEY_ID: ${{ secrets.ALICLOUDOSS_KEY_ID }}
OSSUTIL_ACCESS_KEY_SECRET: ${{ secrets.ALICLOUDOSS_KEY_SECRET }}
OSSUTIL_ENDPOINT: https://oss-accelerate.aliyuncs.com
run: |
echo "::group::Uploading GUI files to OSS"
# Upload the GUI artifact file to two different paths
ossutil cp "${{ steps.build_gui.outputs.gui_artifact_name }}.zip" "oss://rustfs-artifacts/artifacts/rustfs/${{ steps.build_gui.outputs.gui_artifact_name }}.zip" --force
ossutil cp "${{ steps.build_gui.outputs.gui_artifact_name }}.zip" "oss://rustfs-artifacts/artifacts/rustfs/${{ steps.build_gui.outputs.gui_artifact_name }}.latest.zip" --force
echo "Successfully uploaded GUI artifacts to OSS"
merge:
runs-on: ubuntu-latest
needs: [ build-rustfs ]
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/upload-artifact/merge@v4
with:
name: rustfs-packages
pattern: "rustfs-*"
delete-merged: true