Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: CI

on:
push:
branches:
- main
- 'feat/**'
- 'fix/**'
- 'chore/**'
paths:
- '.github/workflows/ci.yml'
- 'rust/**'
- 'agents/**'
- 'tools/**'
- 'scripts/**'
pull_request:
branches:
- main
paths:
- '.github/workflows/ci.yml'
- 'rust/**'
- 'agents/**'
- 'tools/**'
- 'scripts/**'
workflow_dispatch:

concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1

defaults:
run:
working-directory: rust

# ── Job: validate agents ─────────────────────────────────────────────────────
jobs:
validate-agents:
name: Validate agent files
runs-on: ubuntu-latest
defaults:
run:
working-directory: .
steps:
- uses: actions/checkout@v4

- name: Check agent MD files
run: bash scripts/validate-agents.sh --strict

# ── Job: rustfmt ─────────────────────────────────────────────────────────────
fmt:
name: cargo fmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- uses: Swatinem/rust-cache@v2
with:
workspaces: rust -> target

- name: Check formatting
run: cargo fmt --all --check

# ── Job: clippy ──────────────────────────────────────────────────────────────
clippy:
name: cargo clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
components: clippy

- uses: Swatinem/rust-cache@v2
with:
workspaces: rust -> target

- name: Run clippy
run: cargo clippy --workspace -- -D warnings

# ── Job: test ────────────────────────────────────────────────────────────────
test:
name: cargo test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2
with:
workspaces: rust -> target

- name: Run workspace tests
run: cargo test --workspace

# ── Job: Windows smoke build ─────────────────────────────────────────────────
windows-smoke:
name: Windows build smoke
runs-on: windows-latest
defaults:
run:
working-directory: rust
shell: pwsh
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2
with:
workspaces: rust -> target

- name: Build (debug)
run: cargo build --workspace

- name: Smoke test binary
run: |
$bin = "target\debug\claude-tools.exe"
if (Test-Path $bin) {
& $bin --version
Write-Host "claude-tools binary OK"
} else {
Write-Host "No claude-tools binary found (workspace may not include binary crate yet)"
}

# ── Job: dogfood build ───────────────────────────────────────────────────────
dogfood:
name: Dogfood build (Linux)
runs-on: ubuntu-latest
needs: [fmt, clippy, test]
defaults:
run:
working-directory: .
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2
with:
workspaces: rust -> target

- name: Build via dogfood script
run: |
bash scripts/dogfood-build.sh

- name: Validate agents with built binary
run: bash scripts/validate-agents.sh
26 changes: 26 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM rust:bookworm

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
git \
libssl-dev \
pkg-config \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*

ENV CARGO_TERM_COLOR=always
WORKDIR /workspace

# Pre-fetch dependencies so layer is cached
COPY rust/Cargo.toml rust/Cargo.lock ./rust/
RUN cd rust && cargo fetch --locked 2>/dev/null || true

# Copy full source
COPY . .

RUN cd rust && cargo build --workspace --release \
&& cp target/release/claude-tools /usr/local/bin/claude-tools

CMD ["bash"]
25 changes: 18 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,21 +106,32 @@ test-agents: ## Verify agent files exist and are non-empty
echo "Agents: $$ok OK, $$fail empty"

# ─── lint / format ─────────────────────────────────────────────────────────
.PHONY: lint fmt
.PHONY: lint fmt fmt-check
lint: ## Clippy lint (Rust)
cd $(RUST_DIR) && $(CARGO) clippy -- -D warnings

fmt: ## rustfmt + check Python style
cd $(RUST_DIR) && $(CARGO) fmt
@command -v ruff >/dev/null 2>&1 \
&& ruff format $(TOOLS_DIR)/ \
|| echo "ruff not found, skipping Python format"
fmt: ## Format all code (Rust + Python)
bash scripts/fmt.sh

fmt-check: ## Check formatting without modifying (CI mode)
bash scripts/fmt.sh --check

# ─── dev helpers ───────────────────────────────────────────────────────────
.PHONY: watch-cost env status
.PHONY: watch-cost env status dogfood container validate
watch-cost: ## Live cost monitor (requires claude-tools build)
@$(RUST_DIR)/target/release/claude-tools watch --interval 2

dogfood: ## Build from source with provenance check (like claw-code)
@bash scripts/dogfood-build.sh

container: ## Build Containerfile (requires Docker / Podman)
@command -v docker >/dev/null 2>&1 && docker build -f Containerfile -t claude-agents:dev . \
|| command -v podman >/dev/null 2>&1 && podman build -f Containerfile -t claude-agents:dev . \
|| { echo "docker or podman required"; exit 1; }

validate: ## Validate agent MD files
@bash scripts/validate-agents.sh

env: ## Show Claude environment status
@$(RUST_DIR)/target/release/claude-tools env

Expand Down
Loading
Loading