Skip to content

0.7.1 - See changelog for updates. #70

0.7.1 - See changelog for updates.

0.7.1 - See changelog for updates. #70

Workflow file for this run

name: CI
on:
push:
branches: [main, dev]
tags: ["v*"]
pull_request:
branches: [main, dev]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-Dwarnings"
permissions:
contents: write
id-token: write
# =============================================================================
# Tier 1 — CI (runs on every push and PR)
# =============================================================================
jobs:
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
components: rustfmt
- run: cargo fmt --all --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --workspace --exclude rusty-bacnet --exclude bacnet-wasm --all-targets
wasm-check:
name: WASM Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
- run: cargo check -p bacnet-wasm --target wasm32-unknown-unknown
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Linux: full feature set (serial + ethernet are Linux-only deps)
- os: ubuntu-latest
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls,bacnet-transport/serial,bacnet-transport/ethernet"
# macOS: ipv6 + sc-tls only
- os: macos-latest
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls"
# Windows: ipv6 + sc-tls only
- os: windows-latest
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.os }}
- run: cargo test --workspace --exclude rusty-bacnet --exclude bacnet-wasm ${{ matrix.features }}
deny:
name: Cargo Deny
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
# ===========================================================================
# Tier 2 — Release (only on v* tags, after all CI passes)
# ===========================================================================
validate:
name: Validate Release
if: startsWith(github.ref, 'refs/tags/v')
needs: [fmt, clippy, test, deny, wasm-check]
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Extract and validate version
id: version
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
CARGO_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "::error::Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION)"
exit 1
fi
echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT"
- name: Check CHANGELOG.md
run: |
VERSION="${{ steps.version.outputs.version }}"
if ! grep -q "## \[$VERSION\]" CHANGELOG.md; then
echo "::error::CHANGELOG.md missing entry for version $VERSION"
exit 1
fi
publish-crates:
name: Publish to crates.io
if: startsWith(github.ref, 'refs/tags/v')
needs: validate
runs-on: ubuntu-latest
environment: release
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
- uses: Swatinem/rust-cache@v2
- name: Publish bacnet-types
run: cargo publish -p bacnet-types --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-encoding
run: cargo publish -p bacnet-encoding --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-services
run: cargo publish -p bacnet-services --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-transport
run: cargo publish -p bacnet-transport --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-network
run: cargo publish -p bacnet-network --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-objects
run: cargo publish -p bacnet-objects --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-server
run: cargo publish -p bacnet-server --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: sleep 30
- name: Publish bacnet-client
run: cargo publish -p bacnet-client --no-verify
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
build-wheels:
name: Wheels (${{ matrix.os }} ${{ matrix.target }})
if: startsWith(github.ref, 'refs/tags/v')
needs: validate
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64
- os: ubuntu-24.04-arm
target: aarch64
- os: macos-latest
target: x86_64
- os: macos-latest
target: aarch64
- os: windows-latest
target: x86_64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist -m crates/rusty-bacnet/Cargo.toml -i 3.11 3.12 3.13
manylinux: auto
sccache: true
before-script-linux: |
if command -v yum &> /dev/null; then
yum install -y perl-IPC-Cmd cmake3 || true
ln -sf /usr/bin/cmake3 /usr/local/bin/cmake || true
elif command -v apk &> /dev/null; then
apk add --no-cache cmake perl make
fi
- uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.os }}-${{ matrix.target }}
path: dist
build-sdist:
name: Build sdist
if: startsWith(github.ref, 'refs/tags/v')
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build sdist
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist -m crates/rusty-bacnet/Cargo.toml
- uses: actions/upload-artifact@v4
with:
name: wheels-sdist
path: dist
build-wasm:
name: Build WASM
if: startsWith(github.ref, 'refs/tags/v')
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Build (bundler target)
run: wasm-pack build crates/bacnet-wasm --target bundler --out-dir ../../dist/wasm-npm
- name: Build (web target)
run: wasm-pack build crates/bacnet-wasm --target web --out-dir ../../dist/wasm-web
- uses: actions/upload-artifact@v4
with:
name: wasm-npm
path: dist/wasm-npm
- uses: actions/upload-artifact@v4
with:
name: wasm-web
path: dist/wasm-web
publish-pypi:
name: Publish to PyPI
if: startsWith(github.ref, 'refs/tags/v')
needs: [build-wheels, build-sdist]
runs-on: ubuntu-latest
environment: release
steps:
- uses: actions/download-artifact@v4
with:
pattern: wheels-*
merge-multiple: true
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
publish-npm:
name: Publish to npm
if: startsWith(github.ref, 'refs/tags/v')
needs: [build-wasm]
runs-on: ubuntu-latest
environment: release
steps:
- uses: actions/download-artifact@v4
with:
name: wasm-npm
path: dist/wasm-npm
- uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Upgrade npm for trusted publishing
run: npm install -g npm@latest
- name: Publish to npm
run: cd dist/wasm-npm && npm publish --provenance --access public
github-release:
name: GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
needs: [publish-crates, publish-pypi, publish-npm, publish-java, build-cli-binaries]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: java-jar
path: dist/java
- uses: actions/download-artifact@v4
with:
pattern: cli-*
path: dist/cli
merge-multiple: true
- uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
dist/java/*.jar
dist/cli/bacnet-*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ===========================================================================
# Tier 2c — CLI binary distribution
# ===========================================================================
build-cli-binaries:
name: CLI Binary (${{ matrix.target }})
if: startsWith(github.ref, 'refs/tags/v')
needs: validate
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
binary: bacnet-linux-amd64
features: "pcap,sc-tls"
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
binary: bacnet-linux-arm64
features: "pcap,sc-tls"
- os: macos-latest
target: x86_64-apple-darwin
binary: bacnet-macos-amd64
features: "sc-tls"
- os: macos-latest
target: aarch64-apple-darwin
binary: bacnet-macos-arm64
features: "sc-tls"
- os: windows-latest
target: x86_64-pc-windows-msvc
binary: bacnet-windows-amd64.exe
features: "sc-tls"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: cli-${{ matrix.target }}
- name: Install libpcap (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libpcap-dev
- name: Build CLI
run: cargo build --release -p bacnet-cli --target ${{ matrix.target }} --features ${{ matrix.features }}
- name: Rename binary
shell: bash
run: |
src="target/${{ matrix.target }}/release/bacnet"
if [ "${{ runner.os }}" = "Windows" ]; then
src="${src}.exe"
fi
cp "$src" "${{ matrix.binary }}"
- uses: actions/upload-artifact@v4
with:
name: cli-${{ matrix.target }}
path: ${{ matrix.binary }}
# ===========================================================================
# Tier 2b — Java/Kotlin release
# ===========================================================================
build-java-native:
name: Java Native (${{ matrix.os }} ${{ matrix.target }})
if: startsWith(github.ref, 'refs/tags/v')
needs: validate
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
jna_dir: linux-x86-64
lib_name: libbacnet_java.so
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls,bacnet-transport/serial,bacnet-transport/ethernet"
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
jna_dir: linux-aarch64
lib_name: libbacnet_java.so
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls,bacnet-transport/serial,bacnet-transport/ethernet"
- os: macos-latest
target: x86_64-apple-darwin
jna_dir: darwin-x86-64
lib_name: libbacnet_java.dylib
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls"
- os: macos-latest
target: aarch64-apple-darwin
jna_dir: darwin-aarch64
lib_name: libbacnet_java.dylib
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls"
- os: windows-latest
target: x86_64-pc-windows-msvc
jna_dir: win32-x86-64
lib_name: bacnet_java.dll
features: "--features bacnet-transport/ipv6,bacnet-transport/sc-tls"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: java-${{ matrix.target }}
- name: Install Linux aarch64 dependencies
if: matrix.target == 'aarch64-unknown-linux-gnu' && runner.arch != 'ARM64'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Build native library
run: cargo build -p bacnet-java --release --target ${{ matrix.target }} ${{ matrix.features }}
- name: Upload native library
uses: actions/upload-artifact@v4
with:
name: java-native-${{ matrix.jna_dir }}
path: target/${{ matrix.target }}/release/${{ matrix.lib_name }}
publish-java:
name: Publish Java/Kotlin JAR
if: startsWith(github.ref, 'refs/tags/v')
needs: [build-java-native]
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- name: Download all native libraries
uses: actions/download-artifact@v4
with:
pattern: java-native-*
path: native-libs
- name: Build Linux x86_64 cdylib for binding generation
run: cargo build -p bacnet-java --release
- name: Build uniffi-bindgen
run: cargo build -p uniffi-bindgen
- name: Generate Kotlin bindings
run: |
cargo run -p uniffi-bindgen -- generate \
--library target/release/libbacnet_java.so \
--language kotlin \
--no-format \
--out-dir java/src/main/kotlin
- name: Assemble native libraries into JNA layout
run: |
for dir in native-libs/java-native-*/; do
JNA_DIR=$(basename "$dir" | sed 's/java-native-//')
mkdir -p "java/src/main/resources/$JNA_DIR"
cp "$dir"/* "java/src/main/resources/$JNA_DIR/"
done
find java/src/main/resources -type f | sort
- name: Build JAR
working-directory: java
run: ./gradlew build
- name: Publish to GitHub Packages
working-directory: java
run: ./gradlew publish
env:
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload JAR artifact
uses: actions/upload-artifact@v4
with:
name: java-jar
path: java/build/libs/*.jar
# ===========================================================================
# Docker Hub (placeholder for 1.0)
# ===========================================================================
# TODO: Add multi-arch Docker builds for:
# - bacnet-device (BIP/SC server)
# - bacnet-router (multi-port router)
# - bacnet-bbmd (broadcast management)
# - bacnet-sc-hub (SC hub relay)
# Target: linux/amd64 + linux/arm64 via docker/build-push-action