add conditional-variables

This commit is contained in:
2026-07-22 13:32:19 +02:00
parent 48f0948cfb
commit 89673b81ce
2 changed files with 186 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
name: Conditional Variables
description: |
Evaluates a list of conditions and exposes variables as outputs.
Conditions are evaluated in order. All matching conditions are applied.
If multiple conditions set the same variable, the last matching value wins.
inputs:
context:
description: |
Context variables available during condition evaluation.
conditions:
description: |
List of conditions to evaluate.
Example:
- when:
branch:
- 9.0-alpine-24
- 9.0-alpine-23
set:
DOTNET_VERSION: 9.0
required: true
fail-on-no-match:
description: |
Fail the action when no condition matches.
required: false
default: "false"
runs:
using: composite
steps:
- name: Evaluate conditions
shell: bash
env:
CONTEXT: ${{ inputs.context }}
CONDITIONS: ${{ inputs.conditions }}
FAIL_ON_NO_MATCH: ${{ inputs.fail-on-no-match }}
run: |
"${{ github.action_path }}/evaluate.sh"
+141
View File
@@ -0,0 +1,141 @@
trim() {
local var="$*"
var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "$var"
}
declare -A context
#
# 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"
matched=false
#
# Evaluate conditions (OR)
#
while IFS= read -r condition; do
condition="$(trim "${condition:-}")"
[[ -z "$condition" ]] && continue
[[ "$condition" =~ ^# ]] && continue
read -r variable operator expected <<< "$condition"
#
# Validate condition format
#
if [[ -z "${variable:-}" || -z "${operator:-}" || -z "${expected:-}" ]]; then
echo "Invalid condition: $condition"
exit 1
fi
if [[ ! -v context["$variable"] ]]; then
echo "Unknown context variable '$variable'"
exit 1
fi
actual="${context[$variable]}"
case "$operator" in
"==")
[[ "$actual" == "$expected" ]] && matched=true
;;
"!=")
[[ "$actual" != "$expected" ]] && matched=true
;;
">"|">="|"<"|"<=")
#
# Numeric comparisons only
#
if [[ ! "$actual" =~ ^-?[0-9]+$ ]]; then
echo "Numeric operator '$operator' requires integer value. Actual: '$actual'"
exit 1
fi
if [[ ! "$expected" =~ ^-?[0-9]+$ ]]; then
echo "Numeric operator '$operator' requires integer comparison value. Expected: '$expected'"
exit 1
fi
case "$operator" in
">")
(( actual > expected )) && matched=true
;;
">=")
(( actual >= expected )) && matched=true
;;
"<")
(( actual < expected )) && matched=true
;;
"<=")
(( actual <= expected )) && matched=true
;;
esac
;;
*)
echo "Unsupported operator: $operator"
exit 1
;;
esac
#
# OR logic:
# stop at first match
#
[[ "$matched" == true ]] && break
done <<< "$CONDITIONS"
#
# Set outputs
#
if [[ "$matched" == true ]]; then
while IFS= read -r output; do
output="$(trim "${output:-}")"
[[ -z "$output" ]] && continue
[[ "$output" =~ ^# ]] && continue
#
# Validate output syntax
#
if [[ ! "$output" =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then
echo "Invalid variable definition: $output"
exit 1
fi
echo "$output" >> "$GITHUB_OUTPUT"
done <<< "$VARIABLES"
fi
if [[ "$matched" == false && "$FAIL_ON_NO_MATCH" == "true" ]]; then
echo "No conditions matched"
exit 1
fi
echo "matched=$matched" >> "$GITHUB_OUTPUT"