name: Release
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
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: Update version in Cargo.toml
run: |
VERSION=${{ steps.get_version.outputs.version }}
# 更新根 Cargo.toml
sed -i "s/^version = .*/version = \"$VERSION\"/" Cargo.toml
# 更新 macros/Cargo.toml(如果存在)
if [ -f "macros/Cargo.toml" ]; then
sed -i "s/^version = .*/version = \"$VERSION\"/" macros/Cargo.toml
fi
- 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 macros/Cargo.toml || true
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 Library
needs: update-version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Build library
run: cargo build --release --all-features --workspace
- name: Run tests
run: cargo test --all-features --workspace --release
- name: Package library
run: |
mkdir -p artifacts
tar czf artifacts/limiteron-${{ needs.update-version.outputs.version }}.tar.gz \
Cargo.toml Cargo.lock src/ macros/ examples/ tests/ docs/ scripts/
- name: Upload library artifacts
uses: actions/upload-artifact@v4
with:
name: library
path: artifacts/*
build-binaries:
name: Build Binary - ${{ matrix.target }}
needs: update-version
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
rust: stable
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
rust: stable
cross: true
- os: macos-latest
target: x86_64-apple-darwin
rust: stable
- os: macos-latest
target: aarch64-apple-darwin
rust: stable
- os: windows-latest
target: x86_64-pc-windows-msvc
rust: stable
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross
if: matrix.cross
run: cargo install cross
- name: Set up QEMU (for ARM cross-compilation)
if: matrix.cross
uses: docker/setup-qemu-action@v3
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
- name: Build binary
run: |
if [ "${{ matrix.cross }}" == "true" ]; then
cross build --release --target ${{ matrix.target }}
else
cargo build --release --target ${{ matrix.target }}
fi
shell: bash
- name: Package binary
run: |
mkdir -p artifacts
if [ "${{ matrix.os }}" == "windows-latest" ]; then
# Windows: 创建 zip
7z a artifacts/limiteron-${{ needs.update-version.outputs.version }}-${{ matrix.target }}.zip \
target/${{ matrix.target }}/release/*.dll target/${{ matrix.target }}/release/*.rlib
else
# Linux/macOS: 创建 tar.gz
tar czf artifacts/limiteron-${{ needs.update-version.outputs.version }}-${{ matrix.target }}.tar.gz \
-C target/${{ matrix.target }}/release *.rlib *.so *.dylib 2>/dev/null || true
fi
shell: bash
- name: Upload binary artifacts
uses: actions/upload-artifact@v4
with:
name: binary-${{ matrix.target }}
path: artifacts/*
release:
name: Create GitHub Release
needs: [update-version, build, build-binaries]
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 "## Installation" >> changelog.md
echo "" >> changelog.md
echo "### Cargo" >> changelog.md
echo '```toml' >> changelog.md
echo "[dependencies]" >> changelog.md
echo "limiteron = \"$VERSION\"" >> changelog.md
echo '```' >> changelog.md
echo "" >> changelog.md
echo "### Binaries" >> changelog.md
echo "" >> changelog.md
ls release-assets/*.tar.gz release-assets/*.zip 2>/dev/null | 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@v2
with:
files: release-assets/*
body_path: changelog.md
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-crates:
name: Publish to crates.io
needs: [update-version, build, build-binaries, release]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: main
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Login to crates.io
run: cargo login ${{ secrets.CRATES_IO_TOKEN }}
- name: Publish to crates.io
run: |
# 先发布宏包(如果有)
if [ -f "macros/Cargo.toml" ]; then
cd macros && cargo publish && cd ..
sleep 30 # 等待 crates.io 索引更新
fi
# 发布主包
cargo publish