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
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ linker = "aarch64-linux-gnu-gcc"

[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"
rustflags = ["-C", "target-feature=+crt-static", "-C", "link-arg=-s"]

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
Expand All @@ -20,6 +21,7 @@ linker = "arm-linux-musleabihf-gcc"

[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"
rustflags = ["-C", "target-feature=+crt-static", "-C", "link-arg=-s"]

[target.powerpc64le-unknown-linux-gnu]
linker = "powerpc64le-linux-gnu-gcc"
Expand All @@ -43,6 +45,8 @@ linker = "riscv64-linux-gnu-gcc"

# Build configuration
[build]
# Use a shared target directory for all workspace members
target-dir = "target"
# Default target intentionally left as host; set --target explicitly (use `cross` for Linux)

# Cross-compilation settings (commented out - let cross-rs handle Docker images)
Expand Down
42 changes: 28 additions & 14 deletions .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ on:
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10
REGISTRY: ghcr.io
IMAGE_NAME: terraphim/terraphim-ai
# sccache configuration for distributed caching
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"
# Use CI-optimized profiles
CARGO_PROFILE_DEV_DEBUG: 0
CARGO_PROFILE_TEST_DEBUG: 0

jobs:
# Build setup and metadata
Expand Down Expand Up @@ -103,6 +108,9 @@ jobs:
components: rustfmt, clippy
targets: ${{ matrix.target }}

- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.3

- name: Cache Cargo registry and dependencies (self-hosted)
uses: actions/cache@v4
with:
Expand All @@ -129,33 +137,39 @@ jobs:

- name: Build release binaries
run: |
# Build workspace with default features (no rocksdb for faster CI)
cargo build --release --target ${{ matrix.target }} --workspace
# Start sccache server
sccache --start-server || true

# Build workspace with default features using CI-optimized profile
cargo build --profile ci-release --target ${{ matrix.target }} --workspace

# Verify key binaries exist
ls -la target/${{ matrix.target }}/release/terraphim*
ls -la target/${{ matrix.target }}/ci-release/terraphim*

# Show binary sizes
for binary in target/${{ matrix.target }}/release/terraphim*; do
for binary in target/${{ matrix.target }}/ci-release/terraphim*; do
if [[ -f "$binary" ]]; then
echo "$(basename "$binary"): $(du -h "$binary" | cut -f1)"
fi
done

# Show sccache stats
sccache -s || true

- name: Run tests
run: |
# Run unit and integration tests (exclude integration-signing which requires zipsign CLI)
cargo test --release --target ${{ matrix.target }} --workspace --features "self_update/signatures"
# Run unit and integration tests with CI profile
cargo test --profile ci --target ${{ matrix.target }} --workspace --features "self_update/signatures"

- name: Upload binary artifacts
uses: actions/upload-artifact@v4
with:
name: rust-binaries-${{ matrix.target }}
path: |
target/${{ matrix.target }}/release/terraphim_server
target/${{ matrix.target }}/release/terraphim_mcp_server
target/${{ matrix.target }}/release/terraphim-agent
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '90' || '30' }}
target/${{ matrix.target }}/ci-release/terraphim_server
target/${{ matrix.target }}/ci-release/terraphim_mcp_server
target/${{ matrix.target }}/ci-release/terraphim-agent
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '30' || '7' }}

- name: Create .deb package
if: matrix.target == 'x86_64-unknown-linux-gnu'
Expand All @@ -177,7 +191,7 @@ jobs:
with:
name: deb-packages
path: target/${{ matrix.target }}/debian/*.deb
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '90' || '30' }}
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '30' || '7' }}

# Frontend build
frontend-build:
Expand Down Expand Up @@ -224,7 +238,7 @@ jobs:
with:
name: frontend-dist
path: desktop/dist/
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '90' || '30' }}
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '30' || '7' }}

# WASM build
wasm-build:
Expand Down Expand Up @@ -264,7 +278,7 @@ jobs:
with:
name: wasm-package
path: crates/terraphim_automata/wasm-test/pkg/
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '90' || '30' }}
retention-days: ${{ needs.setup.outputs.is-release == 'true' && '30' || '7' }}

# Docker image build
docker-build:
Expand Down
75 changes: 75 additions & 0 deletions .github/workflows/cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Nightly Cleanup
on:
schedule:
- cron: '0 2 * * *' # 2 AM daily
workflow_dispatch:

env:
CARGO_TERM_COLOR: always

jobs:
cleanup:
name: Cleanup Build Artifacts
runs-on: [self-hosted, Linux, X64]
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Run target cleanup script
run: |
chmod +x scripts/cleanup-target.sh
./scripts/cleanup-target.sh --retention 3

- name: Cleanup old GitHub Actions artifacts
run: |
# Keep only artifacts from last 10 workflow runs
gh run list --limit 50 --json databaseId,createdAt | \
jq -r '.[10:].databaseId' | \
xargs -I {} gh run delete {} || true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Cleanup cargo cache
run: |
if command -v cargo-cache &> /dev/null; then
echo "Running cargo cache autoclean..."
cargo cache --autoclean
else
echo "cargo-cache not installed, skipping..."
fi

# Clean up old cargo registry cache manually
if [[ -d ~/.cargo/registry/cache ]]; then
echo "Cleaning old cargo registry cache..."
find ~/.cargo/registry/cache -type f -mtime +7 -delete || true
fi

- name: Report disk usage
run: |
echo "## Disk Usage Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Current Disk Usage" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
df -h >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [[ -d target ]]; then
echo "### Target Directory Size" >> $GITHUB_STEP_SUMMARY
echo "$(du -sh target 2>/dev/null | cut -f1)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi

if [[ -d ~/.cargo/registry ]]; then
echo "### Cargo Registry Size" >> $GITHUB_STEP_SUMMARY
echo "$(du -sh ~/.cargo/registry 2>/dev/null | cut -f1)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi

if [[ -d /opt/cargo-cache ]]; then
echo "### Self-Hosted Cache Size" >> $GITHUB_STEP_SUMMARY
echo "$(du -sh /opt/cargo-cache 2>/dev/null | cut -f1)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ keys/

# Claude Code working files
.claude/plans/

# Build output logs (should not be committed)
cargo_test_output.log
*.log
40 changes: 39 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,53 @@ log = "0.4"
genai = { git = "https://github.com/terraphim/rust-genai.git", branch = "merge-upstream-20251103" }
self_update = { git = "https://github.com/AlexMikhalev/self_update.git", branch = "update-zipsign-api-v0.2" }

# Optimized profiles for disk usage and build performance

[profile.dev]
# Enable incremental with optimized settings
incremental = true
codegen-units = 256
# Split debug info to reduce object file sizes
split-debuginfo = "unpacked"

[profile.test]
incremental = true
codegen-units = 256
split-debuginfo = "unpacked"

[profile.release]
panic = "unwind"
lto = false
lto = "thin"
codegen-units = 1
opt-level = 3
strip = "debuginfo"

[profile.release-lto]
inherits = "release"
lto = true
codegen-units = 1
opt-level = 3
strip = true
panic = "abort"

[profile.size-optimized]
inherits = "release"
opt-level = "z"
lto = true
codegen-units = 1
strip = true
panic = "abort"

# CI-optimized profiles for faster builds with less disk usage
[profile.ci]
inherits = "dev"
incremental = false
codegen-units = 16
split-debuginfo = "off"
debug = false

[profile.ci-release]
inherits = "release"
lto = "thin"
codegen-units = 8
strip = "debuginfo"
20 changes: 18 additions & 2 deletions crates/terraphim_automata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,24 @@ pub async fn load_thesaurus(automata_path: &AutomataPath) -> Result<Thesaurus> {
}

let contents = match automata_path {
AutomataPath::Local(path) => fs::read_to_string(path)?,
AutomataPath::Remote(url) => read_url(url.clone()).await?,
AutomataPath::Local(path) => {
// Read file directly and handle errors atomically (avoid TOCTOU race)
fs::read_to_string(path).map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
TerraphimAutomataError::InvalidThesaurus(format!(
"Thesaurus file not found: {}",
path.display()
))
} else {
TerraphimAutomataError::Io(e)
}
})?
}
AutomataPath::Remote(_) => {
return Err(TerraphimAutomataError::InvalidThesaurus(
"Remote loading is not supported. Enable the 'remote-loading' feature.".to_string(),
));
}
};

let thesaurus = serde_json::from_str(&contents)?;
Expand Down
67 changes: 55 additions & 12 deletions crates/terraphim_service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,25 @@ impl TerraphimService {
Ok(thesaurus)
}
Err(e) => {
log::error!(
"Failed to build thesaurus from local KG for role {}: {:?}",
role_name,
e
);
// Check if error is "file not found" (expected for optional files)
// and downgrade log level from ERROR to DEBUG
let is_file_not_found =
e.to_string().contains("file not found")
|| e.to_string().contains("not found:");

if is_file_not_found {
log::debug!(
"Failed to build thesaurus from local KG (optional file not found) for role {}: {:?}",
role_name,
e
);
} else {
log::error!(
"Failed to build thesaurus from local KG for role {}: {:?}",
role_name,
e
);
}
Err(ServiceError::Config(
"Failed to load or build thesaurus".into(),
))
Expand Down Expand Up @@ -345,11 +359,19 @@ impl TerraphimService {
Ok(thesaurus)
}
Err(e) => {
log::error!(
"Failed to build thesaurus from local KG for role {}: {:?}",
role_name,
e
);
// Check if error is "file not found" (expected for optional files)
// and downgrade log level from ERROR to DEBUG
let is_file_not_found = e.to_string().contains("file not found");

if is_file_not_found {
log::debug!("Failed to build thesaurus from local KG (optional file not found) for role {}: {:?}", role_name, e);
} else {
log::error!(
"Failed to build thesaurus from local KG for role {}: {:?}",
role_name,
e
);
}
Err(ServiceError::Config(
"Failed to build thesaurus from local KG".into(),
))
Expand Down Expand Up @@ -417,7 +439,19 @@ impl TerraphimService {
rolegraphs.insert(role_name.clone(), rolegraph_value);
}
Err(e) => {
log::error!("Failed to update role and thesaurus: {:?}", e)
// Check if error is "file not found" (expected for optional files)
// and downgrade log level from ERROR to DEBUG
let is_file_not_found =
e.to_string().contains("file not found");

if is_file_not_found {
log::debug!("Failed to update role and thesaurus (optional file not found): {:?}", e);
} else {
log::error!(
"Failed to update role and thesaurus: {:?}",
e
);
}
}
}

Expand Down Expand Up @@ -459,7 +493,16 @@ impl TerraphimService {
Ok(thesaurus)
}
Err(e) => {
log::error!("Failed to load thesaurus: {:?}", e);
// Check if error is "file not found" (expected for optional files)
// and downgrade log level from ERROR to DEBUG
let is_file_not_found = e.to_string().contains("file not found")
|| e.to_string().contains("not found:");

if is_file_not_found {
log::debug!("Thesaurus file not found (optional): {:?}", e);
} else {
log::error!("Failed to load thesaurus: {:?}", e);
}
// Try to build thesaurus from KG and update the config_state directly
let mut rolegraphs = self.config_state.roles.clone();
let result = load_thesaurus_from_automata_path(
Expand Down
Loading
Loading