Skip to content

A worker in shell

Terminal window
oren init worker my-task --template shell

Generates the contract, the implementation, the Dockerfile and the worker. oren run dev works straight after, with no Docker command at all.

The template includes worker/oren.sh:

Terminal window
oren_input() { jq -r "$1" "$OREN_INPUT_PATH"; }
oren_output() { cat > "$OREN_OUTPUT_PATH"; }
oren_log() { echo "$@" >&2; }
oren_fail() { echo "$@" >&2; exit 1; }
oren_path() { jq -r ".dependencies.\"$1\".path" "$OREN_CONTEXT_PATH"; }

Ten lines. For shell, the unit of distribution of an SDK is the image, not a package manager — and that generalises to any language, including those with no convenient registry.

#!/bin/sh
set -eu
. /worker/oren.sh
message=$(oren_input '.message')
source_dir=$(oren_path 'source')
oren_log "processing $source_dir"
files=$(find "$source_dir" -type f | wc -l | tr -d ' ')
jq -n --arg r "$message" --argjson a "$files" \
'{result: $r, files: $a}' | oren_output

This pattern breaks with any value containing a space:

Terminal window
# WRONG
for pair in $(jq -r '.vars | to_entries[] | "\(.key)=\(.value)"' "$INPUT"); do
args="$args -var=$pair"
done

content: "created by oren" becomes three separate arguments. for ... in $(...) does word splitting.

Use positional arguments, which preserve spaces:

Terminal window
set --
while IFS= read -r pair; do
[ -n "$pair" ] && set -- "$@" "-var=$pair"
done <<END
$(jq -r '.vars | to_entries[] | "\(.key)=\(.value)"' "$INPUT")
END
terraform plan "$@"

This bug existed in three official workers before anyone noticed — worth checking when writing any worker in shell.