Skip to content

Commit 8f08c33

Browse files
committed
Add CI/CD pipelines, serve health checks, and worker CLI improvements
- Add GitHub Actions CI workflow for PR checks (fmt, clippy, test) - Add multi-platform release workflow with 9 POSIX-compliant targets - Add --force flag and pre-flight health check for serve command - Improve worker CLI with containers/runners resources - Add health tracking for pipelines via worker heartbeats - Fix various clippy warnings (explicit_counter_loop, dead_code, etc.)
1 parent d89e541 commit 8f08c33

41 files changed

Lines changed: 1424 additions & 439 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
branches: [main, master]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
12+
jobs:
13+
check:
14+
name: Check
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: dtolnay/rust-toolchain@stable
19+
- run: cargo check --all-features
20+
21+
test:
22+
name: Test
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
- uses: dtolnay/rust-toolchain@stable
27+
- run: cargo test --all-features
28+
29+
fmt:
30+
name: Format
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
- uses: dtolnay/rust-toolchain@stable
35+
with:
36+
components: rustfmt
37+
- run: cargo fmt --all -- --check
38+
39+
clippy:
40+
name: Clippy
41+
runs-on: ubuntu-latest
42+
steps:
43+
- uses: actions/checkout@v4
44+
- uses: dtolnay/rust-toolchain@stable
45+
with:
46+
components: clippy
47+
- run: cargo clippy --all-features -- -D warnings

.github/workflows/release.yml

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
tags:
9+
- 'v*'
10+
# Trigger on PR merge from version branches (v*)
11+
pull_request:
12+
types: [closed]
13+
branches:
14+
- main
15+
- master
16+
workflow_dispatch:
17+
inputs:
18+
tag:
19+
description: 'Release tag (e.g., v0.1.0)'
20+
required: false
21+
22+
env:
23+
CARGO_TERM_COLOR: always
24+
25+
jobs:
26+
build:
27+
name: Build ${{ matrix.target }}
28+
# Skip if PR was closed without merge
29+
if: github.event_name != 'pull_request' || github.event.pull_request.merged == true
30+
runs-on: ${{ matrix.os }}
31+
strategy:
32+
fail-fast: false
33+
matrix:
34+
include:
35+
# ===========================================
36+
# Linux glibc (standard distributions)
37+
# ===========================================
38+
39+
# Linux x86_64 (glibc) - most common servers
40+
- target: x86_64-unknown-linux-gnu
41+
os: ubuntu-latest
42+
artifact: llmnet-linux-x86_64-gnu
43+
44+
# Linux aarch64 (glibc) - ARM servers, DGX, Graviton
45+
- target: aarch64-unknown-linux-gnu
46+
os: ubuntu-latest
47+
artifact: llmnet-linux-aarch64-gnu
48+
cross: true
49+
50+
# ===========================================
51+
# Linux musl (static binaries, Alpine, containers)
52+
# ===========================================
53+
54+
# Linux x86_64 musl - static binary, works everywhere
55+
- target: x86_64-unknown-linux-musl
56+
os: ubuntu-latest
57+
artifact: llmnet-linux-x86_64-musl
58+
cross: true
59+
60+
# Linux aarch64 musl - static ARM binary
61+
- target: aarch64-unknown-linux-musl
62+
os: ubuntu-latest
63+
artifact: llmnet-linux-aarch64-musl
64+
cross: true
65+
66+
# ===========================================
67+
# macOS
68+
# ===========================================
69+
70+
# macOS x86_64 (Intel Macs)
71+
- target: x86_64-apple-darwin
72+
os: macos-13
73+
artifact: llmnet-darwin-x86_64
74+
75+
# macOS aarch64 (Apple Silicon M1/M2/M3)
76+
- target: aarch64-apple-darwin
77+
os: macos-latest
78+
artifact: llmnet-darwin-aarch64
79+
80+
# ===========================================
81+
# Linux ARM 32-bit (Raspberry Pi, embedded)
82+
# ===========================================
83+
84+
# ARMv7 (Raspberry Pi 2/3/4 32-bit mode)
85+
- target: armv7-unknown-linux-gnueabihf
86+
os: ubuntu-latest
87+
artifact: llmnet-linux-armv7-gnueabihf
88+
cross: true
89+
90+
# ARMv7 musl (static, for containers)
91+
- target: armv7-unknown-linux-musleabihf
92+
os: ubuntu-latest
93+
artifact: llmnet-linux-armv7-musleabihf
94+
cross: true
95+
96+
# ===========================================
97+
# BSD (servers, firewalls, NAS)
98+
# ===========================================
99+
100+
# FreeBSD x86_64
101+
- target: x86_64-unknown-freebsd
102+
os: ubuntu-latest
103+
artifact: llmnet-freebsd-x86_64
104+
cross: true
105+
106+
steps:
107+
- name: Checkout
108+
uses: actions/checkout@v4
109+
110+
- name: Install Rust toolchain
111+
uses: dtolnay/rust-toolchain@stable
112+
with:
113+
targets: ${{ matrix.target }}
114+
115+
- name: Install cross (for cross-compilation)
116+
if: matrix.cross
117+
run: cargo install cross --git https://github.com/cross-rs/cross
118+
119+
- name: Build (native)
120+
if: ${{ !matrix.cross }}
121+
run: cargo build --release --target ${{ matrix.target }}
122+
123+
- name: Build (cross)
124+
if: matrix.cross
125+
run: cross build --release --target ${{ matrix.target }}
126+
127+
- name: Package binary
128+
shell: bash
129+
run: |
130+
mkdir -p dist
131+
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
132+
cp target/${{ matrix.target }}/release/llmnet.exe dist/${{ matrix.artifact }}.exe
133+
else
134+
cp target/${{ matrix.target }}/release/llmnet dist/${{ matrix.artifact }}
135+
chmod +x dist/${{ matrix.artifact }}
136+
fi
137+
138+
- name: Upload artifact
139+
uses: actions/upload-artifact@v4
140+
with:
141+
name: ${{ matrix.artifact }}
142+
path: dist/${{ matrix.artifact }}*
143+
if-no-files-found: error
144+
145+
# Run tests on the primary platforms
146+
test:
147+
name: Test
148+
runs-on: ubuntu-latest
149+
if: github.event_name != 'pull_request' || github.event.pull_request.merged == true
150+
steps:
151+
- uses: actions/checkout@v4
152+
- uses: dtolnay/rust-toolchain@stable
153+
- run: cargo test --all-features
154+
155+
# Create release on tag push, manual trigger, or merged version PR
156+
release:
157+
name: Create Release
158+
needs: [build, test]
159+
runs-on: ubuntu-latest
160+
# Release if:
161+
# - Tag push starting with 'v'
162+
# - Manual workflow dispatch
163+
# - Merged PR from a branch starting with 'v' (version branch)
164+
if: |
165+
startsWith(github.ref, 'refs/tags/v') ||
166+
github.event_name == 'workflow_dispatch' ||
167+
(github.event_name == 'pull_request' &&
168+
github.event.pull_request.merged == true &&
169+
startsWith(github.event.pull_request.head.ref, 'v'))
170+
permissions:
171+
contents: write
172+
steps:
173+
- name: Checkout
174+
uses: actions/checkout@v4
175+
176+
- name: Download all artifacts
177+
uses: actions/download-artifact@v4
178+
with:
179+
path: artifacts
180+
181+
- name: Prepare release assets
182+
run: |
183+
mkdir -p release
184+
for dir in artifacts/*/; do
185+
for file in "$dir"*; do
186+
if [ -f "$file" ]; then
187+
cp "$file" release/
188+
fi
189+
done
190+
done
191+
ls -la release/
192+
193+
- name: Determine version
194+
id: version
195+
run: |
196+
if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.tag }}" ]]; then
197+
# Manual trigger with specified tag
198+
echo "version=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
199+
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
200+
# Tag push
201+
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
202+
elif [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.ref }}" == v* ]]; then
203+
# Merged PR from version branch (e.g., v1.0.0)
204+
echo "version=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT
205+
else
206+
# Fallback to dev version
207+
echo "version=dev-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
208+
fi
209+
210+
- name: Create Release
211+
uses: softprops/action-gh-release@v1
212+
with:
213+
tag_name: ${{ steps.version.outputs.version }}
214+
name: Release ${{ steps.version.outputs.version }}
215+
draft: false
216+
prerelease: ${{ !startsWith(github.ref, 'refs/tags/v') }}
217+
files: release/*
218+
generate_release_notes: true
219+
env:
220+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.memory.jsonl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"type":"entity","name":"llmnet","entityType":"project","observations":["LLM pipeline orchestration CLI tool written in Rust","Secrets system supports env-file, env, and vault sources (src/config/secrets.rs)","Functions system supports REST, Shell, WebSocket, gRPC types (src/config/functions.rs)","Hooks system with pre/post execution, observe/transform modes (src/runtime/hooks.rs)","Hook integration tests with thin HTTP servers (tests/hooks_integration.rs)","Rustbook documentation deployed to GitHub Pages at avarok-cybersecurity.github.io/llmnet","Book source in docs/book/ with 27 chapters covering all features","All 296+ tests passing"],"createdAt":"2025-12-30T22:35:51.760Z","version":1}
1+
{"type":"entity","name":"llmnet","entityType":"project","observations":["LLM pipeline orchestration CLI tool written in Rust","Secrets system supports env-file, env, and vault sources (src/config/secrets.rs)","Functions system supports REST, Shell, WebSocket, gRPC types (src/config/functions.rs)","Hooks system with pre/post execution, observe/transform modes (src/runtime/hooks.rs)","Hook integration tests with thin HTTP servers (tests/hooks_integration.rs)","Rustbook documentation deployed to GitHub Pages at avarok-cybersecurity.github.io/llmnet","Book source in docs/book/ with 27 chapters covering all features","All 296+ tests passing","Implemented health tracking: wait_for_ready() now fails on health check failure (src/runtime/runner.rs:320)","Added HealthAction enum (UpdateStatus, Restart, Reschedule) for configurable failure behavior (src/cluster/pipeline.rs:22-28)","Worker heartbeat now tracks running pipelines from SharedRunnerManager (src/cluster/heartbeat.rs)","Orchestrator reconciles pipeline ready_replicas from node heartbeats (src/cluster/orchestrator.rs:266-330)","Added built-in 'worker' context pointing to localhost:8080 (src/context/mod.rs:214)","WorkerClient provides list_containers, list_runners, stream_logs, status methods (src/cli/commands.rs)","GetResource enum has Containers and Runners for worker-mode resources (src/cli/mod.rs:164-170)","Context-aware routing: control plane commands rejected in worker mode with helpful error message (src/main.rs:263-276)","serve command now checks if server already running: healthy→exit 1, unhealthy→exit 0 (src/main.rs:91-126)","Added --force flag to serve command for restart scenarios (src/cli/mod.rs:110-112)","Added ServerStatus enum and check_server_status() function (src/cli/commands.rs:570-615)","GitHub Actions CI workflow added for PR checks: check, test, fmt, clippy (.github/workflows/ci.yml)","GitHub Actions Release workflow builds 4 targets in parallel: linux-x86_64, linux-aarch64, darwin-x86_64, darwin-aarch64 (.github/workflows/release.yml)","Release pipeline triggers on: tag push (v*), workflow_dispatch, or merged PR from v* branch","DGX runs on aarch64-unknown-linux-gnu (ARM64), worker running on port 8082"],"createdAt":"2025-12-30T22:35:51.760Z","version":1}

0 commit comments

Comments
 (0)