working on runtime executions
This commit is contained in:
74
work-summary/2026-02-13-pack-install-fixes.md
Normal file
74
work-summary/2026-02-13-pack-install-fixes.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Work Summary: Pack Installation Fixes (2026-02-13)
|
||||
|
||||
## Problem
|
||||
|
||||
The `/packs/install` web UI page was completely non-functional when attempting to install packs from git repositories. Multiple cascading issues prevented successful pack installation via the API.
|
||||
|
||||
## Issues Fixed
|
||||
|
||||
### 1. `git` binary missing from API container
|
||||
**Error:** `Failed to execute git clone: No such file or directory (os error 2)`
|
||||
|
||||
The `install_from_git` method in `PackInstaller` runs `Command::new("git")` to clone repositories, but the runtime Docker image (`debian:bookworm-slim`) did not include `git`.
|
||||
|
||||
**Fix:** Added `git` to the runtime stage's `apt-get install` in `docker/Dockerfile.optimized`.
|
||||
|
||||
### 2. Pack tests ran before pack files existed at expected location
|
||||
**Error:** `Pack directory not found: /opt/attune/packs/python_example`
|
||||
|
||||
The `execute_and_store_pack_tests` function always constructed the pack path as `packs_base_dir/pack_ref`, but during installation the pack files were still in a temp directory. The move to permanent storage happened *after* test execution.
|
||||
|
||||
**Fix:**
|
||||
- Added `execute_pack_tests_at(pack_dir, ...)` method to `TestExecutor` that accepts an explicit directory path
|
||||
- Added `pack_dir_override: Option<&std::path::Path>` parameter to `execute_and_store_pack_tests`
|
||||
- `register_pack_internal` now passes the actual pack path through to tests
|
||||
|
||||
### 3. Missing test config treated as installation failure
|
||||
**Error:** `No testing configuration found in pack.yaml for pack 'python_example'`
|
||||
|
||||
Packs without a `testing` section in `pack.yaml` could not be installed without `force=true`, because the absence of test config was returned as an error.
|
||||
|
||||
**Fix:** Changed `execute_and_store_pack_tests` return type from `Result<PackTestResult>` to `Option<Result<PackTestResult>>`. Returns `None` when no testing config exists or testing is disabled, which the caller treats as "no tests to run" (success). All `?` operators were replaced with explicit `match`/`return` to work with the `Option<Result<...>>` return type.
|
||||
|
||||
### 4. Packs volume mounted read-only on API container
|
||||
**Error:** `Read-only file system (os error 30)`
|
||||
|
||||
The `packs_data` volume was mounted as `:ro` on the API container, and files were owned by root (written by `init-packs` running as root). The API service (running as user `attune`, uid 1000) could not write.
|
||||
|
||||
**Fix:**
|
||||
- Changed volume mount from `packs_data:/opt/attune/packs:ro` to `:rw` in `docker-compose.yaml`
|
||||
- Added `chown -R 1000:1000 "$TARGET_PACKS_DIR"` to `docker/init-packs.sh` (runs after initial pack copy and again after all packs loaded)
|
||||
|
||||
### 5. Pack components not loaded into database
|
||||
**Symptom:** Pack installed successfully but actions, triggers, and sensors not visible in the UI.
|
||||
|
||||
The `register_pack_internal` function only created the `pack` table record and synced workflows. It never loaded the pack's individual components (actions, triggers, sensors) from their YAML definition files. This was previously only handled by the Python `load_core_pack.py` script during `init-packs`.
|
||||
|
||||
**Fix:** Created `PackComponentLoader` in `crates/common/src/pack_registry/loader.rs` — a Rust-native pack component loader that:
|
||||
- Reads `triggers/*.yaml` and creates trigger records via `TriggerRepository`
|
||||
- Reads `actions/*.yaml` and creates action records with full field support (parameter_delivery, parameter_format, output_format) via direct SQL
|
||||
- Reads `sensors/*.yaml` and creates sensor records via `SensorRepository`, resolving trigger and runtime references
|
||||
- Loads in dependency order: triggers → actions → sensors
|
||||
- Skips components that already exist (idempotent)
|
||||
- Resolves runtime IDs by looking up common ref patterns (e.g., `shell` → `core.action.shell`)
|
||||
|
||||
Integrated into `register_pack_internal` so both the `/packs/install` and `/packs/register` endpoints load components.
|
||||
|
||||
### 6. Pack stored with version suffix in directory name
|
||||
**Symptom:** Pack stored at `python_example-1.0.0` but workers/sensors look for `python_example`.
|
||||
|
||||
`PackStorage::install_pack` was called with `Some(&pack.version)`, creating a versioned directory name. The rest of the system expects `packs_base_dir/pack_ref` without version.
|
||||
|
||||
**Fix:** Changed to `install_pack(&installed.path, &pack.r#ref, None)` to match the system convention.
|
||||
|
||||
## Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `docker/Dockerfile.optimized` | Added `git` to runtime dependencies |
|
||||
| `docker/init-packs.sh` | Added `chown -R 1000:1000` for attune user write access |
|
||||
| `docker-compose.yaml` | Changed packs volume mount from `:ro` to `:rw` on API |
|
||||
| `crates/common/src/test_executor.rs` | Added `execute_pack_tests_at` method |
|
||||
| `crates/common/src/pack_registry/loader.rs` | **New file** — `PackComponentLoader` |
|
||||
| `crates/common/src/pack_registry/mod.rs` | Added `loader` module and re-exports |
|
||||
| `crates/api/src/routes/packs.rs` | Fixed test execution path, no-test-config handling, component loading, storage path |
|
||||
Reference in New Issue
Block a user