update conditional variables

This commit is contained in:
2026-07-22 13:58:55 +02:00
parent 89673b81ce
commit 60b16feb1c
2 changed files with 141 additions and 78 deletions
+43 -16
View File
@@ -1,45 +1,72 @@
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.
Evaluates a set of rules and exposes variables as outputs.
Rules are evaluated in the order they are defined.
A rule matches when any of its conditions match the supplied context.
If multiple matching rules 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.
Context variables available during rule evaluation.
Example:
- when:
branch:
- 9.0-alpine-24
- 9.0-alpine-23
branch=9.0-alpine-24
event=push
install_something=1
required: true
rules:
description: |
Rules to evaluate.
Example:
- conditions:
- branch == 9.0-alpine-24
- branch == 9.0-alpine-23
set:
DOTNET_VERSION: 9.0
DOTNET_VERSION=9.0
DOTNET_RUNTIME_VERSION=9.0.18
- conditions:
- install_something == 1
set:
INSTALL_DEPENDENCY=true
Conditions within a rule are evaluated as OR.
required: true
fail-on-no-match:
description: |
Fail the action when no condition matches.
Fail the action if no rule matches.
required: false
default: "false"
outputs:
matched:
description: Indicates whether at least one rule matched.
value: ${{ steps.evaluate.outputs.matched }}
runs:
using: composite
steps:
- name: Evaluate conditions
- name: Evaluate rules
id: evaluate
shell: bash
env:
CONTEXT: ${{ inputs.context }}
CONDITIONS: ${{ inputs.conditions }}
RULES: ${{ inputs.rules }}
FAIL_ON_NO_MATCH: ${{ inputs.fail-on-no-match }}
run: |
"${{ github.action_path }}/evaluate.sh"
+97 -61
View File
@@ -1,3 +1,8 @@
declare -A context
#
# Remove leading/trailing whitespace
#
trim() {
local var="$*"
var="${var#"${var%%[![:space:]]*}"}"
@@ -5,48 +10,51 @@ trim() {
printf '%s' "$var"
}
declare -A context
#
# 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"
}
#
# Load context
# Evaluate a single condition
#
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
# Examples:
# branch == 9.0
# event != push
# count > 10
#
# Evaluate conditions (OR)
#
while IFS= read -r condition; do
evaluate_condition() {
condition="$(trim "${condition:-}")"
local condition="$1"
[[ -z "$condition" ]] && continue
[[ "$condition" =~ ^# ]] && continue
local variable
local operator
local expected
local actual
read -r variable operator expected <<< "$condition"
#
# Validate condition format
#
if [[ -z "${variable:-}" || -z "${operator:-}" || -z "${expected:-}" ]]; then
echo "Invalid condition: $condition"
exit 1
return 1
fi
if [[ ! -v context["$variable"] ]]; then
echo "Unknown context variable '$variable'"
exit 1
return 1
fi
actual="${context[$variable]}"
@@ -54,63 +62,78 @@ while IFS= read -r condition; do
case "$operator" in
"==")
[[ "$actual" == "$expected" ]] && matched=true
[[ "$actual" == "$expected" ]]
;;
"!=")
[[ "$actual" != "$expected" ]] && matched=true
[[ "$actual" != "$expected" ]]
;;
">"|">="|"<"|"<=")
#
# Numeric comparisons only
#
if [[ ! "$actual" =~ ^-?[0-9]+$ ]]; then
echo "Numeric operator '$operator' requires integer value. Actual: '$actual'"
exit 1
return 1
fi
if [[ ! "$expected" =~ ^-?[0-9]+$ ]]; then
echo "Numeric operator '$operator' requires integer comparison value. Expected: '$expected'"
exit 1
echo "Numeric operator '$operator' requires integer value. Expected: '$expected'"
return 1
fi
case "$operator" in
">")
(( actual > expected )) && matched=true
(( actual > expected ))
;;
">=")
(( actual >= expected )) && matched=true
(( actual >= expected ))
;;
"<")
(( actual < expected )) && matched=true
(( actual < expected ))
;;
"<=")
(( actual <= expected )) && matched=true
(( actual <= expected ))
;;
esac
;;
*)
echo "Unsupported operator: $operator"
exit 1
return 1
;;
esac
#
# OR logic:
# stop at first match
#
[[ "$matched" == true ]] && break
done <<< "$CONDITIONS"
}
#
# Set outputs
# Evaluate list of conditions
#
if [[ "$matched" == true ]]; then
# 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
@@ -119,23 +142,36 @@ if [[ "$matched" == true ]]; then
[[ -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
return 1
fi
echo "$output" >> "$GITHUB_OUTPUT"
done <<< "$VARIABLES"
}
fi
#
# Main
#
main() {
if [[ "$matched" == false && "$FAIL_ON_NO_MATCH" == "true" ]]; then
echo "No conditions matched"
exit 1
fi
load_context
echo "matched=$matched" >> "$GITHUB_OUTPUT"
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