Files
attune/docs/development/packs-dev-directory.md

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

  1. Create pack structure

    ./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

    ./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
# 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.yaml exists 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

  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

#!/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
!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:

    curl http://localhost:8080/api/v1/packs/$PACK_REF \
      -H "Authorization: Bearer $TOKEN"
    
  2. Check pack directory exists:

    docker exec attune-api ls -la /opt/attune/packs.dev/
    
  3. 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:

  1. Check script exists and is executable:

    ls -la packs.dev/my-pack/actions/
    
  2. Verify entry_point in action YAML matches filename:

    grep entry_point packs.dev/my-pack/actions/*.yaml
    
  3. 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:

  1. Check file ownership (should be readable by UID 1000):

    ls -ln packs.dev/my-pack/
    
  2. Fix permissions:

    chmod -R 755 packs.dev/my-pack/
    
  3. 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:

  1. For action scripts: Changes are immediate, but verify mount:

    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:

    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:

  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 for production deployment.

See Also