Skip to content

Commit 7ae9ef0

Browse files
author
Jenkins
committed
ci: add GitHub Actions CI/CD pipeline with lint, test, release, and security audit
- ci.yml: runs cargo fmt, clippy, test, build on push/PR with dependency caching - release.yml: builds & pushes Docker image to ghcr.io/epappas/llmtrace-proxy on v* tags, creates GitHub Release with auto-generated changelog - security.yml: weekly cargo audit and cargo deny checks (Mondays 08:00 UTC) - deny.toml: cargo-deny config with license allowlist and advisory checks - README.md: added CI and Security Audit status badges Loop 22: CI/CD Pipeline (GitHub Actions)
1 parent 33339df commit 7ae9ef0

5 files changed

Lines changed: 264 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# =============================================================================
2+
# CI — Lint, Format, Test on every push and PR
3+
# =============================================================================
4+
name: CI
5+
6+
on:
7+
push:
8+
branches: [main]
9+
pull_request:
10+
branches: [main]
11+
12+
env:
13+
CARGO_TERM_COLOR: always
14+
RUSTFLAGS: "-D warnings"
15+
16+
jobs:
17+
fmt:
18+
name: Format
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: dtolnay/rust-toolchain@stable
23+
with:
24+
components: rustfmt
25+
- run: cargo fmt --all --check
26+
27+
clippy:
28+
name: Clippy
29+
runs-on: ubuntu-latest
30+
needs: fmt
31+
steps:
32+
- uses: actions/checkout@v4
33+
- uses: dtolnay/rust-toolchain@stable
34+
with:
35+
components: clippy
36+
- uses: actions/cache@v4
37+
with:
38+
path: |
39+
~/.cargo/bin/
40+
~/.cargo/registry/index/
41+
~/.cargo/registry/cache/
42+
~/.cargo/git/db/
43+
target/
44+
key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('**/Cargo.lock') }}
45+
restore-keys: |
46+
${{ runner.os }}-cargo-clippy-
47+
- run: cargo clippy --workspace -- -D warnings
48+
49+
test:
50+
name: Test
51+
runs-on: ubuntu-latest
52+
needs: fmt
53+
steps:
54+
- uses: actions/checkout@v4
55+
- uses: dtolnay/rust-toolchain@stable
56+
- uses: actions/cache@v4
57+
with:
58+
path: |
59+
~/.cargo/bin/
60+
~/.cargo/registry/index/
61+
~/.cargo/registry/cache/
62+
~/.cargo/git/db/
63+
target/
64+
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
65+
restore-keys: |
66+
${{ runner.os }}-cargo-test-
67+
- run: cargo test --workspace
68+
69+
build:
70+
name: Build
71+
runs-on: ubuntu-latest
72+
needs: [clippy, test]
73+
steps:
74+
- uses: actions/checkout@v4
75+
- uses: dtolnay/rust-toolchain@stable
76+
- uses: actions/cache@v4
77+
with:
78+
path: |
79+
~/.cargo/bin/
80+
~/.cargo/registry/index/
81+
~/.cargo/registry/cache/
82+
~/.cargo/git/db/
83+
target/
84+
key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
85+
restore-keys: |
86+
${{ runner.os }}-cargo-build-
87+
- run: cargo build --workspace --release

.github/workflows/release.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# =============================================================================
2+
# Release — Build Docker image, push to GHCR, create GitHub Release on tag
3+
# =============================================================================
4+
name: Release
5+
6+
on:
7+
push:
8+
tags:
9+
- "v*"
10+
11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: epappas/llmtrace-proxy
14+
15+
permissions:
16+
contents: write
17+
packages: write
18+
19+
jobs:
20+
build-and-push:
21+
name: Build & Push Docker Image
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Extract version from tag
29+
id: meta
30+
run: |
31+
TAG="${GITHUB_REF#refs/tags/}"
32+
VERSION="${TAG#v}"
33+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
34+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
35+
# Generate changelog from last tag
36+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
37+
if [ -n "$PREV_TAG" ]; then
38+
echo "## Changes since $PREV_TAG" > changelog.md
39+
git log --pretty=format:"- %s (%h)" "$PREV_TAG"..HEAD >> changelog.md
40+
else
41+
echo "## Initial Release" > changelog.md
42+
git log --pretty=format:"- %s (%h)" >> changelog.md
43+
fi
44+
45+
- name: Log in to GHCR
46+
uses: docker/login-action@v3
47+
with:
48+
registry: ${{ env.REGISTRY }}
49+
username: ${{ github.actor }}
50+
password: ${{ secrets.GITHUB_TOKEN }}
51+
52+
- name: Set up Docker Buildx
53+
uses: docker/setup-buildx-action@v3
54+
55+
- name: Build and push Docker image
56+
uses: docker/build-push-action@v6
57+
with:
58+
context: .
59+
push: true
60+
tags: |
61+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
62+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
63+
labels: |
64+
org.opencontainers.image.source=https://github.com/${{ github.repository }}
65+
org.opencontainers.image.revision=${{ github.sha }}
66+
org.opencontainers.image.version=${{ steps.meta.outputs.version }}
67+
org.opencontainers.image.created=${{ github.event.head_commit.timestamp }}
68+
cache-from: type=gha
69+
cache-to: type=gha,mode=max
70+
71+
- name: Create GitHub Release
72+
uses: softprops/action-gh-release@v2
73+
with:
74+
tag_name: ${{ steps.meta.outputs.tag }}
75+
name: "LLMTrace ${{ steps.meta.outputs.tag }}"
76+
body_path: changelog.md
77+
draft: false
78+
prerelease: ${{ contains(steps.meta.outputs.tag, '-') }}
79+
env:
80+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/security.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# =============================================================================
2+
# Security — Weekly cargo audit and cargo deny checks
3+
# =============================================================================
4+
name: Security Audit
5+
6+
on:
7+
schedule:
8+
# Every Monday at 08:00 UTC
9+
- cron: "0 8 * * 1"
10+
# Also allow manual trigger
11+
workflow_dispatch:
12+
13+
env:
14+
CARGO_TERM_COLOR: always
15+
16+
permissions:
17+
issues: write
18+
19+
jobs:
20+
audit:
21+
name: Cargo Audit
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: dtolnay/rust-toolchain@stable
26+
- name: Install cargo-audit
27+
run: cargo install cargo-audit --locked || true
28+
- name: Run cargo audit
29+
run: cargo audit
30+
31+
deny:
32+
name: Cargo Deny
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: EmbarkStudios/cargo-deny-action@v2
37+
with:
38+
command: check
39+
arguments: --all-features

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# LLMTrace
22

3+
[![CI](https://github.com/epappas/llmtrace/actions/workflows/ci.yml/badge.svg)](https://github.com/epappas/llmtrace/actions/workflows/ci.yml)
4+
[![Security Audit](https://github.com/epappas/llmtrace/actions/workflows/security.yml/badge.svg)](https://github.com/epappas/llmtrace/actions/workflows/security.yml)
5+
36
**Security-aware observability for LLM applications.**
47

58
LLMTrace is a transparent proxy that sits between your application and any OpenAI-compatible LLM API. It captures every interaction as structured traces, runs real-time security analysis (prompt injection detection, PII scanning), and stores everything in SQLite for inspection — with zero code changes to your application.

deny.toml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# =============================================================================
2+
# cargo-deny configuration — https://embarkstudios.github.io/cargo-deny/
3+
# =============================================================================
4+
5+
[graph]
6+
targets = []
7+
all-features = true
8+
9+
# =============================================================================
10+
# Advisories — check for known vulnerabilities
11+
# =============================================================================
12+
[advisories]
13+
vulnerability = "deny"
14+
unmaintained = "warn"
15+
yanked = "warn"
16+
notice = "warn"
17+
18+
# =============================================================================
19+
# Licenses — allowlist of acceptable licenses
20+
# =============================================================================
21+
[licenses]
22+
allow = [
23+
"MIT",
24+
"Apache-2.0",
25+
"Apache-2.0 WITH LLVM-exception",
26+
"BSD-2-Clause",
27+
"BSD-3-Clause",
28+
"ISC",
29+
"Unicode-3.0",
30+
"Unicode-DFS-2016",
31+
"Zlib",
32+
"BSL-1.0",
33+
"OpenSSL",
34+
"MPL-2.0",
35+
]
36+
confidence-threshold = 0.8
37+
38+
[licenses.private]
39+
ignore = false
40+
41+
# =============================================================================
42+
# Bans — deny specific problematic crates
43+
# =============================================================================
44+
[bans]
45+
multiple-versions = "warn"
46+
wildcards = "allow"
47+
48+
# =============================================================================
49+
# Sources — only allow crates from crates.io
50+
# =============================================================================
51+
[sources]
52+
unknown-registry = "deny"
53+
unknown-git = "deny"
54+
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
55+
allow-git = []

0 commit comments

Comments
 (0)