documenting action spec
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# Build Pack Environments Action
|
||||
# Creates runtime environments and installs dependencies for packs
|
||||
|
||||
name: build_pack_envs
|
||||
ref: core.build_pack_envs
|
||||
label: "Build Pack Environments"
|
||||
description: "Build runtime environments for packs and install declared dependencies (Python requirements.txt, Node.js package.json)"
|
||||
enabled: true
|
||||
runner_type: shell
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Download Packs Action
|
||||
# Downloads packs from various sources (git repositories, HTTP archives, or pack registry)
|
||||
|
||||
name: download_packs
|
||||
ref: core.download_packs
|
||||
label: "Download Packs"
|
||||
description: "Download packs from git repositories, HTTP archives, or pack registry to a temporary directory"
|
||||
enabled: true
|
||||
runner_type: shell
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Echo Action
|
||||
# Outputs a message to stdout
|
||||
|
||||
name: echo
|
||||
ref: core.echo
|
||||
label: "Echo"
|
||||
description: "Echo a message to stdout"
|
||||
enabled: true
|
||||
|
||||
@@ -26,7 +26,6 @@ parameters:
|
||||
message:
|
||||
type: string
|
||||
description: "Message to echo (empty string if not provided)"
|
||||
required: []
|
||||
|
||||
# Output schema: not applicable for text output format
|
||||
# The action outputs plain text to stdout
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Get Pack Dependencies Action
|
||||
# Parses pack.yaml files to identify pack and runtime dependencies
|
||||
|
||||
name: get_pack_dependencies
|
||||
ref: core.get_pack_dependencies
|
||||
label: "Get Pack Dependencies"
|
||||
description: "Parse pack.yaml files to extract pack dependencies and runtime requirements"
|
||||
enabled: true
|
||||
runner_type: shell
|
||||
|
||||
@@ -1,209 +1,259 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# HTTP Request Action - Core Pack
|
||||
# Make HTTP requests to external APIs using curl
|
||||
#
|
||||
# This script uses pure POSIX shell without external dependencies like jq.
|
||||
# It reads parameters in DOTENV format from stdin until the delimiter.
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
# Read JSON parameters from stdin
|
||||
INPUT=$(cat)
|
||||
# Initialize variables
|
||||
url=""
|
||||
method="GET"
|
||||
body=""
|
||||
json_body=""
|
||||
timeout="30"
|
||||
verify_ssl="true"
|
||||
auth_type="none"
|
||||
auth_username=""
|
||||
auth_password=""
|
||||
auth_token=""
|
||||
follow_redirects="true"
|
||||
max_redirects="10"
|
||||
|
||||
# Parse required parameters
|
||||
URL=$(echo "$INPUT" | jq -r '.url // ""')
|
||||
# Temporary files
|
||||
headers_file=$(mktemp)
|
||||
query_params_file=$(mktemp)
|
||||
body_file=""
|
||||
temp_headers=$(mktemp)
|
||||
curl_output=$(mktemp)
|
||||
|
||||
if [ -z "$URL" ] || [ "$URL" = "null" ]; then
|
||||
echo "ERROR: 'url' parameter is required" >&2
|
||||
cleanup() {
|
||||
rm -f "$headers_file" "$query_params_file" "$temp_headers" "$curl_output"
|
||||
[ -n "$body_file" ] && [ -f "$body_file" ] && rm -f "$body_file"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Read DOTENV-formatted parameters
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
*"---ATTUNE_PARAMS_END---"*) break ;;
|
||||
esac
|
||||
[ -z "$line" ] && continue
|
||||
|
||||
key="${line%%=*}"
|
||||
value="${line#*=}"
|
||||
|
||||
# Remove quotes
|
||||
case "$value" in
|
||||
\"*\") value="${value#\"}"; value="${value%\"}" ;;
|
||||
\'*\') value="${value#\'}"; value="${value%\'}" ;;
|
||||
esac
|
||||
|
||||
# Process parameters
|
||||
case "$key" in
|
||||
url) url="$value" ;;
|
||||
method) method="$value" ;;
|
||||
body) body="$value" ;;
|
||||
json_body) json_body="$value" ;;
|
||||
timeout) timeout="$value" ;;
|
||||
verify_ssl) verify_ssl="$value" ;;
|
||||
auth_type) auth_type="$value" ;;
|
||||
auth_username) auth_username="$value" ;;
|
||||
auth_password) auth_password="$value" ;;
|
||||
auth_token) auth_token="$value" ;;
|
||||
follow_redirects) follow_redirects="$value" ;;
|
||||
max_redirects) max_redirects="$value" ;;
|
||||
headers.*)
|
||||
printf '%s: %s\n' "${key#headers.}" "$value" >> "$headers_file"
|
||||
;;
|
||||
query_params.*)
|
||||
printf '%s=%s\n' "${key#query_params.}" "$value" >> "$query_params_file"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required
|
||||
if [ -z "$url" ]; then
|
||||
printf '{"status_code":0,"headers":{},"body":"","json":null,"elapsed_ms":0,"url":"","success":false,"error":"url parameter is required"}\n'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse optional parameters
|
||||
METHOD=$(echo "$INPUT" | jq -r '.method // "GET"' | tr '[:lower:]' '[:upper:]')
|
||||
HEADERS=$(echo "$INPUT" | jq -r '.headers // {}')
|
||||
BODY=$(echo "$INPUT" | jq -r '.body // ""')
|
||||
JSON_BODY=$(echo "$INPUT" | jq -c '.json_body // null')
|
||||
QUERY_PARAMS=$(echo "$INPUT" | jq -r '.query_params // {}')
|
||||
TIMEOUT=$(echo "$INPUT" | jq -r '.timeout // 30')
|
||||
VERIFY_SSL=$(echo "$INPUT" | jq -r '.verify_ssl // true')
|
||||
AUTH_TYPE=$(echo "$INPUT" | jq -r '.auth_type // "none"')
|
||||
FOLLOW_REDIRECTS=$(echo "$INPUT" | jq -r '.follow_redirects // true')
|
||||
MAX_REDIRECTS=$(echo "$INPUT" | jq -r '.max_redirects // 10')
|
||||
# Normalize method
|
||||
method=$(printf '%s' "$method" | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Build URL with query parameters
|
||||
FINAL_URL="$URL"
|
||||
if [ "$QUERY_PARAMS" != "{}" ] && [ "$QUERY_PARAMS" != "null" ]; then
|
||||
QUERY_STRING=$(echo "$QUERY_PARAMS" | jq -r 'to_entries | map("\(.key)=\(.value | @uri)") | join("&")')
|
||||
if [[ "$FINAL_URL" == *"?"* ]]; then
|
||||
FINAL_URL="${FINAL_URL}&${QUERY_STRING}"
|
||||
else
|
||||
FINAL_URL="${FINAL_URL}?${QUERY_STRING}"
|
||||
# URL encode helper
|
||||
url_encode() {
|
||||
printf '%s' "$1" | sed 's/ /%20/g; s/!/%21/g; s/"/%22/g; s/#/%23/g; s/\$/%24/g; s/&/%26/g; s/'\''/%27/g'
|
||||
}
|
||||
|
||||
# Build URL with query params
|
||||
final_url="$url"
|
||||
if [ -s "$query_params_file" ]; then
|
||||
query_string=""
|
||||
while IFS='=' read -r param_name param_value; do
|
||||
[ -z "$param_name" ] && continue
|
||||
encoded=$(url_encode "$param_value")
|
||||
[ -z "$query_string" ] && query_string="${param_name}=${encoded}" || query_string="${query_string}&${param_name}=${encoded}"
|
||||
done < "$query_params_file"
|
||||
|
||||
if [ -n "$query_string" ]; then
|
||||
case "$final_url" in
|
||||
*\?*) final_url="${final_url}&${query_string}" ;;
|
||||
*) final_url="${final_url}?${query_string}" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build curl arguments array
|
||||
CURL_ARGS=(
|
||||
-X "$METHOD"
|
||||
-s # Silent mode
|
||||
-w "\n%{http_code}\n%{time_total}\n%{url_effective}\n" # Write out metadata
|
||||
--max-time "$TIMEOUT"
|
||||
--connect-timeout 10
|
||||
)
|
||||
|
||||
# Handle SSL verification
|
||||
if [ "$VERIFY_SSL" = "false" ]; then
|
||||
CURL_ARGS+=(-k)
|
||||
# Prepare body
|
||||
if [ -n "$json_body" ]; then
|
||||
body_file=$(mktemp)
|
||||
printf '%s' "$json_body" > "$body_file"
|
||||
elif [ -n "$body" ]; then
|
||||
body_file=$(mktemp)
|
||||
printf '%s' "$body" > "$body_file"
|
||||
fi
|
||||
|
||||
# Handle redirects
|
||||
if [ "$FOLLOW_REDIRECTS" = "true" ]; then
|
||||
CURL_ARGS+=(-L --max-redirs "$MAX_REDIRECTS")
|
||||
fi
|
||||
# Build curl args file (avoid shell escaping issues)
|
||||
curl_args=$(mktemp)
|
||||
{
|
||||
printf -- '-X\n%s\n' "$method"
|
||||
printf -- '-s\n'
|
||||
printf -- '-w\n\n%%{http_code}\n%%{url_effective}\n\n'
|
||||
printf -- '--max-time\n%s\n' "$timeout"
|
||||
printf -- '--connect-timeout\n10\n'
|
||||
printf -- '--dump-header\n%s\n' "$temp_headers"
|
||||
|
||||
[ "$verify_ssl" = "false" ] && printf -- '-k\n'
|
||||
|
||||
if [ "$follow_redirects" = "true" ]; then
|
||||
printf -- '-L\n'
|
||||
printf -- '--max-redirs\n%s\n' "$max_redirects"
|
||||
fi
|
||||
|
||||
# Add headers
|
||||
if [ "$HEADERS" != "{}" ] && [ "$HEADERS" != "null" ]; then
|
||||
while IFS= read -r header; do
|
||||
if [ -n "$header" ]; then
|
||||
CURL_ARGS+=(-H "$header")
|
||||
fi
|
||||
done < <(echo "$HEADERS" | jq -r 'to_entries | map("\(.key): \(.value)") | .[]')
|
||||
fi
|
||||
if [ -s "$headers_file" ]; then
|
||||
while IFS= read -r h; do
|
||||
[ -n "$h" ] && printf -- '-H\n%s\n' "$h"
|
||||
done < "$headers_file"
|
||||
fi
|
||||
|
||||
# Handle authentication
|
||||
case "$AUTH_TYPE" in
|
||||
basic)
|
||||
AUTH_USERNAME=$(echo "$INPUT" | jq -r '.auth_username // ""')
|
||||
AUTH_PASSWORD=$(echo "$INPUT" | jq -r '.auth_password // ""')
|
||||
if [ -n "$AUTH_USERNAME" ] && [ "$AUTH_USERNAME" != "null" ]; then
|
||||
CURL_ARGS+=(-u "${AUTH_USERNAME}:${AUTH_PASSWORD}")
|
||||
fi
|
||||
;;
|
||||
bearer)
|
||||
AUTH_TOKEN=$(echo "$INPUT" | jq -r '.auth_token // ""')
|
||||
if [ -n "$AUTH_TOKEN" ] && [ "$AUTH_TOKEN" != "null" ]; then
|
||||
CURL_ARGS+=(-H "Authorization: Bearer ${AUTH_TOKEN}")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Handle request body
|
||||
if [ "$JSON_BODY" != "null" ] && [ "$JSON_BODY" != "" ]; then
|
||||
CURL_ARGS+=(-H "Content-Type: application/json")
|
||||
CURL_ARGS+=(-d "$JSON_BODY")
|
||||
elif [ -n "$BODY" ] && [ "$BODY" != "null" ]; then
|
||||
CURL_ARGS+=(-d "$BODY")
|
||||
fi
|
||||
|
||||
# Capture start time
|
||||
START_TIME=$(date +%s%3N)
|
||||
|
||||
# Make the request and capture response headers
|
||||
TEMP_HEADERS=$(mktemp)
|
||||
CURL_ARGS+=(--dump-header "$TEMP_HEADERS")
|
||||
|
||||
# Execute curl and capture output
|
||||
set +e
|
||||
RESPONSE=$(curl "${CURL_ARGS[@]}" "$FINAL_URL" 2>&1)
|
||||
CURL_EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
# Calculate elapsed time
|
||||
END_TIME=$(date +%s%3N)
|
||||
ELAPSED_MS=$((END_TIME - START_TIME))
|
||||
|
||||
# Parse curl output (last 3 lines are: http_code, time_total, url_effective)
|
||||
BODY_OUTPUT=$(echo "$RESPONSE" | head -n -3)
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n 3 | head -n 1 | tr -d '\r\n')
|
||||
CURL_TIME=$(echo "$RESPONSE" | tail -n 2 | head -n 1 | tr -d '\r\n')
|
||||
EFFECTIVE_URL=$(echo "$RESPONSE" | tail -n 1 | tr -d '\r\n')
|
||||
|
||||
# Ensure HTTP_CODE is numeric, default to 0 if not
|
||||
if ! [[ "$HTTP_CODE" =~ ^[0-9]+$ ]]; then
|
||||
HTTP_CODE=0
|
||||
fi
|
||||
|
||||
# If curl failed, handle error
|
||||
if [ "$CURL_EXIT_CODE" -ne 0 ]; then
|
||||
ERROR_MSG="curl failed with exit code $CURL_EXIT_CODE"
|
||||
|
||||
# Determine specific error
|
||||
case $CURL_EXIT_CODE in
|
||||
6) ERROR_MSG="Could not resolve host" ;;
|
||||
7) ERROR_MSG="Failed to connect to host" ;;
|
||||
28) ERROR_MSG="Request timeout" ;;
|
||||
35) ERROR_MSG="SSL/TLS connection error" ;;
|
||||
52) ERROR_MSG="Empty reply from server" ;;
|
||||
56) ERROR_MSG="Failure receiving network data" ;;
|
||||
*) ERROR_MSG="curl error code $CURL_EXIT_CODE" ;;
|
||||
case "$auth_type" in
|
||||
basic)
|
||||
[ -n "$auth_username" ] && printf -- '-u\n%s:%s\n' "$auth_username" "$auth_password"
|
||||
;;
|
||||
bearer)
|
||||
[ -n "$auth_token" ] && printf -- '-H\nAuthorization: Bearer %s\n' "$auth_token"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Output error result as JSON
|
||||
jq -n \
|
||||
--arg error "$ERROR_MSG" \
|
||||
--argjson elapsed "$ELAPSED_MS" \
|
||||
--arg url "$FINAL_URL" \
|
||||
'{
|
||||
status_code: 0,
|
||||
headers: {},
|
||||
body: "",
|
||||
json: null,
|
||||
elapsed_ms: $elapsed,
|
||||
url: $url,
|
||||
success: false,
|
||||
error: $error
|
||||
}'
|
||||
if [ -n "$body_file" ] && [ -f "$body_file" ]; then
|
||||
[ -n "$json_body" ] && printf -- '-H\nContent-Type: application/json\n'
|
||||
printf -- '-d\n@%s\n' "$body_file"
|
||||
fi
|
||||
|
||||
rm -f "$TEMP_HEADERS"
|
||||
printf -- '%s\n' "$final_url"
|
||||
} > "$curl_args"
|
||||
|
||||
# Execute curl
|
||||
start_time=$(date +%s%3N 2>/dev/null || echo $(($(date +%s) * 1000)))
|
||||
|
||||
set +e
|
||||
xargs -a "$curl_args" curl > "$curl_output" 2>&1
|
||||
curl_exit_code=$?
|
||||
set -e
|
||||
|
||||
rm -f "$curl_args"
|
||||
|
||||
end_time=$(date +%s%3N 2>/dev/null || echo $(($(date +%s) * 1000)))
|
||||
elapsed_ms=$((end_time - start_time))
|
||||
|
||||
# Parse output
|
||||
response=$(cat "$curl_output")
|
||||
total_lines=$(printf '%s\n' "$response" | wc -l)
|
||||
body_lines=$((total_lines - 2))
|
||||
|
||||
if [ "$body_lines" -gt 0 ]; then
|
||||
body_output=$(printf '%s\n' "$response" | head -n "$body_lines")
|
||||
else
|
||||
body_output=""
|
||||
fi
|
||||
|
||||
http_code=$(printf '%s\n' "$response" | tail -n 2 | head -n 1 | tr -d '\r\n ')
|
||||
effective_url=$(printf '%s\n' "$response" | tail -n 1 | tr -d '\r\n')
|
||||
|
||||
case "$http_code" in
|
||||
''|*[!0-9]*) http_code=0 ;;
|
||||
esac
|
||||
|
||||
# Handle errors
|
||||
if [ "$curl_exit_code" -ne 0 ]; then
|
||||
error_msg="curl error code $curl_exit_code"
|
||||
case $curl_exit_code in
|
||||
6) error_msg="Could not resolve host" ;;
|
||||
7) error_msg="Failed to connect to host" ;;
|
||||
28) error_msg="Request timeout" ;;
|
||||
35) error_msg="SSL/TLS connection error" ;;
|
||||
52) error_msg="Empty reply from server" ;;
|
||||
56) error_msg="Failure receiving network data" ;;
|
||||
esac
|
||||
error_msg=$(printf '%s' "$error_msg" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
||||
printf '{"status_code":0,"headers":{},"body":"","json":null,"elapsed_ms":%d,"url":"%s","success":false,"error":"%s"}\n' \
|
||||
"$elapsed_ms" "$final_url" "$error_msg"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse response headers into JSON
|
||||
HEADERS_JSON="{}"
|
||||
if [ -f "$TEMP_HEADERS" ]; then
|
||||
# Skip the status line and parse headers
|
||||
HEADERS_JSON=$(grep -v "^HTTP/" "$TEMP_HEADERS" | grep ":" | sed 's/\r$//' | jq -R -s -c '
|
||||
split("\n") |
|
||||
map(select(length > 0)) |
|
||||
map(split(": "; "") | select(length > 1) | {key: .[0], value: (.[1:] | join(": "))}) |
|
||||
map({(.key): .value}) |
|
||||
add // {}
|
||||
' || echo '{}')
|
||||
rm -f "$TEMP_HEADERS"
|
||||
# Parse headers
|
||||
headers_json="{"
|
||||
first_header=true
|
||||
if [ -f "$temp_headers" ]; then
|
||||
while IFS= read -r line; do
|
||||
case "$line" in HTTP/*|'') continue ;; esac
|
||||
|
||||
header_name="${line%%:*}"
|
||||
header_value="${line#*:}"
|
||||
[ "$header_name" = "$line" ] && continue
|
||||
|
||||
header_value=$(printf '%s' "$header_value" | sed 's/^ *//; s/ *$//; s/\r$//; s/\\/\\\\/g; s/"/\\"/g')
|
||||
header_name=$(printf '%s' "$header_name" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
||||
|
||||
if [ "$first_header" = true ]; then
|
||||
headers_json="${headers_json}\"${header_name}\":\"${header_value}\""
|
||||
first_header=false
|
||||
else
|
||||
headers_json="${headers_json},\"${header_name}\":\"${header_value}\""
|
||||
fi
|
||||
done < "$temp_headers"
|
||||
fi
|
||||
headers_json="${headers_json}}"
|
||||
|
||||
# Success check
|
||||
success="false"
|
||||
[ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ] && success="true"
|
||||
|
||||
# Escape body
|
||||
body_escaped=$(printf '%s' "$body_output" | sed 's/\\/\\\\/g; s/"/\\"/g; s/ /\\t/g' | awk '{printf "%s\\n", $0}' | sed 's/\\n$//')
|
||||
|
||||
# Detect JSON
|
||||
json_parsed="null"
|
||||
if [ -n "$body_output" ]; then
|
||||
first_char=$(printf '%s' "$body_output" | sed 's/^[[:space:]]*//' | head -c 1)
|
||||
last_char=$(printf '%s' "$body_output" | sed 's/[[:space:]]*$//' | tail -c 1)
|
||||
case "$first_char" in
|
||||
'{'|'[')
|
||||
case "$last_char" in
|
||||
'}'|']') json_parsed="$body_output" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Ensure HEADERS_JSON is valid JSON
|
||||
if ! echo "$HEADERS_JSON" | jq empty 2>/dev/null; then
|
||||
HEADERS_JSON="{}"
|
||||
# Output
|
||||
if [ "$json_parsed" = "null" ]; then
|
||||
printf '{"status_code":%d,"headers":%s,"body":"%s","json":null,"elapsed_ms":%d,"url":"%s","success":%s}\n' \
|
||||
"$http_code" "$headers_json" "$body_escaped" "$elapsed_ms" "$effective_url" "$success"
|
||||
else
|
||||
printf '{"status_code":%d,"headers":%s,"body":"%s","json":%s,"elapsed_ms":%d,"url":"%s","success":%s}\n' \
|
||||
"$http_code" "$headers_json" "$body_escaped" "$json_parsed" "$elapsed_ms" "$effective_url" "$success"
|
||||
fi
|
||||
|
||||
# Determine if successful (2xx status code)
|
||||
SUCCESS=false
|
||||
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
||||
SUCCESS=true
|
||||
fi
|
||||
|
||||
# Try to parse body as JSON
|
||||
JSON_PARSED="null"
|
||||
if [ -n "$BODY_OUTPUT" ] && echo "$BODY_OUTPUT" | jq empty 2>/dev/null; then
|
||||
JSON_PARSED=$(echo "$BODY_OUTPUT" | jq -c '.' || echo 'null')
|
||||
fi
|
||||
|
||||
# Output result as JSON
|
||||
jq -n \
|
||||
--argjson status_code "$HTTP_CODE" \
|
||||
--argjson headers "$HEADERS_JSON" \
|
||||
--arg body "$BODY_OUTPUT" \
|
||||
--argjson json "$JSON_PARSED" \
|
||||
--argjson elapsed "$ELAPSED_MS" \
|
||||
--arg url "$EFFECTIVE_URL" \
|
||||
--argjson success "$SUCCESS" \
|
||||
'{
|
||||
status_code: $status_code,
|
||||
headers: $headers,
|
||||
body: $body,
|
||||
json: $json,
|
||||
elapsed_ms: $elapsed,
|
||||
url: $url,
|
||||
success: $success
|
||||
}'
|
||||
|
||||
# Exit with success
|
||||
exit 0
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# HTTP Request Action
|
||||
# Make HTTP requests to external APIs
|
||||
|
||||
name: http_request
|
||||
ref: core.http_request
|
||||
label: "HTTP Request"
|
||||
description: "Make HTTP requests to external APIs with support for various methods, headers, and authentication"
|
||||
enabled: true
|
||||
|
||||
@@ -13,9 +13,9 @@ runner_type: shell
|
||||
entry_point: http_request.sh
|
||||
|
||||
# Parameter delivery configuration (for security)
|
||||
# Use stdin + JSON for secure parameter passing (credentials won't appear in process list)
|
||||
# Use stdin + DOTENV for secure parameter passing (credentials won't appear in process list)
|
||||
parameter_delivery: stdin
|
||||
parameter_format: json
|
||||
parameter_format: dotenv
|
||||
|
||||
# Output format: json (structured data parsing enabled)
|
||||
output_format: json
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# No Operation Action
|
||||
# Does nothing - useful for testing and placeholder workflows
|
||||
|
||||
name: noop
|
||||
ref: core.noop
|
||||
label: "No-Op"
|
||||
description: "Does nothing - useful for testing and placeholder workflows"
|
||||
enabled: true
|
||||
|
||||
@@ -32,7 +32,6 @@ parameters:
|
||||
default: 0
|
||||
minimum: 0
|
||||
maximum: 255
|
||||
required: []
|
||||
|
||||
# Output schema: not applicable for text output format
|
||||
# The action outputs plain text to stdout
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Register Packs Action
|
||||
# Validates pack structure and loads components into database
|
||||
|
||||
name: register_packs
|
||||
ref: core.register_packs
|
||||
label: "Register Packs"
|
||||
description: "Register packs by validating schemas, loading components into database, and copying to permanent storage"
|
||||
enabled: true
|
||||
runner_type: shell
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Sleep Action
|
||||
# Pauses execution for a specified duration
|
||||
|
||||
name: sleep
|
||||
ref: core.sleep
|
||||
label: "Sleep"
|
||||
description: "Sleep for a specified number of seconds"
|
||||
enabled: true
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ conf_schema:
|
||||
type: boolean
|
||||
description: "Enable debug logging for core pack actions"
|
||||
default: false
|
||||
required: []
|
||||
|
||||
# Default pack configuration
|
||||
config:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Timer Sensor
|
||||
# Monitors time and fires all timer trigger types
|
||||
|
||||
name: interval_timer_sensor
|
||||
ref: core.interval_timer_sensor
|
||||
label: "Interval Timer Sensor"
|
||||
description: "Built-in sensor that monitors time and fires timer triggers (interval, cron, and one-shot datetime)"
|
||||
enabled: true
|
||||
|
||||
@@ -28,7 +28,6 @@ parameters:
|
||||
default: 1
|
||||
minimum: 1
|
||||
maximum: 60
|
||||
required: []
|
||||
|
||||
# Poll interval (how often the sensor checks for events)
|
||||
poll_interval: 1
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Cron Timer Trigger
|
||||
# Fires based on cron schedule expressions
|
||||
|
||||
name: crontimer
|
||||
ref: core.crontimer
|
||||
label: "Cron Timer"
|
||||
description: "Fires based on a cron schedule expression (e.g., '0 0 * * * *' for every hour)"
|
||||
enabled: true
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Datetime Timer Trigger
|
||||
# Fires once at a specific date and time
|
||||
|
||||
name: datetimetimer
|
||||
ref: core.datetimetimer
|
||||
label: "DateTime Timer"
|
||||
description: "Fires once at a specific date and time"
|
||||
enabled: true
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Interval Timer Trigger
|
||||
# Fires at regular intervals based on time unit and interval
|
||||
|
||||
name: intervaltimer
|
||||
ref: core.intervaltimer
|
||||
label: "Interval Timer"
|
||||
description: "Fires at regular intervals based on specified time unit and interval"
|
||||
enabled: true
|
||||
|
||||
|
||||
106
packs/examples/README.md
Normal file
106
packs/examples/README.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Examples Pack
|
||||
|
||||
**Demonstration actions and workflows for learning Attune**
|
||||
|
||||
## Overview
|
||||
|
||||
The Examples pack provides reference implementations that demonstrate various Attune features and best practices. These examples are designed for learning and can be used as templates for building your own actions.
|
||||
|
||||
## Contents
|
||||
|
||||
### Actions
|
||||
|
||||
#### `list_example` - JSON Lines Output Demo
|
||||
|
||||
Demonstrates the JSON Lines (JSONL) output format for streaming results.
|
||||
|
||||
**Features:**
|
||||
- Streams multiple JSON objects as output
|
||||
- Each line is a separate JSON object
|
||||
- Results are collected into an array
|
||||
- Useful for processing lists or progress updates
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
attune action execute examples.list_example --param count=10
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `count` (integer): Number of items to generate (default: 5, range: 1-100)
|
||||
|
||||
**Output Format:** JSONL - Each line is parsed as JSON and collected into an array
|
||||
|
||||
**Example Output:**
|
||||
```json
|
||||
[
|
||||
{"id": 0, "value": "item-0", "timestamp": "2024-01-20T10:30:00Z"},
|
||||
{"id": 1, "value": "item-1", "timestamp": "2024-01-20T10:30:01Z"},
|
||||
{"id": 2, "value": "item-2", "timestamp": "2024-01-20T10:30:02Z"}
|
||||
]
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Learning Attune
|
||||
- Study action structure and metadata
|
||||
- Understand parameter schemas
|
||||
- Learn about different output formats
|
||||
- See working implementations
|
||||
|
||||
### Templates
|
||||
- Copy and modify examples for your own actions
|
||||
- Reference implementations for common patterns
|
||||
- Starting point for new packs
|
||||
|
||||
## Installation
|
||||
|
||||
The examples pack is not installed by default but can be easily added:
|
||||
|
||||
```bash
|
||||
# Via pack registry (if published)
|
||||
attune pack install examples
|
||||
|
||||
# Via local directory
|
||||
attune pack install --local ./packs/examples
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Adding New Examples
|
||||
|
||||
When adding new example actions:
|
||||
|
||||
1. Create action metadata in `actions/<name>.yaml`
|
||||
2. Implement the action script in `actions/<name>.sh` (or .py, .js)
|
||||
3. Use ref format: `examples.<action_name>`
|
||||
4. Add documentation to this README
|
||||
5. Include clear comments in the code
|
||||
6. Demonstrate a specific feature or pattern
|
||||
|
||||
### Guidelines
|
||||
|
||||
- **Keep it simple** - Examples should be easy to understand
|
||||
- **One concept per example** - Focus on demonstrating one feature clearly
|
||||
- **Well-commented** - Explain what the code does and why
|
||||
- **Self-contained** - Minimize external dependencies
|
||||
- **Documented** - Update this README with usage examples
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Action Development Guide](../../docs/action-development-guide.md)
|
||||
- [Pack Structure](../../docs/packs/pack-structure.md)
|
||||
- [Parameter Configuration](../../docs/action-development-guide.md#parameter-configuration)
|
||||
- [Output Formats](../../docs/action-development-guide.md#output-configuration)
|
||||
|
||||
## Contributing
|
||||
|
||||
Have an idea for a useful example? Contributions are welcome! Please ensure:
|
||||
|
||||
- Examples are educational and demonstrate best practices
|
||||
- Code is well-commented and easy to follow
|
||||
- Documentation is updated
|
||||
- Examples are tested and working
|
||||
|
||||
## License
|
||||
|
||||
This pack is part of the Attune project and follows the same license terms.
|
||||
17
packs/examples/actions/list_example.sh
Executable file
17
packs/examples/actions/list_example.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
# List Example Action
|
||||
# Demonstrates JSON Lines output format for streaming results
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Read parameters from stdin (JSON format)
|
||||
read -r params_json
|
||||
|
||||
# Extract count parameter (default to 5 if not provided)
|
||||
count=$(echo "$params_json" | jq -r '.count // 5')
|
||||
|
||||
# Generate JSON Lines output (one JSON object per line)
|
||||
for i in $(seq 1 "$count"); do
|
||||
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
echo "{\"id\": $i, \"value\": \"item_$i\", \"timestamp\": \"$timestamp\"}"
|
||||
done
|
||||
58
packs/examples/actions/list_example.yaml
Normal file
58
packs/examples/actions/list_example.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
# List Example Action
|
||||
# Demonstrates JSON Lines output format for streaming results
|
||||
|
||||
ref: examples.list_example
|
||||
label: "List Example"
|
||||
description: "Example action that outputs multiple JSON objects as JSON Lines"
|
||||
enabled: true
|
||||
|
||||
# Runner type determines how the action is executed
|
||||
runner_type: shell
|
||||
|
||||
# Entry point is the shell script to execute
|
||||
entry_point: list_example.sh
|
||||
|
||||
# Parameter delivery: stdin for secure parameter passing
|
||||
parameter_delivery: stdin
|
||||
parameter_format: json
|
||||
|
||||
# Output format: jsonl (each line is a JSON object, collected into array)
|
||||
output_format: jsonl
|
||||
|
||||
# Action parameters schema (standard JSON Schema format)
|
||||
parameters:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
description: "Number of items to generate"
|
||||
default: 5
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
|
||||
# Output schema: array of objects (required for jsonl format)
|
||||
# Each line in stdout will be parsed as JSON and collected into this array
|
||||
output_schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
description: "Item identifier"
|
||||
value:
|
||||
type: string
|
||||
description: "Item value"
|
||||
timestamp:
|
||||
type: string
|
||||
description: "ISO 8601 timestamp"
|
||||
required:
|
||||
- id
|
||||
- value
|
||||
|
||||
# Tags for categorization
|
||||
tags:
|
||||
- utility
|
||||
- example
|
||||
- jsonl
|
||||
- streaming
|
||||
54
packs/examples/pack.yaml
Normal file
54
packs/examples/pack.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
# Examples Pack
|
||||
# Demonstrates various Attune features and patterns
|
||||
|
||||
ref: examples
|
||||
label: "Examples Pack"
|
||||
description: "Example actions and workflows demonstrating Attune capabilities"
|
||||
version: "1.0.0"
|
||||
author: "Attune Team"
|
||||
email: "support@attune.io"
|
||||
|
||||
# System pack flag
|
||||
system: false
|
||||
enabled: true
|
||||
|
||||
# Configuration schema
|
||||
conf_schema:
|
||||
type: object
|
||||
properties:
|
||||
example_setting:
|
||||
type: string
|
||||
description: "Example configuration setting"
|
||||
default: "default_value"
|
||||
|
||||
# Default pack configuration
|
||||
config:
|
||||
example_setting: "default_value"
|
||||
|
||||
# Pack metadata
|
||||
meta:
|
||||
category: "examples"
|
||||
keywords:
|
||||
- "examples"
|
||||
- "demos"
|
||||
- "tutorials"
|
||||
- "learning"
|
||||
documentation_url: "https://docs.attune.io/packs/examples"
|
||||
repository_url: "https://github.com/attune/attune"
|
||||
description: |
|
||||
The Examples pack provides reference implementations and demonstrations
|
||||
of Attune features including:
|
||||
|
||||
- JSON Lines (JSONL) output format for streaming results
|
||||
- Various parameter delivery methods
|
||||
- Different output formats
|
||||
- Best practices for action development
|
||||
|
||||
# Tags for categorization
|
||||
tags:
|
||||
- examples
|
||||
- demos
|
||||
- documentation
|
||||
|
||||
# Runtime dependencies (none for examples)
|
||||
runtime_deps: []
|
||||
Reference in New Issue
Block a user