name: Release Binaries
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: write
jobs:
audit:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-audit and cargo-deny
run: |
cargo install cargo-audit --locked
cargo install cargo-deny --locked
- name: Run security audit
run: cargo audit
- name: Run cargo deny checks
run: cargo deny check all
build:
needs: audit
runs-on: ${{ matrix.os }}
environment: release
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
ext: ""
archive: tar.gz
- os: windows-latest
target: x86_64-pc-windows-msvc
ext: ".exe"
archive: zip
- os: macos-latest
target: x86_64-apple-darwin
ext: ""
archive: tar.gz
needs_signing: true
- os: macos-latest
target: aarch64-apple-darwin
ext: ""
archive: tar.gz
needs_signing: true
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl-tools (Linux only)
if: matrix.target == 'x86_64-unknown-linux-musl'
run: sudo apt-get update && sudo apt-get install -y musl-tools
- name: Build release binary
run: cargo build --locked --release --target ${{ matrix.target }}
- name: Strip binary (if available)
run: |
STRIP=$(which strip || true)
if [ -n "$STRIP" ] && [ -f target/${{ matrix.target }}/release/kelora${{ matrix.ext }} ]; then
$STRIP target/${{ matrix.target }}/release/kelora${{ matrix.ext }} || true
fi
shell: bash
- name: Import Code-Signing Certificate
if: runner.os == 'macOS' && matrix.needs_signing && vars.ENABLE_MACOS_SIGNING == 'true'
uses: apple-actions/import-codesign-certs@v2
with:
p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }}
p12-password: ${{ secrets.MACOS_CERTIFICATE_PWD }}
keychain: signing_temp
create-keychain: true
- name: Sign macOS Binary
if: runner.os == 'macOS' && matrix.needs_signing && vars.ENABLE_MACOS_SIGNING == 'true'
run: |
codesign --force --options runtime \
--entitlements entitlements.plist \
--sign "${{ secrets.MACOS_IDENTITY }}" \
"target/${{ matrix.target }}/release/kelora"
- name: Create ZIP for notarization (macOS)
if: runner.os == 'macOS' && matrix.needs_signing && vars.ENABLE_MACOS_SIGNING == 'true'
run: |
ditto -c -k --keepParent "target/${{ matrix.target }}/release/kelora" "kelora-${{ matrix.target }}.zip"
- name: Notarize macOS Binary
if: runner.os == 'macOS' && matrix.needs_signing && vars.ENABLE_MACOS_SIGNING == 'true'
run: |
xcrun notarytool submit "kelora-${{ matrix.target }}.zip" \
--apple-id "${{ secrets.APPLE_ID }}" \
--password "${{ secrets.APPLE_APP_PASSWORD }}" \
--team-id "${{ secrets.APPLE_TEAM_ID }}" \
--wait
# Extract the binary back
unzip -o "kelora-${{ matrix.target }}.zip"
# Verify signing
codesign -vvv --deep --strict "target/${{ matrix.target }}/release/kelora"
- name: Compress to .tar.gz (Unix)
if: matrix.archive == 'tar.gz'
run: |
cd target/${{ matrix.target }}/release
tar -czf kelora-${{ matrix.target }}.tar.gz kelora${{ matrix.ext }}
shell: bash
- name: Compress to .zip (Windows)
if: matrix.archive == 'zip' && matrix.os != 'macos-latest'
run: |
cd target/${{ matrix.target }}/release
powershell Compress-Archive -Path kelora.exe -DestinationPath kelora-${{ matrix.target }}.zip
- name: Extract changelog for this version
if: matrix.target == 'x86_64-unknown-linux-musl'
run: |
VERSION=${GITHUB_REF#refs/tags/v}
awk -v ver="$VERSION" '
/^## \[/ {
if (found) exit
if ($0 ~ "\\[" ver "\\]") found=1
}
found && !/^## \[/ { print }
' CHANGELOG.md > release_notes.md
shell: bash
- name: Verify release notes were extracted
if: matrix.target == 'x86_64-unknown-linux-musl'
run: |
VERSION=${GITHUB_REF#refs/tags/v}
if [ ! -s release_notes.md ]; then
echo "No changelog entry found for version ${VERSION} in CHANGELOG.md"
exit 1
fi
- name: Upload release asset
uses: softprops/action-gh-release@v2
with:
files: |
target/${{ matrix.target }}/release/kelora-${{ matrix.target }}.tar.gz
target/${{ matrix.target }}/release/kelora-${{ matrix.target }}.zip
body_path: ${{ matrix.target == 'x86_64-unknown-linux-musl' && 'release_notes.md' || '' }}
generate_release_notes: ${{ matrix.target == 'x86_64-unknown-linux-musl' }}
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-openbsd:
needs: audit
runs-on: ubuntu-latest
environment: release
strategy:
matrix:
openbsd_release: ["7.8", "7.7"]
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Build OpenBSD binary
uses: vmactions/openbsd-vm@v1
with:
usesh: true
copyback: true
release: ${{ matrix.openbsd_release }}
prepare: |
pkg_add rust
run: |
export PATH="$HOME/.cargo/bin:$PATH"
cargo build --locked --release --target x86_64-unknown-openbsd
cd target/x86_64-unknown-openbsd/release
tar -czf kelora-x86_64-unknown-openbsd-${{ matrix.openbsd_release }}.tar.gz kelora
- name: Upload OpenBSD release asset
uses: softprops/action-gh-release@v2
with:
files: target/x86_64-unknown-openbsd/release/kelora-x86_64-unknown-openbsd-${{ matrix.openbsd_release }}.tar.gz
generate_release_notes: false
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-freebsd:
needs: audit
runs-on: ubuntu-latest
environment: release
strategy:
matrix:
freebsd_release: ["14.3", "13.5"]
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Build FreeBSD binary
uses: vmactions/freebsd-vm@v1
with:
copyback: true
release: ${{ matrix.freebsd_release }}
prepare: |
pkg update -f
pkg install -y rust
run: |
export PATH="$HOME/.cargo/bin:$PATH"
cargo build --locked --release --target x86_64-unknown-freebsd
cd target/x86_64-unknown-freebsd/release
tar -czf kelora-x86_64-unknown-freebsd-${{ matrix.freebsd_release }}.tar.gz kelora
- name: Upload FreeBSD release asset
uses: softprops/action-gh-release@v2
with:
files: target/x86_64-unknown-freebsd/release/kelora-x86_64-unknown-freebsd-${{ matrix.freebsd_release }}.tar.gz
generate_release_notes: false
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish:
needs: [audit, build, build-openbsd, build-freebsd]
environment: release
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'alpha') && !contains(github.ref, 'beta') && !contains(github.ref, 'rc')
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --token "$CARGO_REGISTRY_TOKEN"