11 KiB
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
./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
./scripts/dev-pack.sh validate my-pack
3. Start Docker Environment
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:
# Login via web UI or CLI
attune auth login test@attune.local
Register the pack via API:
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:
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:
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
-
Create pack structure
./scripts/dev-pack.sh create my-integration -
Edit pack files
- Edit
packs.dev/my-integration/pack.yaml - Add actions in
actions/ - Add workflows in
workflows/
- Edit
-
Validate
./scripts/dev-pack.sh validate my-integration -
Test immediately - Changes are live in containers!
- No rebuild needed
- No restart needed
- Actions are available instantly
-
Iterate - Make changes and test again
-
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
# 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 <pack-ref>
Creates a new pack structure with example files.
./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.
./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 <pack-ref>
Validates pack structure and files.
./scripts/dev-pack.sh validate my-pack
Checks:
pack.yamlexists and is valid YAML- Action definitions reference existing scripts
- Scripts are executable
- Required directories exist
register <pack-ref>
Shows the API command to register the pack.
./scripts/dev-pack.sh register my-pack
Outputs the curl command needed to register via API.
clean
Removes all non-example packs (interactive confirmation).
./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:
# 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
- Use descriptive refs:
my-company-integration, notpack1 - Version properly: Follow semantic versioning (1.0.0)
- Document actions: Clear descriptions and parameter docs
- Test parameters: Validate edge cases and defaults
- Handle errors: Always return valid JSON, even on error
Action Scripts
#!/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
- No secrets in code: Use Attune's secret management
- Validate inputs: Never trust action parameters directly
- Sandbox scripts: Be aware workers execute with privileges
- Review dependencies: Check Python/Node packages carefully
Version Control
The .gitignore in packs.dev/ excludes custom packs:
*
!.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:
- Move it to a separate repository
- Or explicitly add it:
git add -f packs.dev/my-pack/
Troubleshooting
Pack Not Found
Symptom: "Pack not found" when executing action
Solutions:
-
Verify pack is registered in database:
curl http://localhost:8080/api/v1/packs/$PACK_REF \ -H "Authorization: Bearer $TOKEN" -
Check pack directory exists:
docker exec attune-api ls -la /opt/attune/packs.dev/ -
Verify mount in docker-compose.yaml:
grep -A 2 "packs.dev" docker-compose.yaml
Action Not Executing
Symptom: Action fails with "entry point not found"
Solutions:
-
Check script exists and is executable:
ls -la packs.dev/my-pack/actions/ -
Verify entry_point in action YAML matches filename:
grep entry_point packs.dev/my-pack/actions/*.yaml -
Check script has shebang and is executable:
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:
-
Check file ownership (should be readable by UID 1000):
ls -ln packs.dev/my-pack/ -
Fix permissions:
chmod -R 755 packs.dev/my-pack/ -
Ensure scripts are executable:
find packs.dev/my-pack/ -name "*.sh" -exec chmod +x {} \;
Changes Not Reflected
Symptom: Code changes don't appear in execution
Solutions:
-
For action scripts: Changes are immediate, but verify mount:
docker exec attune-worker-shell cat /opt/attune/packs.dev/my-pack/actions/script.sh -
For action YAML: Re-register pack or update action in DB
-
For workflows: Run sync endpoint:
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:
# 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/:
# 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:
- Clean up: Remove test files and documentation
- Version: Tag with proper version number
- Test: Run full test suite
- Package: Create proper pack archive
- Install: Use pack installation API
- Deploy: Install on production Attune instance
See Pack Registry Documentation for production deployment.