declare -A context echo "=== CONTEXT ===" printf '%s\n' "$CONTEXT" echo echo "=== RULES ===" printf '%s\n' "$RULES" # # Remove leading/trailing whitespace # trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" var="${var%"${var##*[![:space:]]}"}" printf '%s' "$var" } # # Load key=value pairs into context array # load_context() { while IFS='=' read -r key value; do key="$(trim "${key:-}")" value="$(trim "${value:-}")" [[ -z "$key" ]] && continue [[ "$key" =~ ^# ]] && continue context["$key"]="$value" done <<< "$CONTEXT" } # # Evaluate a single condition # # Examples: # branch == 9.0 # event != push # count > 10 # evaluate_condition() { local condition="$1" local variable local operator local expected local actual read -r variable operator expected <<< "$condition" if [[ -z "${variable:-}" || -z "${operator:-}" || -z "${expected:-}" ]]; then echo "Invalid condition: $condition" return 1 fi if [[ ! -v context["$variable"] ]]; then echo "Unknown context variable '$variable'" return 1 fi actual="${context[$variable]}" case "$operator" in "==") [[ "$actual" == "$expected" ]] ;; "!=") [[ "$actual" != "$expected" ]] ;; "contains") [[ "$actual" == *"$expected"* ]] ;; "startsWith") [[ "$actual" == "$expected"* ]] ;; "endsWith") [[ "$actual" == *"$expected" ]] ;; ">"|">="|"<"|"<=") if [[ ! "$actual" =~ ^-?[0-9]+$ ]]; then echo "Numeric operator '$operator' requires integer value. Actual: '$actual'" return 1 fi if [[ ! "$expected" =~ ^-?[0-9]+$ ]]; then echo "Numeric operator '$operator' requires integer value. Expected: '$expected'" return 1 fi case "$operator" in ">") (( actual > expected )) ;; ">=") (( actual >= expected )) ;; "<") (( actual < expected )) ;; "<=") (( actual <= expected )) ;; esac ;; *) echo "Unsupported operator: $operator" return 1 ;; esac } # # Evaluate list of conditions # # Conditions are OR'd together # evaluate_conditions() { local matched=false while IFS= read -r condition; do condition="$(trim "${condition:-}")" [[ -z "$condition" ]] && continue [[ "$condition" =~ ^# ]] && continue if evaluate_condition "$condition"; then matched=true break fi done <<< "$CONDITIONS" [[ "$matched" == true ]] } # # Write outputs # apply_variables() { while IFS= read -r output; do output="$(trim "${output:-}")" [[ -z "$output" ]] && continue [[ "$output" =~ ^# ]] && continue if [[ ! "$output" =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then echo "Invalid variable definition: $output" return 1 fi echo "$output" >> "$GITHUB_OUTPUT" done <<< "$VARIABLES" } # # Main # main() { load_context local matched=false if evaluate_conditions; then matched=true apply_variables fi if [[ "$matched" == false && "$FAIL_ON_NO_MATCH" == "true" ]]; then echo "No conditions matched" exit 1 fi echo "matched=$matched" >> "$GITHUB_OUTPUT" } main