name: Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+*"
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
test:
name: Test before release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ubuntu-latest-cargo-${{ hashFiles('Cargo.lock') }}
- run: cargo test --release
build:
name: Build release binary (${{ matrix.target }})
needs: test
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
binary_suffix: ""
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
binary_suffix: ""
- os: windows-latest
target: x86_64-pc-windows-msvc
binary_suffix: ".exe"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross-compilation tools (aarch64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('Cargo.lock') }}
- name: Build train_generic binary
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
run: cargo build --release --bin train_generic --target ${{ matrix.target }}
- name: Package binary
shell: bash
run: |
TAG=${GITHUB_REF_NAME}
BIN_NAME="train_generic-${TAG}-${{ matrix.target }}${{ matrix.binary_suffix }}"
cp target/${{ matrix.target }}/release/train_generic${{ matrix.binary_suffix }} "${BIN_NAME}"
echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_ENV
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.BIN_NAME }}
path: ${{ env.BIN_NAME }}
github-release:
name: Create GitHub Release
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts/
- name: Extract changelog entry
id: changelog
run: |
TAG=${GITHUB_REF_NAME}
VERSION=${TAG#v}
NOTES=$(awk "/^## \[${VERSION}\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md | head -50)
{
echo "NOTES<<EOF"
echo "$NOTES"
echo "EOF"
} >> $GITHUB_ENV
- name: Create Release
uses: softprops/action-gh-release@v2
with:
body: ${{ env.NOTES }}
files: artifacts/**/*
fail_on_unmatched_files: false
publish-crate:
name: Publish to crates.io
needs: github-release
runs-on: ubuntu-latest
if: "!contains(github.ref_name, '-')" steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --no-verify
publish-pypi:
name: Publish Python wheels to PyPI
needs: github-release
runs-on: ${{ matrix.platform.os }}
if: "!contains(github.ref_name, '-')" strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
platform:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
manylinux: "2_28"
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
manylinux: "2_28"
- os: macos-latest
target: x86_64-apple-darwin
- os: macos-latest
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- name: Set up Python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Build wheels with maturin
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
manylinux: ${{ matrix.platform.manylinux || 'auto' }}
args: --release --out dist -i ${{ matrix.platform.os == 'windows-latest' && 'python' || format('python{0}', matrix.python-version) }} --compatibility pypi
sccache: "true"
maturin-version: "v1.13.3"
- name: Upload wheel artifacts
uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.platform.os }}-${{ matrix.platform.target }}-py${{ matrix.python-version }}
path: dist/*
upload-pypi:
name: Publish wheels to PyPI
needs: publish-pypi
runs-on: ubuntu-latest
if: "!contains(github.ref_name, '-')"
steps:
- name: Download wheel artifacts
uses: actions/download-artifact@v4
with:
pattern: wheels-*
path: dist/
merge-multiple: true
- name: Upload wheels to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
packages-dir: dist/
skip-existing: true