# Development Packs Directory ## Overview The `packs.dev/` directory provides a development environment for creating and testing custom packs without rebuilding Docker images. Files in this directory are mounted directly into Docker containers at `/opt/attune/packs.dev`, allowing immediate access to changes. ## Quick Start ### 1. Create a New Pack ```bash ./scripts/dev-pack.sh create my-pack ``` This creates a complete pack structure: ``` packs.dev/my-pack/ ├── pack.yaml ├── actions/ │ ├── example.yaml │ └── example.sh ├── triggers/ ├── sensors/ ├── workflows/ └── README.md ``` ### 2. Validate the Pack ```bash ./scripts/dev-pack.sh validate my-pack ``` ### 3. Start Docker Environment ```bash docker compose up -d ``` The pack is automatically available at `/opt/attune/packs.dev/my-pack` in all containers. ### 4. Register the Pack Get an authentication token: ```bash # Login via web UI or CLI attune auth login test@attune.local ``` Register the pack via API: ```bash curl -X POST http://localhost:8080/api/v1/packs \ -H "Authorization: Bearer $ATTUNE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "ref": "my-pack", "label": "My Custom Pack", "description": "My custom automation pack", "version": "1.0.0", "system": false, "enabled": true }' ``` ### 5. Test the Pack Create a rule that uses your pack's actions, or execute directly: ```bash curl -X POST http://localhost:8080/api/v1/executions \ -H "Authorization: Bearer $ATTUNE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "action": "my-pack.example", "parameters": { "message": "Hello from dev pack!" } }' ``` ## Directory Structure ``` packs.dev/ ├── README.md # Usage guide ├── .gitignore # Ignore custom packs, keep examples ├── examples/ # Example packs │ ├── basic-pack/ # Minimal shell action example │ └── python-pack/ # Python action example └── my-pack/ # Your custom pack (not in git) ├── pack.yaml # Pack metadata ├── actions/ # Action definitions and scripts ├── triggers/ # Trigger definitions ├── sensors/ # Sensor definitions └── workflows/ # Workflow definitions ``` ## Volume Mounts The `packs.dev/` directory is mounted in Docker Compose: ```yaml volumes: - ./packs.dev:/opt/attune/packs.dev:rw ``` This mount is added to all relevant services: - **api** - Pack registration and metadata - **executor** - Workflow execution - **worker-*** - Action execution - **sensor** - Sensor execution ### Core vs Dev Packs | Location | Mount Type | Purpose | |----------|------------|---------| | `/opt/attune/packs` | Volume (ro) | Production core pack | | `/opt/attune/packs.dev` | Bind mount (rw) | Development packs | The core pack is read-only in containers, while dev packs are read-write for active development. ## Development Workflow ### Typical Development Cycle 1. **Create pack structure** ```bash ./scripts/dev-pack.sh create my-integration ``` 2. **Edit pack files** - Edit `packs.dev/my-integration/pack.yaml` - Add actions in `actions/` - Add workflows in `workflows/` 3. **Validate** ```bash ./scripts/dev-pack.sh validate my-integration ``` 4. **Test immediately** - Changes are live in containers! - No rebuild needed - No restart needed - Actions are available instantly 5. **Iterate** - Make changes and test again 6. **Export for production** - When ready, package the pack properly ### Live Reloading Changes to pack files are immediately visible in containers because they're bind-mounted: - **Action scripts**: Available immediately for execution - **Action/Trigger YAML**: Requires pack re-registration to update DB - **Workflows**: Use workflow sync endpoint to reload ```bash # Sync workflows after changes curl -X POST http://localhost:8080/api/v1/packs/my-pack/workflows/sync \ -H "Authorization: Bearer $ATTUNE_TOKEN" ``` ## Helper Script Reference ### Commands #### `create ` Creates a new pack structure with example files. ```bash ./scripts/dev-pack.sh create my-awesome-pack ``` Creates: - `packs.dev/my-awesome-pack/` - Basic pack.yaml - Example shell action - README with instructions #### `list` Lists all development packs. ```bash ./scripts/dev-pack.sh list ``` Output: ``` Development Packs: my-pack Label: My Pack Version: 1.0.0 integration-pack Label: Integration Pack Version: 2.1.0 Total: 2 pack(s) ``` #### `validate ` Validates pack structure and files. ```bash ./scripts/dev-pack.sh validate my-pack ``` Checks: - `pack.yaml` exists and is valid YAML - Action definitions reference existing scripts - Scripts are executable - Required directories exist #### `register ` Shows the API command to register the pack. ```bash ./scripts/dev-pack.sh register my-pack ``` Outputs the `curl` command needed to register via API. #### `clean` Removes all non-example packs (interactive confirmation). ```bash ./scripts/dev-pack.sh clean ``` **Warning**: This permanently deletes custom packs! ## Example Packs ### Basic Pack (Shell Actions) Location: `packs.dev/examples/basic-pack/` Simple shell-based action that echoes a message. **Try it:** ```bash # View the pack ls -la packs.dev/examples/basic-pack/ # Register it (after starting Docker) curl -X POST http://localhost:8080/api/v1/packs \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d @packs.dev/examples/basic-pack/pack.json ``` ### Python Pack Location: `packs.dev/examples/python-pack/` Python action with parameters and structured output. Features: - Parameter validation - JSON output - Array handling - Environment variable access ## Best Practices ### Pack Structure 1. **Use descriptive refs**: `my-company-integration`, not `pack1` 2. **Version properly**: Follow semantic versioning (1.0.0) 3. **Document actions**: Clear descriptions and parameter docs 4. **Test parameters**: Validate edge cases and defaults 5. **Handle errors**: Always return valid JSON, even on error ### Action Scripts ```bash #!/bin/bash set -e # Exit on error # Get parameters (with defaults) PARAM="${ATTUNE_ACTION_param:-default_value}" # Validate inputs if [ -z "$PARAM" ]; then echo '{"error": "param is required"}' >&2 exit 1 fi # Do work RESULT=$(do_something "$PARAM") # Return JSON echo "{\"result\": \"$RESULT\"}" ``` ### Security Considerations 1. **No secrets in code**: Use Attune's secret management 2. **Validate inputs**: Never trust action parameters directly 3. **Sandbox scripts**: Be aware workers execute with privileges 4. **Review dependencies**: Check Python/Node packages carefully ### Version Control The `.gitignore` in `packs.dev/` excludes custom packs: ```gitignore * !.gitignore !README.md !examples/ !examples/** ``` This means: - ✅ Example packs are committed - ✅ Documentation is committed - ❌ Your custom packs are NOT committed To version control a custom pack: 1. Move it to a separate repository 2. Or explicitly add it: `git add -f packs.dev/my-pack/` ## Troubleshooting ### Pack Not Found **Symptom**: "Pack not found" when executing action **Solutions**: 1. Verify pack is registered in database: ```bash curl http://localhost:8080/api/v1/packs/$PACK_REF \ -H "Authorization: Bearer $TOKEN" ``` 2. Check pack directory exists: ```bash docker exec attune-api ls -la /opt/attune/packs.dev/ ``` 3. Verify mount in docker-compose.yaml: ```bash grep -A 2 "packs.dev" docker-compose.yaml ``` ### Action Not Executing **Symptom**: Action fails with "entry point not found" **Solutions**: 1. Check script exists and is executable: ```bash ls -la packs.dev/my-pack/actions/ ``` 2. Verify entry_point in action YAML matches filename: ```bash grep entry_point packs.dev/my-pack/actions/*.yaml ``` 3. Check script has shebang and is executable: ```bash head -1 packs.dev/my-pack/actions/script.sh chmod +x packs.dev/my-pack/actions/script.sh ``` ### Permission Errors **Symptom**: "Permission denied" when accessing pack files **Solutions**: 1. Check file ownership (should be readable by UID 1000): ```bash ls -ln packs.dev/my-pack/ ``` 2. Fix permissions: ```bash chmod -R 755 packs.dev/my-pack/ ``` 3. Ensure scripts are executable: ```bash find packs.dev/my-pack/ -name "*.sh" -exec chmod +x {} \; ``` ### Changes Not Reflected **Symptom**: Code changes don't appear in execution **Solutions**: 1. For **action scripts**: Changes are immediate, but verify mount: ```bash docker exec attune-worker-shell cat /opt/attune/packs.dev/my-pack/actions/script.sh ``` 2. For **action YAML**: Re-register pack or update action in DB 3. For **workflows**: Run sync endpoint: ```bash curl -X POST http://localhost:8080/api/v1/packs/my-pack/workflows/sync \ -H "Authorization: Bearer $TOKEN" ``` ## Advanced Usage ### Multiple Environment Packs Use different pack refs for different environments: ``` packs.dev/ ├── my-pack-dev/ # Development version ├── my-pack-staging/ # Staging version └── my-pack/ # Production-ready version ``` ### Pack Dependencies Reference other packs in workflows: ```yaml # In packs.dev/my-pack/workflows/example.yaml tasks: - name: use_core_action action: core.http_request input: url: https://api.example.com - name: use_my_action action: my-pack.process input: data: "{{ use_core_action.output.body }}" ``` ### Testing Workflows Create test workflows in `packs.dev/`: ```yaml # packs.dev/my-pack/workflows/test_integration.yaml name: test_integration ref: my-pack.test_integration description: "Integration test workflow" tasks: - name: test_action action: my-pack.my_action input: test: true ``` ## Production Migration When ready to deploy a dev pack to production: 1. **Clean up**: Remove test files and documentation 2. **Version**: Tag with proper version number 3. **Test**: Run full test suite 4. **Package**: Create proper pack archive 5. **Install**: Use pack installation API 6. **Deploy**: Install on production Attune instance See [Pack Registry Documentation](../packs/pack-registry-spec.md) for production deployment. ## See Also - [Pack Structure Documentation](../packs/pack-structure.md) - [Action Development Guide](../packs/PACK_TESTING.md) - [Workflow Development](../workflows/workflow-summary.md) - [Pack Registry](../packs/pack-registry-spec.md) - [Docker Deployment](../deployment/docker-deployment.md)