Start
This commit is contained in:
1 parent
fdbd3b0fcb
commit
7494563885
2 files changed
+132
No files matched your search
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# fsm.sh — лёгкий конечный автомат для GitHub Actions (composite)
|
||||
set -euo pipefail
|
||||
|
||||
DEBUG="${INPUT_DEBUG:-false}"
|
||||
[[ "$DEBUG" == "true" ]] && set -x
|
||||
|
||||
log() { echo "::notice::$1"; }
|
||||
debug() { [[ "$DEBUG" == "true" ]] && echo "::debug::$1"; }
|
||||
error() { echo "::error::$1"; exit 1; }
|
||||
|
||||
# Установка jq, если его нет (работает на всех официальных runner-ах)
|
||||
if ! command -v jq &>/dev/null; then
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk add --no-cache jq
|
||||
elif [[ -f /etc/debian_version ]]; then
|
||||
sudo apt-get update && sudo apt-get install -y jq
|
||||
elif [[ "$RUNNER_OS" == "macOS" ]]; then
|
||||
brew install jq
|
||||
elif [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||
choco install jq -y
|
||||
else
|
||||
error "Не удалось установить jq на $RUNNER_OS"
|
||||
fi
|
||||
fi
|
||||
|
||||
STATES_JSON="$INPUT_STATES"
|
||||
CURRENT="$INPUT_INITIAL"
|
||||
EVENT="$INPUT_EVENT"
|
||||
CONTEXT_JSON="${INPUT_CONTEXT:-{}}"
|
||||
|
||||
debug "States: $STATES_JSON"
|
||||
debug "From: $CURRENT → Event: $EVENT"
|
||||
debug "Context: $CONTEXT_JSON"
|
||||
|
||||
# Ищем подходящий переход (поддержка wildcard события *)
|
||||
TRANSITION=$(echo "$STATES_JSON" | jq -r --arg from "$CURRENT" --arg event "$EVENT" '
|
||||
.transitions // [] |
|
||||
.[] |
|
||||
select(.from == $from and (.event == $event or .event == "*")) |
|
||||
{
|
||||
to: .to,
|
||||
action: (.action // "")
|
||||
} | @json
|
||||
' | head -n1)
|
||||
|
||||
[[ -z "$TRANSITION" || "$TRANSITION" == "null" ]] && \
|
||||
error "Нет перехода из состояния '$CURRENT' по событию '$EVENT'"
|
||||
|
||||
NEXT_STATE=$(echo "$TRANSITION" | jq -r '.to')
|
||||
ACTION=$(echo "$TRANSITION" | jq -r '.action')
|
||||
|
||||
log "Переход: $CURRENT --[$EVENT]--> $NEXT_STATE"
|
||||
|
||||
EXECUTED=()
|
||||
|
||||
if [[ -n "$ACTION" && "$ACTION" != "null" ]]; then
|
||||
log "Выполняется действие: $ACTION"
|
||||
|
||||
# Подстановка переменных вида ${{ var }} из контекста + env
|
||||
ACTION_EXP=$(echo "$ACTION" | CONTEXT="$CONTEXT_JSON" jq -r '
|
||||
reduce paths(scalars) as $p (.;
|
||||
setpath($p; getpath($p) |
|
||||
if type == "string" then
|
||||
gsub("\\$\\{\\{[ \\t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \\t]*\\}\\}" ;
|
||||
(capture("\\$\\{\\{[ \\t]*(?<v>[a-zA-Z_][a-zA-Z0-9_]*)[ \\t]*\\}\\}") |.v) as $var |
|
||||
($ENV.CONTEXT | fromjson | .[$var] // env[$var] // "")
|
||||
)
|
||||
else .
|
||||
end
|
||||
)
|
||||
)
|
||||
')
|
||||
|
||||
debug "Расширенная команда: $ACTION_EXP"
|
||||
eval "$ACTION_EXP"
|
||||
EXECUTED+=("$ACTION")
|
||||
fi
|
||||
|
||||
# Выводим outputs
|
||||
echo "next_state=$NEXT_STATE" >> "$GITHUB_OUTPUT"
|
||||
echo "executed_actions=$(jq -c --null-input '$EXECUTED')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
log "Новое состояние: $NEXT_STATE"
|
||||
[[ ${#EXECUTED[@]} -gt 0 ]] && log "Выполнено действий: ${#EXECUTED[@]}"
|
||||
Reference in new issue
Block a user