Files
2025-11-28 11:30:28 +05:00

85 lines
2.8 KiB
Bash

#!/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[@]}"