name: Release
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
id-token: write
env:
CARGO_TERM_COLOR: always
jobs:
update-version:
name: Update Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get version from tag
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-edit
run: cargo install cargo-edit
- name: Update Cargo.toml version
run: |
VERSION=${{ steps.get_version.outputs.version }}
cargo set-version $VERSION
- name: Commit version changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock
git commit -m "chore: bump version to ${{ steps.get_version.outputs.version }}" || echo "No changes to commit"
git push origin HEAD:main || echo "Failed to push, continuing..."
build:
name: Build ${{ matrix.target }}
needs: update-version
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
cross: true
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross-compilation tools
if: matrix.cross
run: |
cargo install cross --git https://github.com/cross-rs/cross
- name: Build binaries
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
cross build --release --target ${{ matrix.target }} --bins
else
cargo build --release --target ${{ matrix.target }} --bins
fi
- name: Package binaries
run: |
mkdir -p artifacts
cd target/${{ matrix.target }}/release
# 查找所有二进制文件(排除 .d 文件和库文件)
for binary in $(find . -maxdepth 1 -type f -executable ! -name "*.d" ! -name "*.so" ! -name "*.dylib" ! -name "*.dll"); do
binary_name=$(basename "$binary")
# 创建 tar.gz 包
tar czf "../../../artifacts/${binary_name}-${{ needs.update-version.outputs.version }}-${{ matrix.target }}.tar.gz" "$binary_name"
# 生成 SHA256
sha256sum "$binary_name" | awk '{print $1}' > "../../../artifacts/${binary_name}-${{ needs.update-version.outputs.version }}-${{ matrix.target }}.tar.gz.sha256"
done
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.target }}
path: artifacts/*
release:
name: Create GitHub Release
needs: [update-version, build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release assets
run: |
mkdir -p release-assets
find artifacts -type f -exec cp {} release-assets/ \;
ls -lah release-assets/
- name: Generate changelog
id: changelog
run: |
VERSION=${{ needs.update-version.outputs.version }}
# 获取上一个 tag
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
echo "## What's Changed" > changelog.md
echo "" >> changelog.md
if [ -n "$PREV_TAG" ]; then
git log $PREV_TAG..HEAD --pretty=format:"- %s (%h)" >> changelog.md
else
git log --pretty=format:"- %s (%h)" >> changelog.md
fi
echo "" >> changelog.md
echo "" >> changelog.md
echo "## Assets" >> changelog.md
echo "" >> changelog.md
echo "### Binaries" >> changelog.md
ls release-assets/*.tar.gz | while read file; do
basename_file=$(basename "$file")
echo "- \`$basename_file\`" >> changelog.md
done
cat changelog.md
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: release-assets/*
body_path: changelog.md
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-crates:
name: Publish to crates.io
needs: [update-version, build]
runs-on: ubuntu-latest
environment:
name: crates.io
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
run: |
# 等待 crates.io 索引更新(如果有依赖)
sleep 5
# 发布 workspace 中的所有 crate
# 如果有多个 crate,按依赖顺序发布
cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}