name: Build Linux Binaries and Release
on:
workflow_dispatch:
inputs:
debug_mode:
description: 'Enable debug mode (save artifacts without release)'
required: false
default: false
type: boolean
enable_release:
description: 'Enable GitHub Release creation'
required: false
default: true
type: boolean
build_static:
description: 'Build static binaries using musl target'
required: false
default: true
type: boolean
build_deb_package:
description: 'Build .deb package for Debian/Ubuntu'
required: false
default: false
type: boolean
env:
BINARY_NAME: ${{ github.event.repository.name }}
DEBIAN_FRONTEND: noninteractive
jobs:
build-linux-binaries:
name: Build Linux Binaries
runs-on: ubuntu-latest
strategy:
matrix:
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
steps:
- uses: actions/checkout@v4
- name: Set up flags
id: flags
run: |
if [ "${{ inputs.debug_mode }}" = "true" ]; then
echo "debug_mode=true" >> $GITHUB_OUTPUT
else
echo "debug_mode=false" >> $GITHUB_OUTPUT
fi
if [ "${{ inputs.enable_release }}" = "true" ]; then
echo "enable_release=true" >> $GITHUB_OUTPUT
else
echo "enable_release=false" >> $GITHUB_OUTPUT
fi
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y musl-tools file
if [ "${{ inputs.build_deb_package }}" = "true" ] && [ "${{ matrix.target }}" = "x86_64-unknown-linux-gnu" ]; then
sudo apt-get install -y devscripts debhelper dh-make fakeroot
fi
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Build
run: |
if [[ "${{ matrix.target }}" == *"musl"* ]]; then
export RUSTFLAGS="-C linker=musl-gcc"
fi
cargo build --release --target ${{ matrix.target }}
- name: Build .deb package
if: ${{ inputs.build_deb_package && matrix.target == 'x86_64-unknown-linux-gnu' }}
run: |
binary_path="target/${{ matrix.target }}/release/$BINARY_NAME"
if [ ! -f "$binary_path" ]; then
echo "❌ Binary not found"
exit 0
fi
# 创建目录结构
DEB_DIR="deb_package"
mkdir -p "$DEB_DIR/DEBIAN"
mkdir -p "$DEB_DIR/usr/bin"
mkdir -p "$DEB_DIR/usr/share/doc/$BINARY_NAME"
# 复制二进制
cp "$binary_path" "$DEB_DIR/usr/bin/$BINARY_NAME"
chmod 755 "$DEB_DIR/usr/bin/$BINARY_NAME"
# 获取版本
VERSION="1.0.0"
if "$binary_path" --version 2>/dev/null; then
VERSION=$("$binary_path" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
fi
# 使用 echo 创建 control 文件,避免 heredoc 问题
echo "Package: $BINARY_NAME" > "$DEB_DIR/DEBIAN/control"
echo "Version: ${VERSION}-1" >> "$DEB_DIR/DEBIAN/control"
echo "Section: utils" >> "$DEB_DIR/DEBIAN/control"
echo "Priority: optional" >> "$DEB_DIR/DEBIAN/control"
echo "Architecture: amd64" >> "$DEB_DIR/DEBIAN/control"
echo "Depends: libc6 (>= 2.31)" >> "$DEB_DIR/DEBIAN/control"
echo "Maintainer: GitHub Actions <actions@github.com>" >> "$DEB_DIR/DEBIAN/control"
echo "Description: $BINARY_NAME - Built with GitHub Actions" >> "$DEB_DIR/DEBIAN/control"
echo " This package contains $BINARY_NAME built for Debian/Ubuntu systems." >> "$DEB_DIR/DEBIAN/control"
echo " The binary was compiled on GitHub Actions and is ready for installation." >> "$DEB_DIR/DEBIAN/control"
# 构建 .deb
DEB_NAME="${BINARY_NAME}_${VERSION}_amd64.deb"
fakeroot dpkg-deb --build "$DEB_DIR" "$DEB_NAME"
mkdir -p release-artifacts
cp "$DEB_NAME" release-artifacts/
echo "✅ .deb package created"
- name: Prepare artifacts
if: ${{ inputs.enable_release == 'true' }}
run: |
binary_path="target/${{ matrix.target }}/release/$BINARY_NAME"
mkdir -p release-artifacts
if [ -f "$binary_path" ]; then
if [[ "${{ matrix.target }}" == *"musl"* ]]; then
cp "$binary_path" "release-artifacts/$BINARY_NAME-linux-musl"
else
cp "$binary_path" "release-artifacts/$BINARY_NAME-linux-gnu"
fi
chmod +x release-artifacts/*
fi
- name: Upload artifacts
if: ${{ inputs.enable_release == 'true' }}
uses: actions/upload-artifact@v4
with:
name: linux-${{ matrix.target }}
path: release-artifacts/
retention-days: 1
create-release:
name: Create Release
runs-on: ubuntu-latest
needs: build-linux-binaries
permissions:
contents: write
if: >
(github.event.inputs.enable_release == 'true' || github.event_name == 'push') &&
github.event.inputs.debug_mode != 'true' &&
startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release files
run: |
mkdir -p release-files
# 查找所有 artifact
find artifacts -type f | while read file; do
filename=$(basename "$file")
cp "$file" "release-files/$filename"
done
# 创建校验和
cd release-files
for file in *; do
sha256sum "$file" > "$file.sha256"
sha512sum "$file" > "$file.sha512"
done
- uses: softprops/action-gh-release@v1
with:
files: release-files/*
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}